1
0
forked from me/IronOS

Works on SRC only units.. mostly

This commit is contained in:
Ben V. Brown
2020-07-22 22:39:35 +10:00
parent 6097216b24
commit 1cebcdc42b
14 changed files with 163 additions and 85 deletions

View File

@@ -0,0 +1,16 @@
/*
* BSP_PD.h
*
* Created on: 21 Jul 2020
* Author: Ralim
*/
#ifndef USER_BSP_PD_H_
#define USER_BSP_PD_H_
#include "BSP.h"
/*
* An array of all of the desired voltages & minimum currents in preferred order
*/
extern const uint16_t USB_PD_Desired_Levels[];
extern const uint8_t USB_PD_Desired_Levels_Len;
#endif /* USER_BSP_PD_H_ */

View File

@@ -0,0 +1,20 @@
/*
* BSP_PD.c
*
* Created on: 21 Jul 2020
* Author: Ralim
*/
#include "BSP_PD.h"
/*
* An array of all of the desired voltages & minimum currents in preferred order
*/
const uint16_t USB_PD_Desired_Levels[] = {
//mV desired input, mA minimum required current
12000, 2500, //12V @ 2.5A
9000, 2000, //9V @ 2A
5000, 1100, //5V @ 1.1A
};
const uint8_t USB_PD_Desired_Levels_Len = 3;

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "BSP.h"
#include "fusb302b.h"
#include "I2CBB.hpp"
#include <pd.h>

View File

