From 0bfe05212764c6dad3e1aef2e1bcedccd200108b Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 1 May 2021 12:21:37 +1000 Subject: [PATCH] Reworking USB-PD stack to remove a thread --- source/Core/Drivers/FUSB302/fusb302b.cpp | 197 +++++++------ source/Core/Drivers/FUSB302/fusb302b.h | 2 +- source/Core/Drivers/FUSB302/fusbpd.cpp | 2 - source/Core/Drivers/FUSB302/int_n.cpp | 125 ++++---- source/Core/Drivers/FUSB302/policy_engine.cpp | 79 ++++- source/Core/Drivers/FUSB302/policy_engine.h | 44 +-- source/Core/Drivers/FUSB302/protocol_tx.cpp | 276 ------------------ source/Core/Drivers/FUSB302/protocol_tx.h | 85 ------ source/Core/Inc/configuration.h | 4 +- 9 files changed, 265 insertions(+), 549 deletions(-) delete mode 100644 source/Core/Drivers/FUSB302/protocol_tx.cpp delete mode 100644 source/Core/Drivers/FUSB302/protocol_tx.h diff --git a/source/Core/Drivers/FUSB302/fusb302b.cpp b/source/Core/Drivers/FUSB302/fusb302b.cpp index 74194ee8..2ee6cadc 100644 --- a/source/Core/Drivers/FUSB302/fusb302b.cpp +++ b/source/Core/Drivers/FUSB302/fusb302b.cpp @@ -23,135 +23,148 @@ #include 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; } diff --git a/source/Core/Drivers/FUSB302/fusb302b.h b/source/Core/Drivers/FUSB302/fusb302b.h index fcba5b6d..72736250 100644 --- a/source/Core/Drivers/FUSB302/fusb302b.h +++ b/source/Core/Drivers/FUSB302/fusb302b.h @@ -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 */ diff --git a/source/Core/Drivers/FUSB302/fusbpd.cpp b/source/Core/Drivers/FUSB302/fusbpd.cpp index 54f026c0..f8a74155 100644 --- a/source/Core/Drivers/FUSB302/fusbpd.cpp +++ b/source/Core/Drivers/FUSB302/fusbpd.cpp @@ -12,7 +12,6 @@ #include "int_n.h" #include "policy_engine.h" -#include "protocol_tx.h" #include #include @@ -20,7 +19,6 @@ void fusb302_start_processing() { /* Initialize the FUSB302B */ if (fusb_setup()) { PolicyEngine::init(); - ProtocolTransmit::init(); InterruptHandler::init(); } } diff --git a/source/Core/Drivers/FUSB302/int_n.cpp b/source/Core/Drivers/FUSB302/int_n.cpp index f571913d..c5dfa669 100644 --- a/source/Core/Drivers/FUSB302/int_n.cpp +++ b/source/Core/Drivers/FUSB302/int_n.cpp @@ -22,79 +22,92 @@ #include "fusbpd.h" #include "policy_engine.h" -#include "protocol_tx.h" #include "task.h" #include #include 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); + } } diff --git a/source/Core/Drivers/FUSB302/policy_engine.cpp b/source/Core/Drivers/FUSB302/policy_engine.cpp index d1ebaba0..d1322c9a 100644 --- a/source/Core/Drivers/FUSB302/policy_engine.cpp +++ b/source/Core/Drivers/FUSB302/policy_engine.cpp @@ -19,7 +19,6 @@ #include "Defines.h" #include "fusb302b.h" #include "int_n.h" -#include "protocol_tx.h" #include #include 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; +} diff --git a/source/Core/Drivers/FUSB302/policy_engine.h b/source/Core/Drivers/FUSB302/policy_engine.h index 489b7a50..447d17c6 100644 --- a/source/Core/Drivers/FUSB302/policy_engine.h +++ b/source/Core/Drivers/FUSB302/policy_engine.h @@ -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(); diff --git a/source/Core/Drivers/FUSB302/protocol_tx.cpp b/source/Core/Drivers/FUSB302/protocol_tx.cpp deleted file mode 100644 index ca9410b5..00000000 --- a/source/Core/Drivers/FUSB302/protocol_tx.cpp +++ /dev/null @@ -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 - -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; -} diff --git a/source/Core/Drivers/FUSB302/protocol_tx.h b/source/Core/Drivers/FUSB302/protocol_tx.h deleted file mode 100644 index 0231f455..00000000 --- a/source/Core/Drivers/FUSB302/protocol_tx.h +++ /dev/null @@ -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 -#include - -/* 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 */ diff --git a/source/Core/Inc/configuration.h b/source/Core/Inc/configuration.h index 99714f99..28508de3 100644 --- a/source/Core/Inc/configuration.h +++ b/source/Core/Inc/configuration.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 //