Formatting the C/C++ files
This commit is contained in:
@@ -6,23 +6,23 @@
|
||||
*/
|
||||
#include "Model_Config.h"
|
||||
#ifdef POW_PD
|
||||
#include <fusbpd.h>
|
||||
#include <pd.h>
|
||||
#include "BSP.h"
|
||||
#include "I2CBB.hpp"
|
||||
#include "fusb302b.h"
|
||||
#include "int_n.h"
|
||||
#include "policy_engine.h"
|
||||
#include "protocol_rx.h"
|
||||
#include "protocol_tx.h"
|
||||
#include "int_n.h"
|
||||
#include <fusbpd.h>
|
||||
#include <pd.h>
|
||||
|
||||
void fusb302_start_processing() {
|
||||
/* Initialize the FUSB302B */
|
||||
if (fusb_setup()) {
|
||||
PolicyEngine::init();
|
||||
ProtocolTransmit::init();
|
||||
ProtocolReceive::init();
|
||||
InterruptHandler::init();
|
||||
}
|
||||
/* Initialize the FUSB302B */
|
||||
if (fusb_setup()) {
|
||||
PolicyEngine::init();
|
||||
ProtocolTransmit::init();
|
||||
ProtocolReceive::init();
|
||||
InterruptHandler::init();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -16,65 +16,63 @@
|
||||
*/
|
||||
|
||||
#include "int_n.h"
|
||||
#include "fusbpd.h"
|
||||
#include <pd.h>
|
||||
#include "BSP.h"
|
||||
#include "fusb302b.h"
|
||||
#include "protocol_rx.h"
|
||||
#include "protocol_tx.h"
|
||||
#include "fusbpd.h"
|
||||
#include "policy_engine.h"
|
||||
#include "protocol_rx.h"
|
||||
#include "protocol_tx.h"
|
||||
#include "task.h"
|
||||
#include "BSP.h"
|
||||
#include <pd.h>
|
||||
|
||||
osThreadId InterruptHandler::TaskHandle = NULL;
|
||||
uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize];
|
||||
osThreadId InterruptHandler::TaskHandle = NULL;
|
||||
uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize];
|
||||
osStaticThreadDef_t InterruptHandler::TaskControlBlock;
|
||||
|
||||
void InterruptHandler::init() {
|
||||
osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, TaskBuffer, &TaskControlBlock);
|
||||
TaskHandle = osThreadCreate(osThread(intTask), NULL);
|
||||
osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, TaskBuffer, &TaskControlBlock);
|
||||
TaskHandle = osThreadCreate(osThread(intTask), NULL);
|
||||
}
|
||||
|
||||
void InterruptHandler::Thread(const void *arg) {
|
||||
(void) arg;
|
||||
union fusb_status status;
|
||||
while (true) {
|
||||
/* If the INT_N line is low */
|
||||
if (xTaskNotifyWait(0x00, 0x0F, NULL, PolicyEngine::setupCompleteOrTimedOut() ? 1000 : 10) == pdPASS) {
|
||||
//delay slightly so we catch the crc with better timing
|
||||
osDelay(1);
|
||||
}
|
||||
/* Read the FUSB302B status and interrupt registers */
|
||||
fusb_get_status(&status);
|
||||
/* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX
|
||||
* thread */
|
||||
if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) {
|
||||
ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT);
|
||||
}
|
||||
if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) {
|
||||
ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
|
||||
}
|
||||
(void)arg;
|
||||
union fusb_status status;
|
||||
while (true) {
|
||||
/* If the INT_N line is low */
|
||||
if (xTaskNotifyWait(0x00, 0x0F, NULL, PolicyEngine::setupCompleteOrTimedOut() ? 1000 : 10) == pdPASS) {
|
||||
// delay slightly so we catch the crc with better timing
|
||||
osDelay(1);
|
||||
}
|
||||
/* Read the FUSB302B status and interrupt registers */
|
||||
fusb_get_status(&status);
|
||||
/* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX
|
||||
* thread */
|
||||
if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) {
|
||||
ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT);
|
||||
}
|
||||
if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) {
|
||||
ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
|
||||
}
|
||||
|
||||
/* If the I_GCRCSENT flag is set, tell the Protocol RX thread */
|
||||
//This means a message was recieved with a good CRC
|
||||
if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) {
|
||||
ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT);
|
||||
}
|
||||
/* If the I_GCRCSENT flag is set, tell the Protocol RX thread */
|
||||
// This means a message was recieved with a good CRC
|
||||
if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) {
|
||||
ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT);
|
||||
}
|
||||
|
||||
/* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy
|
||||
* Engine thread */
|
||||
if ((status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP) && (status.status1 & FUSB_STATUS1_OVRTEMP)) {
|
||||
PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP);
|
||||
}
|
||||
}
|
||||
/* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy
|
||||
* Engine thread */
|
||||
if ((status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP) && (status.status1 & FUSB_STATUS1_OVRTEMP)) {
|
||||
PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
void InterruptHandler::irqCallback() {
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
if (TaskHandle != NULL) {
|
||||
BaseType_t taskWoke = pdFALSE;
|
||||
xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke);
|
||||
portYIELD_FROM_ISR(taskWoke);
|
||||
}
|
||||
}
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
if (TaskHandle != NULL) {
|
||||
BaseType_t taskWoke = pdFALSE;
|
||||
xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke);
|
||||
portYIELD_FROM_ISR(taskWoke);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,9 @@
|
||||
* Created on: 14 Jun 2020
|
||||
* Author: Ralim
|
||||
*/
|
||||
#include "BSP_PD.h"
|
||||
#include "pd.h"
|
||||
#include "policy_engine.h"
|
||||
#include "BSP_PD.h"
|
||||
/* The current draw when the output is disabled */
|
||||
#define DPM_MIN_CURRENT PD_MA2PDI(50)
|
||||
/*
|
||||
@@ -16,212 +16,178 @@
|
||||
* If there is no such PDO, returns -1 instead.
|
||||
*/
|
||||
static int8_t dpm_get_range_fixed_pdo_index(const union pd_msg *caps) {
|
||||
/* Get the number of PDOs */
|
||||
uint8_t numobj = PD_NUMOBJ_GET(caps);
|
||||
/* Get the number of PDOs */
|
||||
uint8_t numobj = PD_NUMOBJ_GET(caps);
|
||||
|
||||
/* Get ready to iterate over the PDOs */
|
||||
int8_t i;
|
||||
int8_t step;
|
||||
i = numobj - 1;
|
||||
step = -1;
|
||||
uint16_t current = 100; // in centiamps
|
||||
uint16_t voltagemin = 8000;
|
||||
uint16_t voltagemax = 10000;
|
||||
/* Look at the PDOs to see if one falls in our voltage range. */
|
||||
while (0 <= i && i < numobj) {
|
||||
/* If we have a fixed PDO, its V is within our range, and its I is at
|
||||
* least our desired I */
|
||||
uint16_t v = PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]);
|
||||
if ((caps->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
|
||||
if ( PD_PDO_SRC_FIXED_CURRENT_GET(caps->obj[i]) >= current) {
|
||||
if (v >= PD_MV2PDV(voltagemin) && v <= PD_MV2PDV(voltagemax)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
i += step;
|
||||
}
|
||||
return -1;
|
||||
/* Get ready to iterate over the PDOs */
|
||||
int8_t i;
|
||||
int8_t step;
|
||||
i = numobj - 1;
|
||||
step = -1;
|
||||
uint16_t current = 100; // in centiamps
|
||||
uint16_t voltagemin = 8000;
|
||||
uint16_t voltagemax = 10000;
|
||||
/* Look at the PDOs to see if one falls in our voltage range. */
|
||||
while (0 <= i && i < numobj) {
|
||||
/* If we have a fixed PDO, its V is within our range, and its I is at
|
||||
* least our desired I */
|
||||
uint16_t v = PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]);
|
||||
if ((caps->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
|
||||
if (PD_PDO_SRC_FIXED_CURRENT_GET(caps->obj[i]) >= current) {
|
||||
if (v >= PD_MV2PDV(voltagemin) && v <= PD_MV2PDV(voltagemax)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
i += step;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
bool PolicyEngine::pdbs_dpm_evaluate_capability(
|
||||
const union pd_msg *capabilities, union pd_msg *request) {
|
||||
bool PolicyEngine::pdbs_dpm_evaluate_capability(const union pd_msg *capabilities, union pd_msg *request) {
|
||||
|
||||
/* Get the number of PDOs */
|
||||
uint8_t numobj = PD_NUMOBJ_GET(capabilities);
|
||||
/* Get the number of PDOs */
|
||||
uint8_t numobj = PD_NUMOBJ_GET(capabilities);
|
||||
|
||||
/* Get whether or not the power supply is constrained */
|
||||
_unconstrained_power =
|
||||
capabilities->obj[0] & PD_PDO_SRC_FIXED_UNCONSTRAINED;
|
||||
/* Get whether or not the power supply is constrained */
|
||||
_unconstrained_power = capabilities->obj[0] & PD_PDO_SRC_FIXED_UNCONSTRAINED;
|
||||
|
||||
/* Make sure we have configuration */
|
||||
/* Look at the PDOs to see if one matches our desires */
|
||||
//Look against USB_PD_Desired_Levels to select in order of preference
|
||||
for (uint8_t desiredLevel = 0; desiredLevel < USB_PD_Desired_Levels_Len;
|
||||
desiredLevel++) {
|
||||
for (uint8_t i = 0; i < numobj; i++) {
|
||||
/* If we have a fixed PDO, its V equals our desired V, and its I is
|
||||
* at least our desired I */
|
||||
if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
|
||||
//This is a fixed PDO entry
|
||||
int voltage = PD_PDV2MV(
|
||||
PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities->obj[i]));
|
||||
int current = PD_PDO_SRC_FIXED_CURRENT_GET(
|
||||
capabilities->obj[i]);
|
||||
uint16_t desiredVoltage = USB_PD_Desired_Levels[(desiredLevel
|
||||
* 2) + 0];
|
||||
uint16_t desiredminCurrent = USB_PD_Desired_Levels[(desiredLevel
|
||||
* 2) + 1];
|
||||
//As pd stores current in 10mA increments, divide by 10
|
||||
desiredminCurrent /= 10;
|
||||
if (voltage == desiredVoltage) {
|
||||
if (current >= desiredminCurrent) {
|
||||
/* We got what we wanted, so build a request for that */
|
||||
request->hdr = hdr_template | PD_MSGTYPE_REQUEST
|
||||
| PD_NUMOBJ(1);
|
||||
/* Make sure we have configuration */
|
||||
/* Look at the PDOs to see if one matches our desires */
|
||||
// Look against USB_PD_Desired_Levels to select in order of preference
|
||||
for (uint8_t desiredLevel = 0; desiredLevel < USB_PD_Desired_Levels_Len; desiredLevel++) {
|
||||
for (uint8_t i = 0; i < numobj; i++) {
|
||||
/* If we have a fixed PDO, its V equals our desired V, and its I is
|
||||
* at least our desired I */
|
||||
if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
|
||||
// This is a fixed PDO entry
|
||||
int voltage = PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities->obj[i]));
|
||||
int current = PD_PDO_SRC_FIXED_CURRENT_GET(capabilities->obj[i]);
|
||||
uint16_t desiredVoltage = USB_PD_Desired_Levels[(desiredLevel * 2) + 0];
|
||||
uint16_t desiredminCurrent = USB_PD_Desired_Levels[(desiredLevel * 2) + 1];
|
||||
// As pd stores current in 10mA increments, divide by 10
|
||||
desiredminCurrent /= 10;
|
||||
if (voltage == desiredVoltage) {
|
||||
if (current >= desiredminCurrent) {
|
||||
/* We got what we wanted, so build a request for that */
|
||||
request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1);
|
||||
|
||||
/* GiveBack disabled */
|
||||
request->obj[0] =
|
||||
PD_RDO_FV_MAX_CURRENT_SET(
|
||||
current) | PD_RDO_FV_CURRENT_SET(current)
|
||||
| PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
|
||||
//We support usb comms (ish)
|
||||
request->obj[0] |= PD_RDO_USB_COMMS;
|
||||
/* GiveBack disabled */
|
||||
request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(current) | PD_RDO_FV_CURRENT_SET(current) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
|
||||
// We support usb comms (ish)
|
||||
request->obj[0] |= PD_RDO_USB_COMMS;
|
||||
|
||||
/* Update requested voltage */
|
||||
_requested_voltage = voltage;
|
||||
/* Update requested voltage */
|
||||
_requested_voltage = voltage;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/* Nothing matched (or no configuration), so get 5 V at low current */
|
||||
request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1);
|
||||
request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_FV_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(1);
|
||||
/* If the output is enabled and we got here, it must be a capability
|
||||
* mismatch. */
|
||||
if (pdNegotiationComplete) {
|
||||
request->obj[0] |= PD_RDO_CAP_MISMATCH;
|
||||
}
|
||||
request->obj[0] |= PD_RDO_USB_COMMS;
|
||||
|
||||
/* Nothing matched (or no configuration), so get 5 V at low current */
|
||||
request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1);
|
||||
request->obj[0] =
|
||||
PD_RDO_FV_MAX_CURRENT_SET(
|
||||
DPM_MIN_CURRENT) | PD_RDO_FV_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_NO_USB_SUSPEND
|
||||
| PD_RDO_OBJPOS_SET(1);
|
||||
/* If the output is enabled and we got here, it must be a capability
|
||||
* mismatch. */
|
||||
if (pdNegotiationComplete) {
|
||||
request->obj[0] |= PD_RDO_CAP_MISMATCH;
|
||||
}
|
||||
request->obj[0] |= PD_RDO_USB_COMMS;
|
||||
/* Update requested voltage */
|
||||
_requested_voltage = 5000;
|
||||
|
||||
/* Update requested voltage */
|
||||
_requested_voltage = 5000;
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) {
|
||||
/* Keep track of how many PDOs we've added */
|
||||
int numobj = 0;
|
||||
/* Keep track of how many PDOs we've added */
|
||||
int numobj = 0;
|
||||
|
||||
/* If we have no configuration or want something other than 5 V, add a PDO
|
||||
* for vSafe5V */
|
||||
/* Minimum current, 5 V, and higher capability. */
|
||||
cap->obj[numobj++] =
|
||||
PD_PDO_TYPE_FIXED
|
||||
| PD_PDO_SNK_FIXED_VOLTAGE_SET(
|
||||
PD_MV2PDV(5000)) | PD_PDO_SNK_FIXED_CURRENT_SET(DPM_MIN_CURRENT);
|
||||
/* If we have no configuration or want something other than 5 V, add a PDO
|
||||
* for vSafe5V */
|
||||
/* Minimum current, 5 V, and higher capability. */
|
||||
cap->obj[numobj++] = PD_PDO_TYPE_FIXED | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_MV2PDV(5000)) | PD_PDO_SNK_FIXED_CURRENT_SET(DPM_MIN_CURRENT);
|
||||
|
||||
/* Get the current we want */
|
||||
uint16_t current = USB_PD_Desired_Levels[1] / 10; // In centi-amps
|
||||
uint16_t voltage = USB_PD_Desired_Levels[0]; // in mv
|
||||
/* Add a PDO for the desired power. */
|
||||
cap->obj[numobj++] = PD_PDO_TYPE_FIXED
|
||||
| PD_PDO_SNK_FIXED_VOLTAGE_SET(
|
||||
PD_MV2PDV(voltage)) | PD_PDO_SNK_FIXED_CURRENT_SET(current);
|
||||
/* Get the current we want */
|
||||
uint16_t current = USB_PD_Desired_Levels[1] / 10; // In centi-amps
|
||||
uint16_t voltage = USB_PD_Desired_Levels[0]; // in mv
|
||||
/* Add a PDO for the desired power. */
|
||||
cap->obj[numobj++] = PD_PDO_TYPE_FIXED | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_MV2PDV(voltage)) | PD_PDO_SNK_FIXED_CURRENT_SET(current);
|
||||
|
||||
/* Get the PDO from the voltage range */
|
||||
int8_t i = dpm_get_range_fixed_pdo_index(cap);
|
||||
/* Get the PDO from the voltage range */
|
||||
int8_t i = dpm_get_range_fixed_pdo_index(cap);
|
||||
|
||||
/* If it's vSafe5V, set our vSafe5V's current to what we want */
|
||||
if (i == 0) {
|
||||
cap->obj[0] &= ~PD_PDO_SNK_FIXED_CURRENT;
|
||||
cap->obj[0] |= PD_PDO_SNK_FIXED_CURRENT_SET(current);
|
||||
} else {
|
||||
/* If we want more than 5 V, set the Higher Capability flag */
|
||||
if (PD_MV2PDV(voltage) != PD_MV2PDV(5000)) {
|
||||
cap->obj[0] |= PD_PDO_SNK_FIXED_HIGHER_CAP;
|
||||
}
|
||||
/* If it's vSafe5V, set our vSafe5V's current to what we want */
|
||||
if (i == 0) {
|
||||
cap->obj[0] &= ~PD_PDO_SNK_FIXED_CURRENT;
|
||||
cap->obj[0] |= PD_PDO_SNK_FIXED_CURRENT_SET(current);
|
||||
} else {
|
||||
/* If we want more than 5 V, set the Higher Capability flag */
|
||||
if (PD_MV2PDV(voltage) != PD_MV2PDV(5000)) {
|
||||
cap->obj[0] |= PD_PDO_SNK_FIXED_HIGHER_CAP;
|
||||
}
|
||||
|
||||
/* If the range PDO is a different voltage than the preferred
|
||||
* voltage, add it to the array. */
|
||||
if (i
|
||||
> 0&& PD_PDO_SRC_FIXED_VOLTAGE_GET(cap->obj[i]) != PD_MV2PDV(voltage)) {
|
||||
cap->obj[numobj++] =
|
||||
PD_PDO_TYPE_FIXED
|
||||
| PD_PDO_SNK_FIXED_VOLTAGE_SET(
|
||||
PD_PDO_SRC_FIXED_VOLTAGE_GET(cap->obj[i])) | PD_PDO_SNK_FIXED_CURRENT_SET(
|
||||
PD_PDO_SRC_FIXED_CURRENT_GET(cap->obj[i]));
|
||||
}
|
||||
/* If the range PDO is a different voltage than the preferred
|
||||
* voltage, add it to the array. */
|
||||
if (i > 0 && PD_PDO_SRC_FIXED_VOLTAGE_GET(cap->obj[i]) != PD_MV2PDV(voltage)) {
|
||||
cap->obj[numobj++] = PD_PDO_TYPE_FIXED | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_PDO_SRC_FIXED_VOLTAGE_GET(cap->obj[i])) | PD_PDO_SNK_FIXED_CURRENT_SET(PD_PDO_SRC_FIXED_CURRENT_GET(cap->obj[i]));
|
||||
}
|
||||
|
||||
/* If we have three PDOs at this point, make sure the last two are
|
||||
* sorted by voltage. */
|
||||
if (numobj == 3
|
||||
&& (cap->obj[1] & PD_PDO_SNK_FIXED_VOLTAGE)
|
||||
> (cap->obj[2] & PD_PDO_SNK_FIXED_VOLTAGE)) {
|
||||
cap->obj[1] ^= cap->obj[2];
|
||||
cap->obj[2] ^= cap->obj[1];
|
||||
cap->obj[1] ^= cap->obj[2];
|
||||
}
|
||||
}
|
||||
/* If we have three PDOs at this point, make sure the last two are
|
||||
* sorted by voltage. */
|
||||
if (numobj == 3 && (cap->obj[1] & PD_PDO_SNK_FIXED_VOLTAGE) > (cap->obj[2] & PD_PDO_SNK_FIXED_VOLTAGE)) {
|
||||
cap->obj[1] ^= cap->obj[2];
|
||||
cap->obj[2] ^= cap->obj[1];
|
||||
cap->obj[1] ^= cap->obj[2];
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the unconstrained power flag. */
|
||||
if (_unconstrained_power) {
|
||||
cap->obj[0] |= PD_PDO_SNK_FIXED_UNCONSTRAINED;
|
||||
}
|
||||
/* Set the USB communications capable flag. */
|
||||
cap->obj[0] |= PD_PDO_SNK_FIXED_USB_COMMS;
|
||||
/* Set the unconstrained power flag. */
|
||||
if (_unconstrained_power) {
|
||||
cap->obj[0] |= PD_PDO_SNK_FIXED_UNCONSTRAINED;
|
||||
}
|
||||
/* Set the USB communications capable flag. */
|
||||
cap->obj[0] |= PD_PDO_SNK_FIXED_USB_COMMS;
|
||||
|
||||
/* Set the Sink_Capabilities message header */
|
||||
cap->hdr = hdr_template | PD_MSGTYPE_SINK_CAPABILITIES | PD_NUMOBJ(numobj);
|
||||
/* Set the Sink_Capabilities message header */
|
||||
cap->hdr = hdr_template | PD_MSGTYPE_SINK_CAPABILITIES | PD_NUMOBJ(numobj);
|
||||
}
|
||||
|
||||
bool PolicyEngine::pdbs_dpm_evaluate_typec_current(
|
||||
enum fusb_typec_current tcc) {
|
||||
(void) tcc;
|
||||
//This is for evaluating 5V static current advertised by resistors
|
||||
/* We don't control the voltage anymore; it will always be 5 V. */
|
||||
current_voltage_mv = _requested_voltage = 5000;
|
||||
//For the soldering iron we accept this as a fallback, but it sucks
|
||||
pdNegotiationComplete = false;
|
||||
return true;
|
||||
bool PolicyEngine::pdbs_dpm_evaluate_typec_current(enum fusb_typec_current tcc) {
|
||||
(void)tcc;
|
||||
// This is for evaluating 5V static current advertised by resistors
|
||||
/* We don't control the voltage anymore; it will always be 5 V. */
|
||||
current_voltage_mv = _requested_voltage = 5000;
|
||||
// For the soldering iron we accept this as a fallback, but it sucks
|
||||
pdNegotiationComplete = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PolicyEngine::pdbs_dpm_transition_default() {
|
||||
/* Cast the dpm_data to the right type */
|
||||
/* Cast the dpm_data to the right type */
|
||||
|
||||
/* Pretend we requested 5 V */
|
||||
current_voltage_mv = 5000;
|
||||
/* Turn the output off */
|
||||
pdNegotiationComplete = false;
|
||||
/* Pretend we requested 5 V */
|
||||
current_voltage_mv = 5000;
|
||||
/* Turn the output off */
|
||||
pdNegotiationComplete = false;
|
||||
}
|
||||
|
||||
void PolicyEngine::pdbs_dpm_transition_requested() {
|
||||
/* Cast the dpm_data to the right type */
|
||||
pdNegotiationComplete = true;
|
||||
/* Cast the dpm_data to the right type */
|
||||
pdNegotiationComplete = true;
|
||||
}
|
||||
|
||||
void PolicyEngine::handleMessage(union pd_msg *msg) {
|
||||
xQueueSend(messagesWaiting, msg, 100);
|
||||
}
|
||||
void PolicyEngine::handleMessage(union pd_msg *msg) { xQueueSend(messagesWaiting, msg, 100); }
|
||||
|
||||
bool PolicyEngine::messageWaiting() {
|
||||
return uxQueueMessagesWaiting(messagesWaiting) > 0;
|
||||
}
|
||||
bool PolicyEngine::messageWaiting() { return uxQueueMessagesWaiting(messagesWaiting) > 0; }
|
||||
|
||||
bool PolicyEngine::readMessage() {
|
||||
return xQueueReceive(messagesWaiting, &tempMessage, 0) == pdTRUE;
|
||||
}
|
||||
bool PolicyEngine::readMessage() { return xQueueReceive(messagesWaiting, &tempMessage, 0) == pdTRUE; }
|
||||
|
||||
void PolicyEngine::pdbs_dpm_transition_typec() {
|
||||
//This means PD failed, so we either have a dump 5V only type C or a QC charger
|
||||
//For now; treat this as failed neg
|
||||
pdNegotiationComplete = false;
|
||||
// This means PD failed, so we either have a dump 5V only type C or a QC charger
|
||||
// For now; treat this as failed neg
|
||||
pdNegotiationComplete = false;
|
||||
}
|
||||
|
||||
@@ -17,173 +17,167 @@
|
||||
|
||||
#include "protocol_rx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "string.h"
|
||||
#include <pd.h>
|
||||
#include "fusb302b.h"
|
||||
#include "policy_engine.h"
|
||||
#include "protocol_tx.h"
|
||||
#include "fusb302b.h"
|
||||
osThreadId ProtocolReceive::TaskHandle = NULL;
|
||||
EventGroupHandle_t ProtocolReceive::xEventGroupHandle = NULL;
|
||||
StaticEventGroup_t ProtocolReceive::xCreatedEventGroup;
|
||||
uint32_t ProtocolReceive::TaskBuffer[ProtocolReceive::TaskStackSize];
|
||||
#include "string.h"
|
||||
#include <pd.h>
|
||||
#include <stdlib.h>
|
||||
osThreadId ProtocolReceive::TaskHandle = NULL;
|
||||
EventGroupHandle_t ProtocolReceive::xEventGroupHandle = NULL;
|
||||
StaticEventGroup_t ProtocolReceive::xCreatedEventGroup;
|
||||
uint32_t ProtocolReceive::TaskBuffer[ProtocolReceive::TaskStackSize];
|
||||
osStaticThreadDef_t ProtocolReceive::TaskControlBlock;
|
||||
union pd_msg ProtocolReceive::tempMessage;
|
||||
uint8_t ProtocolReceive::_rx_messageid;
|
||||
uint8_t ProtocolReceive::_tx_messageidcounter;
|
||||
union pd_msg ProtocolReceive::tempMessage;
|
||||
uint8_t ProtocolReceive::_rx_messageid;
|
||||
uint8_t ProtocolReceive::_tx_messageidcounter;
|
||||
/*
|
||||
* PRL_Rx_Wait_for_PHY_Message state
|
||||
*/
|
||||
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() {
|
||||
/* Wait for an event */
|
||||
_rx_messageid = 0;
|
||||
eventmask_t evt = waitForEvent(
|
||||
PDB_EVT_PRLRX_RESET | PDB_EVT_PRLRX_I_GCRCSENT | PDB_EVT_PRLRX_I_RXPEND);
|
||||
/* Wait for an event */
|
||||
_rx_messageid = 0;
|
||||
eventmask_t evt = waitForEvent(PDB_EVT_PRLRX_RESET | PDB_EVT_PRLRX_I_GCRCSENT | PDB_EVT_PRLRX_I_RXPEND);
|
||||
|
||||
/* If we got a reset event, reset */
|
||||
if (evt & PDB_EVT_PRLRX_RESET) {
|
||||
waitForEvent(PDB_EVT_PRLRX_RESET, 0);
|
||||
return PRLRxWaitPHY;
|
||||
}
|
||||
/* If we got an I_GCRCSENT event, read the message and decide what to do */
|
||||
if (evt & PDB_EVT_PRLRX_I_GCRCSENT) {
|
||||
/* Get a buffer to read the message into. Guaranteed to not fail
|
||||
* because we have a big enough pool and are careful. */
|
||||
union pd_msg *_rx_message = &tempMessage;
|
||||
memset(&tempMessage, 0, sizeof(tempMessage));
|
||||
/* Read the message */
|
||||
fusb_read_message(_rx_message);
|
||||
/* If it's a Soft_Reset, go to the soft reset state */
|
||||
if (PD_MSGTYPE_GET(_rx_message) == PD_MSGTYPE_SOFT_RESET
|
||||
&& PD_NUMOBJ_GET(_rx_message) == 0) {
|
||||
return PRLRxReset;
|
||||
} else {
|
||||
/* Otherwise, check the message ID */
|
||||
return PRLRxCheckMessageID;
|
||||
}
|
||||
} else if (evt & PDB_EVT_PRLRX_I_RXPEND) {
|
||||
//There is an RX message pending that is not a Good CRC
|
||||
union pd_msg *_rx_message = &tempMessage;
|
||||
/* Read the message */
|
||||
fusb_read_message(_rx_message);
|
||||
return PRLRxWaitPHY;
|
||||
}
|
||||
/* If we got a reset event, reset */
|
||||
if (evt & PDB_EVT_PRLRX_RESET) {
|
||||
waitForEvent(PDB_EVT_PRLRX_RESET, 0);
|
||||
return PRLRxWaitPHY;
|
||||
}
|
||||
/* If we got an I_GCRCSENT event, read the message and decide what to do */
|
||||
if (evt & PDB_EVT_PRLRX_I_GCRCSENT) {
|
||||
/* Get a buffer to read the message into. Guaranteed to not fail
|
||||
* because we have a big enough pool and are careful. */
|
||||
union pd_msg *_rx_message = &tempMessage;
|
||||
memset(&tempMessage, 0, sizeof(tempMessage));
|
||||
/* Read the message */
|
||||
fusb_read_message(_rx_message);
|
||||
/* If it's a Soft_Reset, go to the soft reset state */
|
||||
if (PD_MSGTYPE_GET(_rx_message) == PD_MSGTYPE_SOFT_RESET && PD_NUMOBJ_GET(_rx_message) == 0) {
|
||||
return PRLRxReset;
|
||||
} else {
|
||||
/* Otherwise, check the message ID */
|
||||
return PRLRxCheckMessageID;
|
||||
}
|
||||
} else if (evt & PDB_EVT_PRLRX_I_RXPEND) {
|
||||
// There is an RX message pending that is not a Good CRC
|
||||
union pd_msg *_rx_message = &tempMessage;
|
||||
/* Read the message */
|
||||
fusb_read_message(_rx_message);
|
||||
return PRLRxWaitPHY;
|
||||
}
|
||||
|
||||
return PRLRxWaitPHY;
|
||||
return PRLRxWaitPHY;
|
||||
}
|
||||
|
||||
/*
|
||||
* PRL_Rx_Layer_Reset_for_Receive state
|
||||
*/
|
||||
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_reset() {
|
||||
/* Reset MessageIDCounter */
|
||||
_tx_messageidcounter = 0;
|
||||
/* Reset MessageIDCounter */
|
||||
_tx_messageidcounter = 0;
|
||||
|
||||
/* Clear stored MessageID */
|
||||
_rx_messageid = -1;
|
||||
/* Clear stored MessageID */
|
||||
_rx_messageid = -1;
|
||||
|
||||
/* TX transitions to its reset state */
|
||||
ProtocolTransmit::notify(
|
||||
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET);
|
||||
taskYIELD();
|
||||
/* TX transitions to its reset state */
|
||||
ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET);
|
||||
taskYIELD();
|
||||
|
||||
/* If we got a RESET signal, reset the machine */
|
||||
if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) != 0) {
|
||||
return PRLRxWaitPHY;
|
||||
}
|
||||
/* If we got a RESET signal, reset the machine */
|
||||
if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) != 0) {
|
||||
return PRLRxWaitPHY;
|
||||
}
|
||||
|
||||
/* Go to the Check_MessageID state */
|
||||
return PRLRxCheckMessageID;
|
||||
/* Go to the Check_MessageID state */
|
||||
return PRLRxCheckMessageID;
|
||||
}
|
||||
volatile uint32_t rxCounter = 0;
|
||||
/*
|
||||
* PRL_Rx_Check_MessageID state
|
||||
*/
|
||||
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid() {
|
||||
/* If we got a RESET signal, reset the machine */
|
||||
// if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) == PDB_EVT_PRLRX_RESET) {
|
||||
// return PRLRxWaitPHY;
|
||||
// }
|
||||
/* If the message has the stored ID, we've seen this message before. Free
|
||||
* it and don't pass it to the policy engine. */
|
||||
/* If we got a RESET signal, reset the machine */
|
||||
// if (waitForEvent(PDB_EVT_PRLRX_RESET, 0) == PDB_EVT_PRLRX_RESET) {
|
||||
// return PRLRxWaitPHY;
|
||||
// }
|
||||
/* If the message has the stored ID, we've seen this message before. Free
|
||||
* it and don't pass it to the policy engine. */
|
||||
|
||||
/* Otherwise, there's either no stored ID or this message has an ID we
|
||||
* haven't just seen. Transition to the Store_MessageID state. */
|
||||
// if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) {
|
||||
// return PRLRxWaitPHY;
|
||||
// } else
|
||||
{
|
||||
rxCounter++;
|
||||
return PRLRxStoreMessageID;
|
||||
}
|
||||
/* Otherwise, there's either no stored ID or this message has an ID we
|
||||
* haven't just seen. Transition to the Store_MessageID state. */
|
||||
// if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) {
|
||||
// return PRLRxWaitPHY;
|
||||
// } else
|
||||
{
|
||||
rxCounter++;
|
||||
return PRLRxStoreMessageID;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PRL_Rx_Store_MessageID state
|
||||
*/
|
||||
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid() {
|
||||
/* Tell ProtocolTX to discard the message being transmitted */
|
||||
/* Tell ProtocolTX to discard the message being transmitted */
|
||||
|
||||
ProtocolTransmit::notify(
|
||||
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_DISCARD);
|
||||
ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_DISCARD);
|
||||
|
||||
/* Update the stored MessageID */
|
||||
_rx_messageid = PD_MESSAGEID_GET(&tempMessage);
|
||||
/* Update the stored MessageID */
|
||||
_rx_messageid = PD_MESSAGEID_GET(&tempMessage);
|
||||
|
||||
/* Pass the message to the policy engine. */
|
||||
/* Pass the message to the policy engine. */
|
||||
|
||||
PolicyEngine::handleMessage(&tempMessage);
|
||||
PolicyEngine::notify(PDB_EVT_PE_MSG_RX);
|
||||
taskYIELD();
|
||||
/* Don't check if we got a RESET because we'd do nothing different. */
|
||||
PolicyEngine::handleMessage(&tempMessage);
|
||||
PolicyEngine::notify(PDB_EVT_PE_MSG_RX);
|
||||
taskYIELD();
|
||||
/* Don't check if we got a RESET because we'd do nothing different. */
|
||||
|
||||
return PRLRxWaitPHY;
|
||||
return PRLRxWaitPHY;
|
||||
}
|
||||
|
||||
void ProtocolReceive::init() {
|
||||
osThreadStaticDef(protRX, thread, PDB_PRIO_PRL, 0, TaskStackSize,
|
||||
TaskBuffer, &TaskControlBlock);
|
||||
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
|
||||
TaskHandle = osThreadCreate(osThread(protRX), NULL);
|
||||
osThreadStaticDef(protRX, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, &TaskControlBlock);
|
||||
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
|
||||
TaskHandle = osThreadCreate(osThread(protRX), NULL);
|
||||
}
|
||||
|
||||
void ProtocolReceive::thread(const void *args) {
|
||||
(void) args;
|
||||
ProtocolReceive::protocol_rx_state state = PRLRxWaitPHY;
|
||||
(void)args;
|
||||
ProtocolReceive::protocol_rx_state state = PRLRxWaitPHY;
|
||||
|
||||
while (true) {
|
||||
switch (state) {
|
||||
case PRLRxWaitPHY:
|
||||
state = protocol_rx_wait_phy();
|
||||
break;
|
||||
case PRLRxReset:
|
||||
state = protocol_rx_reset();
|
||||
break;
|
||||
case PRLRxCheckMessageID:
|
||||
state = protocol_rx_check_messageid();
|
||||
break;
|
||||
case PRLRxStoreMessageID:
|
||||
state = protocol_rx_store_messageid();
|
||||
break;
|
||||
default:
|
||||
/* This is an error. It really shouldn't happen. We might
|
||||
* want to handle it anyway, though. */
|
||||
state = PRLRxWaitPHY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
switch (state) {
|
||||
case PRLRxWaitPHY:
|
||||
state = protocol_rx_wait_phy();
|
||||
break;
|
||||
case PRLRxReset:
|
||||
state = protocol_rx_reset();
|
||||
break;
|
||||
case PRLRxCheckMessageID:
|
||||
state = protocol_rx_check_messageid();
|
||||
break;
|
||||
case PRLRxStoreMessageID:
|
||||
state = protocol_rx_store_messageid();
|
||||
break;
|
||||
default:
|
||||
/* This is an error. It really shouldn't happen. We might
|
||||
* want to handle it anyway, though. */
|
||||
state = PRLRxWaitPHY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolReceive::notify(uint32_t notification) {
|
||||
if (xEventGroupHandle != NULL) {
|
||||
xEventGroupSetBits(xEventGroupHandle, notification);
|
||||
}
|
||||
if (xEventGroupHandle != NULL) {
|
||||
xEventGroupSetBits(xEventGroupHandle, notification);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ProtocolReceive::waitForEvent(uint32_t mask, TickType_t ticksToWait) {
|
||||
if (xEventGroupHandle != NULL) {
|
||||
return xEventGroupWaitBits(xEventGroupHandle, mask, mask,
|
||||
pdFALSE, ticksToWait);
|
||||
}
|
||||
return 0;
|
||||
if (xEventGroupHandle != NULL) {
|
||||
return xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE, ticksToWait);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,283 +16,268 @@
|
||||
*/
|
||||
|
||||
#include "protocol_tx.h"
|
||||
#include <pd.h>
|
||||
#include "policy_engine.h"
|
||||
#include "protocol_rx.h"
|
||||
#include "fusb302b.h"
|
||||
#include "fusbpd.h"
|
||||
#include "policy_engine.h"
|
||||
#include "protocol_rx.h"
|
||||
#include <pd.h>
|
||||
|
||||
osThreadId ProtocolTransmit::TaskHandle = NULL;
|
||||
uint32_t ProtocolTransmit::TaskBuffer[ProtocolTransmit::TaskStackSize];
|
||||
osThreadId ProtocolTransmit::TaskHandle = NULL;
|
||||
uint32_t ProtocolTransmit::TaskBuffer[ProtocolTransmit::TaskStackSize];
|
||||
osStaticThreadDef_t ProtocolTransmit::TaskControlBlock;
|
||||
StaticQueue_t ProtocolTransmit::xStaticQueue;
|
||||
bool ProtocolTransmit::messageSending = false;
|
||||
uint8_t ProtocolTransmit::ucQueueStorageArea[PDB_MSG_POOL_SIZE
|
||||
* sizeof(union pd_msg)];
|
||||
QueueHandle_t ProtocolTransmit::messagesWaiting = NULL;
|
||||
uint8_t ProtocolTransmit::_tx_messageidcounter;
|
||||
union pd_msg ProtocolTransmit::temp_msg;
|
||||
EventGroupHandle_t ProtocolTransmit::xEventGroupHandle = NULL;
|
||||
StaticEventGroup_t ProtocolTransmit::xCreatedEventGroup;
|
||||
StaticQueue_t ProtocolTransmit::xStaticQueue;
|
||||
bool ProtocolTransmit::messageSending = false;
|
||||
uint8_t ProtocolTransmit::ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)];
|
||||
QueueHandle_t ProtocolTransmit::messagesWaiting = NULL;
|
||||
uint8_t ProtocolTransmit::_tx_messageidcounter;
|
||||
union pd_msg ProtocolTransmit::temp_msg;
|
||||
EventGroupHandle_t ProtocolTransmit::xEventGroupHandle = NULL;
|
||||
StaticEventGroup_t ProtocolTransmit::xCreatedEventGroup;
|
||||
/*
|
||||
* PRL_Tx_PHY_Layer_Reset state
|
||||
*/
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_phy_reset() {
|
||||
/* Reset the PHY */
|
||||
fusb_reset();
|
||||
/* Reset the PHY */
|
||||
fusb_reset();
|
||||
|
||||
/* If a message was pending when we got here, tell the policy engine that
|
||||
* we failed to send it */
|
||||
if (messagePending()) {
|
||||
/* Tell the policy engine that we failed */
|
||||
PolicyEngine::notify( PDB_EVT_PE_TX_ERR);
|
||||
/* Finish failing to send the message */
|
||||
while (messagePending()) {
|
||||
getMessage(); //Discard
|
||||
}
|
||||
}
|
||||
/* If a message was pending when we got here, tell the policy engine that
|
||||
* we failed to send it */
|
||||
if (messagePending()) {
|
||||
/* Tell the policy engine that we failed */
|
||||
PolicyEngine::notify(PDB_EVT_PE_TX_ERR);
|
||||
/* Finish failing to send the message */
|
||||
while (messagePending()) {
|
||||
getMessage(); // Discard
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for a message request */
|
||||
return PRLTxWaitMessage;
|
||||
/* Wait for a message request */
|
||||
return PRLTxWaitMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* PRL_Tx_Wait_for_Message_Request state
|
||||
*/
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message() {
|
||||
/* Wait for an event */
|
||||
ProtocolTransmit::Notifications evt = waitForEvent(
|
||||
(uint32_t) Notifications::PDB_EVT_PRLTX_RESET
|
||||
| (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD
|
||||
| (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX);
|
||||
/* Wait for an event */
|
||||
ProtocolTransmit::Notifications evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PRLTX_RESET | (uint32_t)Notifications::PDB_EVT_PRLTX_DISCARD | (uint32_t)Notifications::PDB_EVT_PRLTX_MSG_TX);
|
||||
|
||||
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) {
|
||||
return PRLTxPHYReset;
|
||||
}
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_RESET) {
|
||||
return PRLTxPHYReset;
|
||||
}
|
||||
|
||||
/* If the policy engine is trying to send a message */
|
||||
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX) {
|
||||
/* Get the message */
|
||||
getMessage();
|
||||
/* If the policy engine is trying to send a message */
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_MSG_TX) {
|
||||
/* Get the message */
|
||||
getMessage();
|
||||
|
||||
/* If it's a Soft_Reset, reset the TX layer first */
|
||||
if (PD_MSGTYPE_GET(&temp_msg) == PD_MSGTYPE_SOFT_RESET
|
||||
&& PD_NUMOBJ_GET(&(temp_msg)) == 0) {
|
||||
return PRLTxReset;
|
||||
/* Otherwise, just send the message */
|
||||
} else {
|
||||
return PRLTxConstructMessage;
|
||||
}
|
||||
}
|
||||
/* If it's a Soft_Reset, reset the TX layer first */
|
||||
if (PD_MSGTYPE_GET(&temp_msg) == PD_MSGTYPE_SOFT_RESET && PD_NUMOBJ_GET(&(temp_msg)) == 0) {
|
||||
return PRLTxReset;
|
||||
/* Otherwise, just send the message */
|
||||
} else {
|
||||
return PRLTxConstructMessage;
|
||||
}
|
||||
}
|
||||
|
||||
/* Silence the compiler warning */
|
||||
return PRLTxWaitMessage;
|
||||
/* Silence the compiler warning */
|
||||
return PRLTxWaitMessage;
|
||||
}
|
||||
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() {
|
||||
/* Clear MessageIDCounter */
|
||||
_tx_messageidcounter = 0;
|
||||
/* Clear MessageIDCounter */
|
||||
_tx_messageidcounter = 0;
|
||||
|
||||
/* Tell the Protocol RX thread to reset */
|
||||
ProtocolReceive::notify( PDB_EVT_PRLRX_RESET);
|
||||
taskYIELD();
|
||||
/* Tell the Protocol RX thread to reset */
|
||||
ProtocolReceive::notify(PDB_EVT_PRLRX_RESET);
|
||||
taskYIELD();
|
||||
|
||||
return PRLTxConstructMessage;
|
||||
return PRLTxConstructMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* PRL_Tx_Construct_Message state
|
||||
*/
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_message() {
|
||||
/* Set the correct MessageID in the message */
|
||||
temp_msg.hdr &= ~PD_HDR_MESSAGEID;
|
||||
temp_msg.hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT;
|
||||
/* Set the correct MessageID in the message */
|
||||
temp_msg.hdr &= ~PD_HDR_MESSAGEID;
|
||||
temp_msg.hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT;
|
||||
|
||||
/* PD 3.0 collision avoidance */
|
||||
// if (PolicyEngine::isPD3_0()) {
|
||||
// /* If we're starting an AMS, wait for permission to transmit */
|
||||
// evt = waitForEvent((uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS,
|
||||
// 0);
|
||||
// if ((uint32_t) evt
|
||||
// & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) {
|
||||
// while (fusb_get_typec_current() != fusb_sink_tx_ok) {
|
||||
// osDelay(1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
messageSending = true;
|
||||
/* Send the message to the PHY */
|
||||
fusb_send_message(&temp_msg);
|
||||
/* PD 3.0 collision avoidance */
|
||||
// if (PolicyEngine::isPD3_0()) {
|
||||
// /* If we're starting an AMS, wait for permission to transmit */
|
||||
// evt = waitForEvent((uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS,
|
||||
// 0);
|
||||
// if ((uint32_t) evt
|
||||
// & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) {
|
||||
// while (fusb_get_typec_current() != fusb_sink_tx_ok) {
|
||||
// osDelay(1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
messageSending = true;
|
||||
/* Send the message to the PHY */
|
||||
fusb_send_message(&temp_msg);
|
||||
|
||||
return PRLTxWaitResponse;
|
||||
return PRLTxWaitResponse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PRL_Tx_Wait_for_PHY_Response state
|
||||
*/
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_response() {
|
||||
/* Wait for an event. There is no need to run CRCReceiveTimer, since the
|
||||
* FUSB302B handles that as part of its retry mechanism. */
|
||||
ProtocolTransmit::Notifications evt = waitForEvent(
|
||||
(uint32_t) Notifications::PDB_EVT_PRLTX_RESET
|
||||
| (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD
|
||||
| (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT
|
||||
| (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
|
||||
/* Wait for an event. There is no need to run CRCReceiveTimer, since the
|
||||
* FUSB302B handles that as part of its retry mechanism. */
|
||||
ProtocolTransmit::Notifications evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PRLTX_RESET | (uint32_t)Notifications::PDB_EVT_PRLTX_DISCARD | (uint32_t)Notifications::PDB_EVT_PRLTX_I_TXSENT
|
||||
| (uint32_t)Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
|
||||
|
||||
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) {
|
||||
return PRLTxPHYReset;
|
||||
}
|
||||
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) {
|
||||
return PRLTxDiscardMessage;
|
||||
}
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_RESET) {
|
||||
return PRLTxPHYReset;
|
||||
}
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_DISCARD) {
|
||||
return PRLTxDiscardMessage;
|
||||
}
|
||||
|
||||
/* If the message was sent successfully */
|
||||
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_TXSENT) {
|
||||
return PRLTxMatchMessageID;
|
||||
}
|
||||
/* If the message failed to be sent */
|
||||
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL) {
|
||||
return PRLTxTransmissionError;
|
||||
}
|
||||
/* If the message was sent successfully */
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_I_TXSENT) {
|
||||
return PRLTxMatchMessageID;
|
||||
}
|
||||
/* If the message failed to be sent */
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_I_RETRYFAIL) {
|
||||
return PRLTxTransmissionError;
|
||||
}
|
||||
|
||||
/* Silence the compiler warning */
|
||||
return PRLTxDiscardMessage;
|
||||
/* Silence the compiler warning */
|
||||
return PRLTxDiscardMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* PRL_Tx_Match_MessageID state
|
||||
*/
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_match_messageid() {
|
||||
union pd_msg goodcrc;
|
||||
union pd_msg goodcrc;
|
||||
|
||||
/* Read the GoodCRC */
|
||||
fusb_read_message(&goodcrc);
|
||||
/* Read the GoodCRC */
|
||||
fusb_read_message(&goodcrc);
|
||||
|
||||
/* Check that the message is correct */
|
||||
if (PD_MSGTYPE_GET(&goodcrc) == PD_MSGTYPE_GOODCRC
|
||||
&& PD_NUMOBJ_GET(&goodcrc) == 0
|
||||
&& PD_MESSAGEID_GET(&goodcrc) == _tx_messageidcounter) {
|
||||
return PRLTxMessageSent;
|
||||
} else {
|
||||
return PRLTxTransmissionError;
|
||||
}
|
||||
/* Check that the message is correct */
|
||||
if (PD_MSGTYPE_GET(&goodcrc) == PD_MSGTYPE_GOODCRC && PD_NUMOBJ_GET(&goodcrc) == 0 && PD_MESSAGEID_GET(&goodcrc) == _tx_messageidcounter) {
|
||||
return PRLTxMessageSent;
|
||||
} else {
|
||||
return PRLTxTransmissionError;
|
||||
}
|
||||
}
|
||||
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_transmission_error() {
|
||||
/* Increment MessageIDCounter */
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
/* Increment MessageIDCounter */
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
|
||||
/* Tell the policy engine that we failed */
|
||||
PolicyEngine::notify( PDB_EVT_PE_TX_ERR);
|
||||
/* Tell the policy engine that we failed */
|
||||
PolicyEngine::notify(PDB_EVT_PE_TX_ERR);
|
||||
|
||||
return PRLTxWaitMessage;
|
||||
return PRLTxWaitMessage;
|
||||
}
|
||||
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_message_sent() {
|
||||
messageSending = false;
|
||||
/* Increment MessageIDCounter */
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
messageSending = false;
|
||||
/* Increment MessageIDCounter */
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
|
||||
/* Tell the policy engine that we succeeded */
|
||||
PolicyEngine::notify( PDB_EVT_PE_TX_DONE);
|
||||
/* Tell the policy engine that we succeeded */
|
||||
PolicyEngine::notify(PDB_EVT_PE_TX_DONE);
|
||||
|
||||
return PRLTxWaitMessage;
|
||||
return PRLTxWaitMessage;
|
||||
}
|
||||
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_discard_message() {
|
||||
/* If we were working on sending a message, increment MessageIDCounter */
|
||||
if (messageSending) {
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
/* If we were working on sending a message, increment MessageIDCounter */
|
||||
if (messageSending) {
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
|
||||
return PRLTxPHYReset;
|
||||
} else {
|
||||
return PRLTxWaitMessage;
|
||||
}
|
||||
return PRLTxPHYReset;
|
||||
} else {
|
||||
return PRLTxWaitMessage;
|
||||
}
|
||||
}
|
||||
void ProtocolTransmit::thread(const void *args) {
|
||||
(void) args;
|
||||
ProtocolTransmit::protocol_tx_state state = PRLTxPHYReset;
|
||||
(void)args;
|
||||
ProtocolTransmit::protocol_tx_state state = PRLTxPHYReset;
|
||||
|
||||
//Init the incoming message queue
|
||||
// Init the incoming message queue
|
||||
|
||||
while (true) {
|
||||
switch (state) {
|
||||
case PRLTxPHYReset:
|
||||
state = protocol_tx_phy_reset();
|
||||
break;
|
||||
case PRLTxWaitMessage:
|
||||
state = protocol_tx_wait_message();
|
||||
break;
|
||||
case PRLTxReset:
|
||||
state = protocol_tx_reset();
|
||||
break;
|
||||
case PRLTxConstructMessage:
|
||||
state = protocol_tx_construct_message();
|
||||
break;
|
||||
case PRLTxWaitResponse:
|
||||
state = protocol_tx_wait_response();
|
||||
break;
|
||||
case PRLTxMatchMessageID:
|
||||
state = protocol_tx_match_messageid();
|
||||
break;
|
||||
case PRLTxTransmissionError:
|
||||
state = protocol_tx_transmission_error();
|
||||
break;
|
||||
case PRLTxMessageSent:
|
||||
state = protocol_tx_message_sent();
|
||||
break;
|
||||
case PRLTxDiscardMessage:
|
||||
state = protocol_tx_discard_message();
|
||||
break;
|
||||
default:
|
||||
state = PRLTxPHYReset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
switch (state) {
|
||||
case PRLTxPHYReset:
|
||||
state = protocol_tx_phy_reset();
|
||||
break;
|
||||
case PRLTxWaitMessage:
|
||||
state = protocol_tx_wait_message();
|
||||
break;
|
||||
case PRLTxReset:
|
||||
state = protocol_tx_reset();
|
||||
break;
|
||||
case PRLTxConstructMessage:
|
||||
state = protocol_tx_construct_message();
|
||||
break;
|
||||
case PRLTxWaitResponse:
|
||||
state = protocol_tx_wait_response();
|
||||
break;
|
||||
case PRLTxMatchMessageID:
|
||||
state = protocol_tx_match_messageid();
|
||||
break;
|
||||
case PRLTxTransmissionError:
|
||||
state = protocol_tx_transmission_error();
|
||||
break;
|
||||
case PRLTxMessageSent:
|
||||
state = protocol_tx_message_sent();
|
||||
break;
|
||||
case PRLTxDiscardMessage:
|
||||
state = protocol_tx_discard_message();
|
||||
break;
|
||||
default:
|
||||
state = PRLTxPHYReset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolTransmit::notify(ProtocolTransmit::Notifications notification) {
|
||||
if (xEventGroupHandle != NULL) {
|
||||
xEventGroupSetBits(xEventGroupHandle, (uint32_t) notification);
|
||||
}
|
||||
if (xEventGroupHandle != NULL) {
|
||||
xEventGroupSetBits(xEventGroupHandle, (uint32_t)notification);
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolTransmit::init() {
|
||||
messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE,
|
||||
sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue);
|
||||
messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue);
|
||||
|
||||
osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, TaskStackSize,
|
||||
TaskBuffer, &TaskControlBlock);
|
||||
TaskHandle = osThreadCreate(osThread(pd_txTask), NULL);
|
||||
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
|
||||
osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, &TaskControlBlock);
|
||||
TaskHandle = osThreadCreate(osThread(pd_txTask), NULL);
|
||||
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
|
||||
}
|
||||
|
||||
void ProtocolTransmit::pushMessage(union pd_msg *msg) {
|
||||
if (messagesWaiting) {
|
||||
xQueueSend(messagesWaiting, msg, 100);
|
||||
}
|
||||
if (messagesWaiting) {
|
||||
xQueueSend(messagesWaiting, msg, 100);
|
||||
}
|
||||
}
|
||||
|
||||
bool ProtocolTransmit::messagePending() {
|
||||
if (messagesWaiting) {
|
||||
return uxQueueMessagesWaiting(messagesWaiting) > 0;
|
||||
}
|
||||
return false;
|
||||
if (messagesWaiting) {
|
||||
return uxQueueMessagesWaiting(messagesWaiting) > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProtocolTransmit::getMessage() {
|
||||
//Loads the pending message into the buffer
|
||||
if (messagesWaiting) {
|
||||
xQueueReceive(messagesWaiting, &temp_msg, 1);
|
||||
}
|
||||
// Loads the pending message into the buffer
|
||||
if (messagesWaiting) {
|
||||
xQueueReceive(messagesWaiting, &temp_msg, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask,
|
||||
TickType_t ticksToWait) {
|
||||
if (xEventGroupHandle) {
|
||||
return (Notifications) xEventGroupWaitBits(xEventGroupHandle, mask,
|
||||
mask,
|
||||
pdFALSE, ticksToWait);
|
||||
}
|
||||
return (Notifications)0;
|
||||
ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask, TickType_t ticksToWait) {
|
||||
if (xEventGroupHandle) {
|
||||
return (Notifications)xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE, ticksToWait);
|
||||
}
|
||||
return (Notifications)0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user