@@ -22,6 +22,7 @@ uint8_t fusb302_detect() {
void fusb302_start_processing() {
/* Initialize the FUSB302B */
resetWatchdog();
fusb_setup();
resetWatchdog();
/* Create the policy engine thread. */

View File

@@ -33,7 +33,7 @@ public:
private:
static void Thread(const void *arg);
static osThreadId TaskHandle;
static const size_t TaskStackSize = 1536 / 4;
static const size_t TaskStackSize = 1536 / 2;
static uint32_t TaskBuffer[TaskStackSize];
static osStaticThreadDef_t TaskControlBlock;
static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait =

View File

@@ -33,40 +33,44 @@ uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize];
osStaticThreadDef_t InterruptHandler::TaskControlBlock;
void InterruptHandler::init() {
osThreadStaticDef(Task, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize,
osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize,
TaskBuffer, &TaskControlBlock);
TaskHandle = osThreadCreate(osThread(Task), NULL);
TaskHandle = osThreadCreate(osThread(intTask), NULL);
}
void InterruptHandler::Thread(const void *arg) {
(void) arg;
union fusb_status status;
volatile uint32_t events;
bool notifSent = false;
while (true) {
/* If the INT_N line is low */
xTaskNotifyWait(0x00, 0x0F, NULL, 100);
if (!notifSent) {
if (xTaskNotifyWait(0x00, 0x0F, NULL, 25) == pdPASS) {
osDelay(1);
}
}
notifSent = false;
/* Read the FUSB302B status and interrupt registers */
fusb_get_status(&status);
/* 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 ((status.status1 & FUSB_STATUS1_RX_EMPTY) == 0) {
ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT);
}
/* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX
* thread */
events = 0;
if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) {
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT);
notifSent = true;
}
if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) {
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
notifSent = true;
}
/* 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);
notifSent = true;
}
/* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset
@@ -74,9 +78,11 @@ void InterruptHandler::Thread(const void *arg) {
events = 0;
if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) {
// events |= PDB_EVT_HARDRST_I_HARDRST;
events |= PDB_EVT_HARDRST_I_HARDRST;
notifSent = true;
} else if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) {
events |= PDB_EVT_HARDRST_I_HARDSENT;
notifSent = true;
}
if (events) {
ResetHandler::notify(events);
@@ -86,6 +92,7 @@ void InterruptHandler::Thread(const void *arg) {
if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP
&& status.status1 & FUSB_STATUS1_OVRTEMP) {
PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP);
notifSent = true;
}
}
}
@@ -93,6 +100,6 @@ volatile uint8_t irqs = 0;
void InterruptHandler::irqCallback() {
irqs++;
BaseType_t taskWoke = pdFALSE;
xTaskNotifyFromISR(TaskHandle, 0x0F, eNotifyAction::eSetBits, &taskWoke);
xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke);
portYIELD_FROM_ISR(taskWoke);
}

View File

@@ -45,6 +45,8 @@ StaticQueue_t PolicyEngine::xStaticQueue;
uint8_t PolicyEngine::ucQueueStorageArea[PDB_MSG_POOL_SIZE
* sizeof(union pd_msg)];
QueueHandle_t PolicyEngine::messagesWaiting;
EventGroupHandle_t PolicyEngine::xEventGroupHandle;
StaticEventGroup_t PolicyEngine::xCreatedEventGroup;
void PolicyEngine::init() {
messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE,
sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue);
@@ -52,10 +54,21 @@ void PolicyEngine::init() {
osThreadStaticDef(Task, pe_task, PDB_PRIO_PE, 0, TaskStackSize, TaskBuffer,
&TaskControlBlock);
TaskHandle = osThreadCreate(osThread(Task), NULL);
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
}
void PolicyEngine::notify(uint32_t notification) {
xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits);
notification = notification
& (
PDB_EVT_PE_RESET | PDB_EVT_PE_MSG_RX | PDB_EVT_PE_TX_DONE
| PDB_EVT_PE_TX_ERR | PDB_EVT_PE_HARD_SENT
| PDB_EVT_PE_I_OVRTEMP | PDB_EVT_PE_PPS_REQUEST);
if (notification) {
xEventGroupSetBits(xEventGroupHandle, notification);
} else {
asm("bkpt");
}
}
void PolicyEngine::pe_task(const void *arg) {
@@ -181,13 +194,13 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() {
if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) {
/* If the other end is using at least version 3.0, we'll
* use version 3.0. */
// if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) {
// hdr_template |= PD_SPECREV_3_0;
// /* Otherwise, use 2.0. Don't worry about the 1.0 case
// * because we don't have hardware for PD 1.0 signaling. */
// } else {
hdr_template |= PD_SPECREV_2_0;
// }
if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) {
hdr_template |= PD_SPECREV_3_0;
/* Otherwise, use 2.0. Don't worry about the 1.0 case
* because we don't have hardware for PD 1.0 signaling. */
} else {
hdr_template |= PD_SPECREV_2_0;
}
}
return PESinkEvalCap;
/* If the message was a Soft_Reset, do the soft reset procedure */
@@ -242,11 +255,11 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_eval_cap() {
}
PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() {
waitForEvent(
PDB_EVT_PE_TX_DONE | PDB_EVT_PE_TX_ERR | PDB_EVT_PE_RESET, 0);
/* Transmit the request */
ProtocolTransmit::pushMessage(&_last_dpm_request);
//Send indication that there is a message pending
waitForEvent(0xFFFF, 0); //clear pending
//Send indication that there is a message pending
ProtocolTransmit::notify(
ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
eventmask_t evt = waitForEvent(
@@ -257,7 +270,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() {
return PESinkTransitionDefault;
}
/* If the message transmission failed, send a hard reset */
if ((evt & PDB_EVT_PE_TX_DONE) == 0) {
if ((evt & PDB_EVT_PE_TX_ERR) == PDB_EVT_PE_TX_ERR) {
return PESinkHardReset;
}
@@ -794,9 +807,9 @@ bool PolicyEngine::heatingAllowed() {
}
uint32_t PolicyEngine::waitForEvent(uint32_t mask, uint32_t ticksToWait) {
uint32_t pulNotificationValue;
xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait);
return pulNotificationValue & mask;
return xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE,
ticksToWait);
}
bool PolicyEngine::isPD3_0() {

View File

@@ -112,6 +112,8 @@ private:
static enum policy_engine_state pe_sink_chunk_received();
static enum policy_engine_state pe_sink_not_supported_received();
static enum policy_engine_state pe_sink_source_unresponsive();
static EventGroupHandle_t xEventGroupHandle;
static StaticEventGroup_t xCreatedEventGroup;
static uint32_t waitForEvent(uint32_t mask, uint32_t ticksToWait =
portMAX_DELAY);
//Task resources

View File

@@ -6,7 +6,7 @@
*/
#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)
/*
@@ -55,32 +55,45 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability(
/* Make sure we have configuration */
/* Look at the PDOs to see if one matches our desires */
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]);
if (voltage == 9000) {
//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);
/* 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);
/* 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);
request->obj[0] |= PD_RDO_USB_COMMS;
request->obj[0] |= PD_RDO_USB_COMMS;
/* Update requested voltage */
_requested_voltage = voltage;
/* Update requested voltage */
_requested_voltage = voltage;
return true;
return true;
}
}
}
}
#if 0
/* If we have a PPS APDO, our desired V lies within its range, and
* its I is at least our desired I */
@@ -110,6 +123,7 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability(
// return true;
}
#endif
}
}
/* If there's a PDO in the voltage range, use it */
// int8_t i = dpm_get_range_fixed_pdo_index(caps, scfg);

View File

