Reworking USB-PD stack to remove a thread
This commit is contained in:
@@ -23,135 +23,148 @@
|
||||
#include <pd.h>
|
||||
void fusb_send_message(const union pd_msg *msg) {
|
||||
|
||||
/* Token sequences for the FUSB302B */
|
||||
static uint8_t sop_seq[5] = {FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP2, FUSB_FIFO_TX_PACKSYM};
|
||||
static const uint8_t eop_seq[4] = {FUSB_FIFO_TX_JAM_CRC, FUSB_FIFO_TX_EOP, FUSB_FIFO_TX_TXOFF, FUSB_FIFO_TX_TXON};
|
||||
/* Token sequences for the FUSB302B */
|
||||
static uint8_t sop_seq[5] = { FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP1,
|
||||
FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP2, FUSB_FIFO_TX_PACKSYM };
|
||||
static const uint8_t eop_seq[4] = { FUSB_FIFO_TX_JAM_CRC, FUSB_FIFO_TX_EOP,
|
||||
FUSB_FIFO_TX_TXOFF, FUSB_FIFO_TX_TXON };
|
||||
|
||||
/* Take the I2C2 mutex now so there can't be a race condition on sop_seq */
|
||||
/* Get the length of the message: a two-octet header plus NUMOBJ four-octet
|
||||
* data objects */
|
||||
uint8_t msg_len = 2 + 4 * PD_NUMOBJ_GET(msg);
|
||||
/* Take the I2C2 mutex now so there can't be a race condition on sop_seq */
|
||||
/* Get the length of the message: a two-octet header plus NUMOBJ four-octet
|
||||
* data objects */
|
||||
uint8_t msg_len = 2 + 4 * PD_NUMOBJ_GET(msg);
|
||||
|
||||
/* Set the number of bytes to be transmitted in the packet */
|
||||
sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len;
|
||||
/* Set the number of bytes to be transmitted in the packet */
|
||||
sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len;
|
||||
|
||||
/* Write all three parts of the message to the TX FIFO */
|
||||
fusb_write_buf(FUSB_FIFOS, 5, sop_seq);
|
||||
fusb_write_buf(FUSB_FIFOS, msg_len, msg->bytes);
|
||||
fusb_write_buf(FUSB_FIFOS, 4, eop_seq);
|
||||
/* Write all three parts of the message to the TX FIFO */
|
||||
fusb_write_buf(FUSB_FIFOS, 5, sop_seq);
|
||||
fusb_write_buf(FUSB_FIFOS, msg_len, msg->bytes);
|
||||
fusb_write_buf(FUSB_FIFOS, 4, eop_seq);
|
||||
}
|
||||
|
||||
bool fusb_rx_pending() {
|
||||
return (fusb_read_byte( FUSB_STATUS1) & FUSB_STATUS1_RX_EMPTY)
|
||||
!= FUSB_STATUS1_RX_EMPTY;
|
||||
}
|
||||
|
||||
uint8_t fusb_read_message(union pd_msg *msg) {
|
||||
|
||||
static uint8_t garbage[4];
|
||||
uint8_t numobj;
|
||||
static uint8_t garbage[4];
|
||||
uint8_t numobj;
|
||||
|
||||
// Read the header. If its not a SOP we dont actually want it at all
|
||||
// But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck
|
||||
fusb_read_byte(FUSB_FIFOS);
|
||||
/* Read the message header into msg */
|
||||
fusb_read_buf(FUSB_FIFOS, 2, msg->bytes);
|
||||
/* Get the number of data objects */
|
||||
numobj = PD_NUMOBJ_GET(msg);
|
||||
/* If there is at least one data object, read the data objects */
|
||||
if (numobj > 0) {
|
||||
fusb_read_buf(FUSB_FIFOS, numobj * 4, msg->bytes + 2);
|
||||
}
|
||||
/* Throw the CRC32 in the garbage, since the PHY already checked it. */
|
||||
fusb_read_buf(FUSB_FIFOS, 4, garbage);
|
||||
// Read the header. If its not a SOP we dont actually want it at all
|
||||
// But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck
|
||||
if ((fusb_read_byte( FUSB_FIFOS) & FUSB_FIFO_RX_TOKEN_BITS)
|
||||
!= FUSB_FIFO_RX_SOP) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
// fusb_read_byte(FUSB_FIFOS);
|
||||
/* Read the message header into msg */
|
||||
fusb_read_buf(FUSB_FIFOS, 2, msg->bytes);
|
||||
/* Get the number of data objects */
|
||||
numobj = PD_NUMOBJ_GET(msg);
|
||||
/* If there is at least one data object, read the data objects */
|
||||
if (numobj > 0) {
|
||||
fusb_read_buf(FUSB_FIFOS, numobj * 4, msg->bytes + 2);
|
||||
}
|
||||
/* Throw the CRC32 in the garbage, since the PHY already checked it. */
|
||||
fusb_read_buf(FUSB_FIFOS, 4, garbage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fusb_send_hardrst() {
|
||||
|
||||
/* Send a hard reset */
|
||||
fusb_write_byte(FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET);
|
||||
/* Send a hard reset */
|
||||
fusb_write_byte(FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET);
|
||||
}
|
||||
|
||||
bool fusb_setup() {
|
||||
/* Fully reset the FUSB302B */
|
||||
fusb_write_byte(FUSB_RESET, FUSB_RESET_SW_RES);
|
||||
vTaskDelay(TICKS_10MS);
|
||||
uint8_t tries = 0;
|
||||
while (!fusb_read_id()) {
|
||||
vTaskDelay(TICKS_10MS);
|
||||
tries++;
|
||||
if (tries > 5) {
|
||||
return false; // Welp :(
|
||||
}
|
||||
}
|
||||
/* Fully reset the FUSB302B */
|
||||
fusb_write_byte(FUSB_RESET, FUSB_RESET_SW_RES);
|
||||
vTaskDelay(TICKS_10MS);
|
||||
uint8_t tries = 0;
|
||||
while (!fusb_read_id()) {
|
||||
vTaskDelay(TICKS_10MS);
|
||||
tries++;
|
||||
if (tries > 5) {
|
||||
return false; // Welp :(
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn on all power */
|
||||
fusb_write_byte(FUSB_POWER, 0x0F);
|
||||
/* Turn on all power */
|
||||
fusb_write_byte(FUSB_POWER, 0x0F);
|
||||
|
||||
/* Set interrupt masks */
|
||||
// Setting to 0 so interrupts are allowed
|
||||
fusb_write_byte(FUSB_MASK1, 0x00);
|
||||
fusb_write_byte(FUSB_MASKA, 0x00);
|
||||
fusb_write_byte(FUSB_MASKB, 0x00);
|
||||
fusb_write_byte(FUSB_CONTROL0, 0b11 << 2);
|
||||
/* Set interrupt masks */
|
||||
// Setting to 0 so interrupts are allowed
|
||||
fusb_write_byte(FUSB_MASK1, 0x00);
|
||||
fusb_write_byte(FUSB_MASKA, 0x00);
|
||||
fusb_write_byte(FUSB_MASKB, 0x00);
|
||||
fusb_write_byte(FUSB_CONTROL0, 0b11 << 2);
|
||||
|
||||
/* Enable automatic retransmission */
|
||||
fusb_write_byte(FUSB_CONTROL3, 0x07);
|
||||
// set defaults
|
||||
fusb_write_byte(FUSB_CONTROL2, 0x00);
|
||||
/* Flush the RX buffer */
|
||||
fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
|
||||
/* Enable automatic retransmission */
|
||||
fusb_write_byte(FUSB_CONTROL3, 0x07);
|
||||
// set defaults
|
||||
fusb_write_byte(FUSB_CONTROL2, 0x00);
|
||||
/* Flush the RX buffer */
|
||||
fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
|
||||
|
||||
/* Measure CC1 */
|
||||
fusb_write_byte(FUSB_SWITCHES0, 0x07);
|
||||
vTaskDelay(TICKS_10MS);
|
||||
uint8_t cc1 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
|
||||
/* Measure CC1 */
|
||||
fusb_write_byte(FUSB_SWITCHES0, 0x07);
|
||||
vTaskDelay(TICKS_10MS);
|
||||
uint8_t cc1 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
|
||||
|
||||
/* Measure CC2 */
|
||||
fusb_write_byte(FUSB_SWITCHES0, 0x0B);
|
||||
vTaskDelay(TICKS_10MS);
|
||||
uint8_t cc2 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
|
||||
/* Measure CC2 */
|
||||
fusb_write_byte(FUSB_SWITCHES0, 0x0B);
|
||||
vTaskDelay(TICKS_10MS);
|
||||
uint8_t cc2 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
|
||||
|
||||
/* Select the correct CC line for BMC signaling; also enable AUTO_CRC */
|
||||
if (cc1 > cc2) {
|
||||
fusb_write_byte(FUSB_SWITCHES1, 0x25); // TX_CC1|AUTO_CRC|SPECREV0
|
||||
fusb_write_byte(FUSB_SWITCHES0, 0x07); // PWDN1|PWDN2|MEAS_CC1
|
||||
} else {
|
||||
fusb_write_byte(FUSB_SWITCHES1, 0x26); // TX_CC2|AUTO_CRC|SPECREV0
|
||||
fusb_write_byte(FUSB_SWITCHES0, 0x0B); // PWDN1|PWDN2|MEAS_CC2
|
||||
}
|
||||
/* Select the correct CC line for BMC signaling; also enable AUTO_CRC */
|
||||
if (cc1 > cc2) {
|
||||
fusb_write_byte(FUSB_SWITCHES1, 0x25); // TX_CC1|AUTO_CRC|SPECREV0
|
||||
fusb_write_byte(FUSB_SWITCHES0, 0x07); // PWDN1|PWDN2|MEAS_CC1
|
||||
} else {
|
||||
fusb_write_byte(FUSB_SWITCHES1, 0x26); // TX_CC2|AUTO_CRC|SPECREV0
|
||||
fusb_write_byte(FUSB_SWITCHES0, 0x0B); // PWDN1|PWDN2|MEAS_CC2
|
||||
}
|
||||
|
||||
fusb_reset();
|
||||
setupFUSBIRQ();
|
||||
return true;
|
||||
fusb_reset();
|
||||
setupFUSBIRQ();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fusb_get_status(union fusb_status *status) {
|
||||
|
||||
/* Read the interrupt and status flags into status */
|
||||
return fusb_read_buf(FUSB_STATUS0A, 7, status->bytes);
|
||||
/* Read the interrupt and status flags into status */
|
||||
return fusb_read_buf(FUSB_STATUS0A, 7, status->bytes);
|
||||
}
|
||||
|
||||
enum fusb_typec_current fusb_get_typec_current() {
|
||||
|
||||
/* Read the BC_LVL into a variable */
|
||||
enum fusb_typec_current bc_lvl = (enum fusb_typec_current)(fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL);
|
||||
/* Read the BC_LVL into a variable */
|
||||
enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte(
|
||||
FUSB_STATUS0) & FUSB_STATUS0_BC_LVL);
|
||||
|
||||
return bc_lvl;
|
||||
return bc_lvl;
|
||||
}
|
||||
|
||||
void fusb_reset() {
|
||||
|
||||
/* Flush the TX buffer */
|
||||
fusb_write_byte(FUSB_CONTROL0, 0x44);
|
||||
/* Flush the RX buffer */
|
||||
fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
|
||||
/* Reset the PD logic */
|
||||
// fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET);
|
||||
/* Flush the TX buffer */
|
||||
fusb_write_byte(FUSB_CONTROL0, 0x44);
|
||||
/* Flush the RX buffer */
|
||||
fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
|
||||
/* Reset the PD logic */
|
||||
fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET);
|
||||
}
|
||||
|
||||
bool fusb_read_id() {
|
||||
// Return true if read of the revision ID is sane
|
||||
uint8_t version = 0;
|
||||
fusb_read_buf(FUSB_DEVICE_ID, 1, &version);
|
||||
if (version == 0 || version == 0xFF)
|
||||
return false;
|
||||
return true;
|
||||
// Return true if read of the revision ID is sane
|
||||
uint8_t version = 0;
|
||||
fusb_read_buf(FUSB_DEVICE_ID, 1, &version);
|
||||
if (version == 0 || version == 0xFF)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ union fusb_status {
|
||||
* Send a USB Power Delivery message to the FUSB302B
|
||||
*/
|
||||
void fusb_send_message(const union pd_msg *msg);
|
||||
|
||||
bool fusb_rx_pending();
|
||||
/*
|
||||
* Read a USB Power Delivery message from the FUSB302B
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "int_n.h"
|
||||
#include "policy_engine.h"
|
||||
|
||||
#include "protocol_tx.h"
|
||||
#include <fusbpd.h>
|
||||
#include <pd.h>
|
||||
|
||||
@@ -20,7 +19,6 @@ void fusb302_start_processing() {
|
||||
/* Initialize the FUSB302B */
|
||||
if (fusb_setup()) {
|
||||
PolicyEngine::init();
|
||||
ProtocolTransmit::init();
|
||||
InterruptHandler::init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,79 +22,92 @@
|
||||
#include "fusbpd.h"
|
||||
#include "policy_engine.h"
|
||||
|
||||
#include "protocol_tx.h"
|
||||
#include "task.h"
|
||||
#include <pd.h>
|
||||
#include <string.h>
|
||||
|
||||
volatile osThreadId InterruptHandler::TaskHandle = NULL;
|
||||
uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize];
|
||||
uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize];
|
||||
osStaticThreadDef_t InterruptHandler::TaskControlBlock;
|
||||
union pd_msg InterruptHandler::tempMessage;
|
||||
union pd_msg InterruptHandler::tempMessage;
|
||||
|
||||
void InterruptHandler::init() {
|
||||
TaskHandle = NULL;
|
||||
osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, TaskBuffer, &TaskControlBlock);
|
||||
TaskHandle = osThreadCreate(osThread(intTask), NULL);
|
||||
TaskHandle = NULL;
|
||||
osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize,
|
||||
TaskBuffer, &TaskControlBlock);
|
||||
TaskHandle = osThreadCreate(osThread(intTask), NULL);
|
||||
}
|
||||
|
||||
volatile uint32_t msgCounter = 0;
|
||||
volatile uint32_t msgCounter1 = 0;
|
||||
void InterruptHandler::readPendingMessage() {
|
||||
/* Get a buffer to read the message into. Guaranteed to not fail
|
||||
* because we have a big enough pool and are careful. */
|
||||
memset(&tempMessage, 0, sizeof(tempMessage));
|
||||
/* Read the message */
|
||||
fusb_read_message(&tempMessage);
|
||||
/* If it's a Soft_Reset, go to the soft reset state */
|
||||
if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET && PD_NUMOBJ_GET(&tempMessage) == 0) {
|
||||
/* TX transitions to its reset state */
|
||||
ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET);
|
||||
} else {
|
||||
/* Tell ProtocolTX to discard the message being transmitted */
|
||||
ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_DISCARD);
|
||||
memset(&tempMessage, 0, sizeof(tempMessage));
|
||||
while (fusb_rx_pending()) {
|
||||
msgCounter++;
|
||||
/* Read the message */
|
||||
if (fusb_read_message(&tempMessage) == 0) {
|
||||
/* If it's a Soft_Reset, go to the soft reset state */
|
||||
if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET
|
||||
&& PD_NUMOBJ_GET(&tempMessage) == 0) {
|
||||
/* TX transitions to its reset state */
|
||||
PolicyEngine::notify(
|
||||
PolicyEngine::Notifications::PDB_EVT_PE_RESET);
|
||||
} else {
|
||||
/* Tell PolicyEngine to discard the message being transmitted */
|
||||
PolicyEngine::notify(
|
||||
PolicyEngine::Notifications::PDB_EVT_TX_DISCARD);
|
||||
|
||||
/* Pass the message to the policy engine. */
|
||||
PolicyEngine::handleMessage(&tempMessage);
|
||||
}
|
||||
/* Pass the message to the policy engine. */
|
||||
PolicyEngine::handleMessage(&tempMessage);
|
||||
}
|
||||
} else {
|
||||
msgCounter1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InterruptHandler::Thread(const void *arg) {
|
||||
(void)arg;
|
||||
union fusb_status status;
|
||||
for (;;) {
|
||||
// If the irq is low continue, otherwise wait for irq or timeout
|
||||
if (!getFUS302IRQLow()) {
|
||||
xTaskNotifyWait(0x00, 0x0F, NULL, TICKS_SECOND * 30);
|
||||
}
|
||||
/* Read the FUSB302B status and interrupt registers */
|
||||
if (fusb_get_status(&status)) {
|
||||
(void) arg;
|
||||
union fusb_status status;
|
||||
for (;;) {
|
||||
// If the irq is low continue, otherwise wait for irq or timeout
|
||||
if (!getFUS302IRQLow()) {
|
||||
xTaskNotifyWait(0x00, 0x0F, NULL, TICKS_SECOND * 30);
|
||||
}
|
||||
/* Read the FUSB302B status and interrupt registers */
|
||||
if (fusb_get_status(&status)) {
|
||||
|
||||
/* If the I_GCRCSENT flag is set, tell the Protocol RX thread */
|
||||
// This means a message was received with a good CRC
|
||||
if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) {
|
||||
readPendingMessage();
|
||||
}
|
||||
/* If the I_GCRCSENT flag is set, tell the Protocol RX thread */
|
||||
// This means a message was received with a good CRC
|
||||
if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) {
|
||||
readPendingMessage();
|
||||
}
|
||||
|
||||
/* 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_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX
|
||||
* thread */
|
||||
if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) {
|
||||
PolicyEngine::notify(
|
||||
PolicyEngine::Notifications::PDB_EVT_TX_I_TXSENT);
|
||||
}
|
||||
if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) {
|
||||
PolicyEngine::notify(
|
||||
PolicyEngine::Notifications::PDB_EVT_TX_I_RETRYFAIL);
|
||||
}
|
||||
|
||||
/* 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(PolicyEngine::Notifications::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(
|
||||
PolicyEngine::Notifications::PDB_EVT_PE_I_OVRTEMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void InterruptHandler::irqCallback() {
|
||||
if (TaskHandle != NULL) {
|
||||
BaseType_t taskWoke = pdFALSE;
|
||||
xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke);
|
||||
portYIELD_FROM_ISR(taskWoke);
|
||||
}
|
||||
if (TaskHandle != NULL) {
|
||||
BaseType_t taskWoke = pdFALSE;
|
||||
xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits,
|
||||
&taskWoke);
|
||||
portYIELD_FROM_ISR(taskWoke);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "Defines.h"
|
||||
#include "fusb302b.h"
|
||||
#include "int_n.h"
|
||||
#include "protocol_tx.h"
|
||||
#include <pd.h>
|
||||
#include <stdbool.h>
|
||||
bool PolicyEngine::pdNegotiationComplete;
|
||||
@@ -43,8 +42,9 @@ uint8_t PolicyEngine::ucQueueStorageArea[PDB_MSG_POOL_
|
||||
QueueHandle_t PolicyEngine::messagesWaiting = NULL;
|
||||
EventGroupHandle_t PolicyEngine::xEventGroupHandle = NULL;
|
||||
StaticEventGroup_t PolicyEngine::xCreatedEventGroup;
|
||||
bool PolicyEngine::PPSTimerEnabled = false;
|
||||
TickType_t PolicyEngine::PPSTimeLastEvent = 0;
|
||||
bool PolicyEngine::PPSTimerEnabled = false;
|
||||
TickType_t PolicyEngine::PPSTimeLastEvent = 0;
|
||||
uint8_t PolicyEngine::_tx_messageidcounter = 0;
|
||||
void PolicyEngine::init() {
|
||||
messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue);
|
||||
// Create static thread at PDB_PRIO_PE priority
|
||||
@@ -238,9 +238,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() {
|
||||
|
||||
/* Transmit the request */
|
||||
waitForEvent((uint32_t)Notifications::PDB_EVT_PE_ALL, 0); // clear pending
|
||||
ProtocolTransmit::pushMessage(&_last_dpm_request);
|
||||
// Send indication that there is a message pending
|
||||
EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
|
||||
EventBits_t evt = pushMessage(&_last_dpm_request);
|
||||
/* If we got reset signaling, transition to default */
|
||||
if (evt & (uint32_t)Notifications::PDB_EVT_PE_RESET || evt == 0) {
|
||||
return PESinkTransitionDefault;
|
||||
@@ -410,8 +408,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_get_source_cap() {
|
||||
/* Make a Get_Source_Cap message */
|
||||
get_source_cap->hdr = hdr_template | PD_MSGTYPE_GET_SOURCE_CAP | PD_NUMOBJ(0);
|
||||
/* Transmit the Get_Source_Cap */
|
||||
ProtocolTransmit::pushMessage(get_source_cap);
|
||||
EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
|
||||
EventBits_t evt = pushMessage(get_source_cap);
|
||||
/* Free the sent message */
|
||||
/* If we got reset signaling, transition to default */
|
||||
if (evt & (uint32_t)Notifications::PDB_EVT_PE_RESET) {
|
||||
@@ -432,8 +429,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_give_sink_cap() {
|
||||
pdbs_dpm_get_sink_capability(snk_cap);
|
||||
|
||||
/* Transmit our capabilities */
|
||||
ProtocolTransmit::pushMessage(snk_cap);
|
||||
EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
|
||||
EventBits_t evt = pushMessage(snk_cap);
|
||||
|
||||
/* Free the Sink_Capabilities message */
|
||||
|
||||
@@ -485,8 +481,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_soft_reset() {
|
||||
/* Make an Accept message */
|
||||
accept.hdr = hdr_template | PD_MSGTYPE_ACCEPT | PD_NUMOBJ(0);
|
||||
/* Transmit the Accept */
|
||||
ProtocolTransmit::pushMessage(&accept);
|
||||
EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
|
||||
EventBits_t evt = pushMessage(&accept);
|
||||
/* Free the sent message */
|
||||
|
||||
/* If we got reset signaling, transition to default */
|
||||
@@ -510,8 +505,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_soft_reset() {
|
||||
/* Make a Soft_Reset message */
|
||||
softrst->hdr = hdr_template | PD_MSGTYPE_SOFT_RESET | PD_NUMOBJ(0);
|
||||
/* Transmit the soft reset */
|
||||
ProtocolTransmit::pushMessage(softrst);
|
||||
EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
|
||||
EventBits_t evt = pushMessage(softrst);
|
||||
/* If we got reset signaling, transition to default */
|
||||
if (evt & (uint32_t)Notifications::PDB_EVT_PE_RESET) {
|
||||
return PESinkTransitionDefault;
|
||||
@@ -564,8 +558,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_not_supported() {
|
||||
}
|
||||
|
||||
/* Transmit the message */
|
||||
ProtocolTransmit::pushMessage(&tempMessage);
|
||||
EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
|
||||
EventBits_t evt = pushMessage(&tempMessage);
|
||||
|
||||
/* If we got reset signaling, transition to default */
|
||||
if (evt & (uint32_t)Notifications::PDB_EVT_PE_RESET) {
|
||||
@@ -625,3 +618,57 @@ void PolicyEngine::PPSTimerCallback() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EventBits_t PolicyEngine::pushMessage(union pd_msg *msg) {
|
||||
if (PD_MSGTYPE_GET(msg) == PD_MSGTYPE_SOFT_RESET && PD_NUMOBJ_GET(msg) == 0) {
|
||||
/* Clear MessageIDCounter */
|
||||
_tx_messageidcounter = 0;
|
||||
return (EventBits_t)Notifications::PDB_EVT_PE_TX_DONE;
|
||||
}
|
||||
msg->hdr &= ~PD_HDR_MESSAGEID;
|
||||
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 */
|
||||
// while (fusb_get_typec_current() != fusb_sink_tx_ok) {
|
||||
// vTaskDelay(TICKS_10MS);
|
||||
// }
|
||||
}
|
||||
/* Send the message to the PHY */
|
||||
fusb_send_message(msg);
|
||||
/* Waiting for response*/
|
||||
EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_RESET | (uint32_t)Notifications::PDB_EVT_TX_DISCARD | (uint32_t)Notifications::PDB_EVT_TX_I_TXSENT
|
||||
| (uint32_t)Notifications::PDB_EVT_TX_I_RETRYFAIL);
|
||||
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_TX_DISCARD) {
|
||||
// increment the counter
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
return (EventBits_t)Notifications::PDB_EVT_PE_TX_ERR; //
|
||||
}
|
||||
|
||||
/* If the message was sent successfully */
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_TX_I_TXSENT) {
|
||||
union pd_msg 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) {
|
||||
/* Increment MessageIDCounter */
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
|
||||
return (EventBits_t)Notifications::PDB_EVT_PE_TX_DONE;
|
||||
} else {
|
||||
return (EventBits_t)Notifications::PDB_EVT_PE_TX_ERR;
|
||||
}
|
||||
}
|
||||
/* If the message failed to be sent */
|
||||
if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_TX_I_RETRYFAIL) {
|
||||
return (EventBits_t)Notifications::PDB_EVT_PE_TX_ERR;
|
||||
}
|
||||
|
||||
/* Silence the compiler warning */
|
||||
return (EventBits_t)Notifications::PDB_EVT_PE_TX_ERR;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,10 @@ public:
|
||||
PDB_EVT_PE_PPS_REQUEST = EVENT_MASK(6),
|
||||
PDB_EVT_PE_GET_SOURCE_CAP = EVENT_MASK(7),
|
||||
PDB_EVT_PE_NEW_POWER = EVENT_MASK(8),
|
||||
PDB_EVT_PE_ALL = (EVENT_MASK(9) - 1),
|
||||
PDB_EVT_TX_I_TXSENT = EVENT_MASK(9),
|
||||
PDB_EVT_TX_I_RETRYFAIL = EVENT_MASK(10),
|
||||
PDB_EVT_TX_DISCARD = EVENT_MASK(11),
|
||||
PDB_EVT_PE_ALL = (EVENT_MASK(12) - 1),
|
||||
};
|
||||
// Send a notification
|
||||
static void notify(Notifications notification);
|
||||
@@ -86,25 +89,28 @@ private:
|
||||
/* The index of the first PPS APDO */
|
||||
static uint8_t _pps_index;
|
||||
|
||||
static void pe_task(const void *arg);
|
||||
static void pe_task(const void *arg);
|
||||
static EventBits_t pushMessage(union pd_msg *msg);
|
||||
static uint8_t _tx_messageidcounter;
|
||||
enum policy_engine_state {
|
||||
PESinkStartup,
|
||||
PESinkDiscovery,
|
||||
PESinkWaitCap,
|
||||
PESinkEvalCap,
|
||||
PESinkSelectCap, // 4
|
||||
PESinkTransitionSink, // 5
|
||||
PESinkReady, // 6
|
||||
PESinkGetSourceCap,
|
||||
PESinkGiveSinkCap,
|
||||
PESinkHardReset,
|
||||
PESinkTransitionDefault,
|
||||
PESinkSoftReset,
|
||||
PESinkSendSoftReset,
|
||||
PESinkSendNotSupported,
|
||||
PESinkChunkReceived,
|
||||
PESinkNotSupportedReceived,
|
||||
PESinkSourceUnresponsive
|
||||
PESinkStartup, // 0
|
||||
PESinkDiscovery, // 1
|
||||
PESinkWaitCap, // 2
|
||||
PESinkEvalCap, // 3
|
||||
PESinkSelectCap, // 4
|
||||
PESinkTransitionSink, // 5
|
||||
PESinkReady, // 6
|
||||
PESinkGetSourceCap, // 7
|
||||
PESinkGiveSinkCap, // 8
|
||||
PESinkHardReset, // 9
|
||||
PESinkTransitionDefault, // 10
|
||||
PESinkSoftReset, // 11
|
||||
PESinkSendSoftReset, // 12
|
||||
PESinkSendNotSupported, // 13
|
||||
PESinkChunkReceived, // 14
|
||||
PESinkNotSupportedReceived, // 15
|
||||
PESinkSourceUnresponsive // 16
|
||||
|
||||
};
|
||||
static enum policy_engine_state pe_sink_startup();
|
||||
static enum policy_engine_state pe_sink_discovery();
|
||||
|
||||
@@ -1,276 +0,0 @@
|
||||
/*
|
||||
* PD Buddy Firmware Library - USB Power Delivery for everyone
|
||||
* Copyright 2017-2018 Clayton G. Hobbs
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "protocol_tx.h"
|
||||
#include "Defines.h"
|
||||
#include "fusb302b.h"
|
||||
#include "fusbpd.h"
|
||||
#include "policy_engine.h"
|
||||
#include <pd.h>
|
||||
|
||||
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;
|
||||
/*
|
||||
* PRL_Tx_PHY_Layer_Reset state
|
||||
*/
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_phy_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(PolicyEngine::Notifications::PDB_EVT_PE_TX_ERR);
|
||||
/* Finish failing to send the message */
|
||||
while (messagePending()) {
|
||||
getMessage(); // Discard
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() {
|
||||
/* Clear MessageIDCounter */
|
||||
_tx_messageidcounter = 0;
|
||||
|
||||
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;
|
||||
|
||||
/* PD 3.0 collision avoidance */
|
||||
if (PolicyEngine::isPD3_0()) {
|
||||
/* If we're starting an AMS, wait for permission to transmit */
|
||||
while (fusb_get_typec_current() != fusb_sink_tx_ok) {
|
||||
vTaskDelay(TICKS_10MS);
|
||||
}
|
||||
}
|
||||
messageSending = true;
|
||||
/* Send the message to the PHY */
|
||||
fusb_send_message(&temp_msg);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Silence the compiler warning */
|
||||
return PRLTxDiscardMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* PRL_Tx_Match_MessageID state
|
||||
*/
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_match_messageid() {
|
||||
union pd_msg 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;
|
||||
}
|
||||
}
|
||||
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_transmission_error() {
|
||||
/* Increment MessageIDCounter */
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
|
||||
/* Tell the policy engine that we failed */
|
||||
PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_PE_TX_ERR);
|
||||
|
||||
return PRLTxWaitMessage;
|
||||
}
|
||||
|
||||
ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_message_sent() {
|
||||
messageSending = false;
|
||||
/* Increment MessageIDCounter */
|
||||
_tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
|
||||
|
||||
/* Tell the policy engine that we succeeded */
|
||||
PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_PE_TX_DONE);
|
||||
|
||||
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;
|
||||
|
||||
return PRLTxPHYReset;
|
||||
} else {
|
||||
return PRLTxWaitMessage;
|
||||
}
|
||||
}
|
||||
void ProtocolTransmit::thread(const void *args) {
|
||||
(void)args;
|
||||
ProtocolTransmit::protocol_tx_state state = PRLTxPHYReset;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolTransmit::notify(ProtocolTransmit::Notifications notification) {
|
||||
if (xEventGroupHandle != NULL) {
|
||||
xEventGroupSetBits(xEventGroupHandle, (uint32_t)notification);
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolTransmit::init() {
|
||||
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);
|
||||
}
|
||||
|
||||
void ProtocolTransmit::pushMessage(union pd_msg *msg) {
|
||||
if (messagesWaiting) {
|
||||
if (xQueueSend(messagesWaiting, msg, 100) == pdTRUE) {
|
||||
notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ProtocolTransmit::messagePending() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask, TickType_t ticksToWait) {
|
||||
if (xEventGroupHandle) {
|
||||
return (Notifications)xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE, ticksToWait);
|
||||
}
|
||||
return (Notifications)0;
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* PD Buddy Firmware Library - USB Power Delivery for everyone
|
||||
* Copyright 2017-2018 Clayton G. Hobbs
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef PDB_PROTOCOL_TX_H
|
||||
#define PDB_PROTOCOL_TX_H
|
||||
|
||||
#include "policy_engine.h"
|
||||
|
||||
#include <pd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Events for the Protocol TX thread */
|
||||
|
||||
class ProtocolTransmit {
|
||||
public:
|
||||
static void init();
|
||||
// Push a message to the queue to be sent out the pd comms bus
|
||||
static void pushMessage(union pd_msg *msg);
|
||||
|
||||
enum class Notifications {
|
||||
|
||||
PDB_EVT_PRLTX_RESET = EVENT_MASK(0), //
|
||||
PDB_EVT_PRLTX_I_TXSENT = EVENT_MASK(1), //
|
||||
PDB_EVT_PRLTX_I_RETRYFAIL = EVENT_MASK(2), //
|
||||
PDB_EVT_PRLTX_DISCARD = EVENT_MASK(3), //
|
||||
PDB_EVT_PRLTX_MSG_TX = EVENT_MASK(4), //
|
||||
};
|
||||
static void notify(Notifications notification);
|
||||
|
||||
private:
|
||||
static void thread(const void *args);
|
||||
static EventGroupHandle_t xEventGroupHandle;
|
||||
static StaticEventGroup_t xCreatedEventGroup;
|
||||
static osThreadId TaskHandle;
|
||||
static const size_t TaskStackSize = 1024 / 4;
|
||||
static uint32_t TaskBuffer[TaskStackSize];
|
||||
static osStaticThreadDef_t TaskControlBlock;
|
||||
static bool messageSending;
|
||||
/*
|
||||
* Protocol TX machine states
|
||||
*
|
||||
* Because the PHY can automatically send retries, the Check_RetryCounter state
|
||||
* has been removed, transitions relating to it are modified appropriately, and
|
||||
* we don't even keep a RetryCounter.
|
||||
*/
|
||||
enum protocol_tx_state { PRLTxPHYReset, PRLTxWaitMessage, PRLTxReset, PRLTxConstructMessage, PRLTxWaitResponse, PRLTxMatchMessageID, PRLTxTransmissionError, PRLTxMessageSent, PRLTxDiscardMessage };
|
||||
// Internal states
|
||||
static protocol_tx_state protocol_tx_discard_message();
|
||||
static protocol_tx_state protocol_tx_message_sent();
|
||||
static protocol_tx_state protocol_tx_transmission_error();
|
||||
static protocol_tx_state protocol_tx_match_messageid();
|
||||
static protocol_tx_state protocol_tx_wait_response();
|
||||
static protocol_tx_state protocol_tx_construct_message();
|
||||
static protocol_tx_state protocol_tx_reset();
|
||||
static protocol_tx_state protocol_tx_wait_message();
|
||||
static protocol_tx_state protocol_tx_phy_reset();
|
||||
// queue of up to PDB_MSG_POOL_SIZE messages to send
|
||||
static StaticQueue_t xStaticQueue;
|
||||
/* The array to use as the queue's storage area. This must be at least
|
||||
uxQueueLength * uxItemSize bytes. */
|
||||
static uint8_t ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)];
|
||||
static QueueHandle_t messagesWaiting;
|
||||
static uint8_t _tx_messageidcounter;
|
||||
static bool messagePending();
|
||||
// Reads a message off the queue into the temp message
|
||||
static void getMessage();
|
||||
static union pd_msg temp_msg;
|
||||
static Notifications waitForEvent(uint32_t mask, TickType_t ticksToWait = portMAX_DELAY);
|
||||
};
|
||||
|
||||
#endif /* PDB_PROTOCOL_TX_H */
|
||||
@@ -164,9 +164,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef MODEL_MHP30
|
||||
#define VOLTAGE_DIV 350 // Default for MHP30
|
||||
#define VOLTAGE_DIV 352 // Default for MHP30
|
||||
#define PID_POWER_LIMIT 65 // Sets the max pwm power limit
|
||||
#define CALIBRATION_OFFSET 0 // the adc offset in uV
|
||||
#define CALIBRATION_OFFSET 700 // the adc offset in uV
|
||||
#define POWER_LIMIT 65 // 65 watts default power limit
|
||||
#define MAX_POWER_LIMIT 65 //
|
||||
#define POWER_LIMIT_STEPS 2 //
|
||||
|
||||
Reference in New Issue
Block a user