@@ -35,11 +35,12 @@ uint8_t ProtocolReceive::_tx_messageidcounter;
ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_wait_phy() {
/* Wait for an event */
_rx_messageid = 0;
eventmask_t evt = waitForEvent(0xFFFFFFFF);
eventmask_t evt = waitForEvent(
PDB_EVT_PRLRX_RESET | PDB_EVT_PRLRX_I_GCRCSENT);
/* If we got a reset event, reset */
if (evt & PDB_EVT_PRLRX_RESET) {
// waitForEvent(PDB_EVT_PRLRX_RESET, 0);
waitForEvent(PDB_EVT_PRLRX_RESET, 0);
return PRLRxWaitPHY;
}
/* If we got an I_GCRCSENT event, read the message and decide what to do */
@@ -99,11 +100,10 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_check_messageid(
/* 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++;
{
if (PD_MESSAGEID_GET(&tempMessage) == _rx_messageid) {
return PRLRxWaitPHY;
} else {
rxCounter++;
return PRLRxStoreMessageID;
}
}
@@ -131,9 +131,12 @@ ProtocolReceive::protocol_rx_state ProtocolReceive::protocol_rx_store_messageid(
return PRLRxWaitPHY;
}
EventGroupHandle_t ProtocolReceive::xEventGroupHandle;
StaticEventGroup_t ProtocolReceive::xCreatedEventGroup;
void ProtocolReceive::init() {
osThreadStaticDef(Task, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer,
&TaskControlBlock);
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
TaskHandle = osThreadCreate(osThread(Task), NULL);
}
@@ -165,14 +168,10 @@ void ProtocolReceive::thread(const void *args) {
}
void ProtocolReceive::notify(uint32_t notification) {
if (notification == PDB_EVT_PRLRX_I_GCRCSENT) {
// asm("bkpt");
}
xTaskNotify(TaskHandle, notification, eNotifyAction::eSetBits);
xEventGroupSetBits(xEventGroupHandle, notification);
}
uint32_t ProtocolReceive::waitForEvent(uint32_t mask, uint32_t ticksToWait) {
uint32_t pulNotificationValue;
xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait);
return pulNotificationValue & mask;
return xEventGroupWaitBits(xEventGroupHandle, mask, mask,
pdFALSE, ticksToWait);
}

View File

@@ -33,6 +33,8 @@ public:
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];

View File

@@ -64,15 +64,15 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message()
| (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) {
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) {
return PRLTxPHYReset;
}
if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) {
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) {
return PRLTxDiscardMessage;
}
/* If the policy engine is trying to send a message */
if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX) {
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_MSG_TX) {
/* Get the message */
getMessage();
@@ -110,10 +110,10 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_mess
(uint32_t) Notifications::PDB_EVT_PRLTX_RESET
| (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD, 0);
if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) {
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) {
return PRLTxPHYReset;
}
if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) {
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) {
return PRLTxDiscardMessage;
}
@@ -126,7 +126,8 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_mess
/* 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) {
if ((uint32_t) evt
& (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) {
while (fusb_get_typec_current() != fusb_sink_tx_ok) {
osDelay(1);
}
@@ -151,19 +152,19 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_response(
| (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) {
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_RESET) {
return PRLTxPHYReset;
}
if ((uint32_t)evt & (uint32_t) Notifications::PDB_EVT_PRLTX_DISCARD) {
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) {
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) {
if ((uint32_t) evt & (uint32_t) Notifications::PDB_EVT_PRLTX_I_RETRYFAIL) {
return PRLTxTransmissionError;
}
@@ -259,8 +260,10 @@ void ProtocolTransmit::thread(const void *args) {
}
}
EventGroupHandle_t ProtocolTransmit::xEventGroupHandle;
StaticEventGroup_t ProtocolTransmit::xCreatedEventGroup;
void ProtocolTransmit::notify(ProtocolTransmit::Notifications notification) {
xTaskNotify(TaskHandle, (uint32_t )notification, eNotifyAction::eSetBits);
xEventGroupSetBits(xEventGroupHandle, (uint32_t) notification);
}
void ProtocolTransmit::init() {
@@ -270,6 +273,7 @@ void ProtocolTransmit::init() {
osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PE, 0, TaskStackSize,
TaskBuffer, &TaskControlBlock);
TaskHandle = osThreadCreate(osThread(pd_txTask), NULL);
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
}
void ProtocolTransmit::pushMessage(union pd_msg *msg) {
@@ -287,7 +291,6 @@ void ProtocolTransmit::getMessage() {
ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask,
uint32_t ticksToWait) {
uint32_t pulNotificationValue;
xTaskNotifyWait(0x00, mask, &pulNotificationValue, ticksToWait);
return (Notifications) (pulNotificationValue & mask);
return (Notifications) xEventGroupWaitBits(xEventGroupHandle, mask, mask,
pdFALSE, ticksToWait);
}

View File

@@ -43,7 +43,8 @@ public:
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];

View File

@@ -14,7 +14,7 @@ MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
/* LOCAL_BUILD*/
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 46K
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 48K
/* production*/
/*ROM (rx) : ORIGIN = 0x08004000, LENGTH = 46K*/