diff --git a/Downstream/Inc/downstream_statemachine.h b/Downstream/Inc/downstream_statemachine.h index cafc548..ed644d0 100644 --- a/Downstream/Inc/downstream_statemachine.h +++ b/Downstream/Inc/downstream_statemachine.h @@ -32,6 +32,13 @@ typedef enum } while (0); +#define DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN \ + do { \ + LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \ + DownstreamState = STATE_ERROR; \ +} while (0); + + void Downstream_InitStateMachine(void); diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c index 522bef6..d91988b 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c @@ -42,6 +42,7 @@ #include "usbh_msc.h" #include "usbh_msc_bot.h" #include "usbh_msc_scsi.h" +#include "interrupts.h" /** @addtogroup USBH_LIB @@ -498,6 +499,10 @@ static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost) case MSC_READ: case MSC_WRITE: + //USBH_MSC_RdWrProcess interacts heavily with downstream SPI code. + //So to protect against preemption we elevate our priority here. + __set_BASEPRI(INT_PRIORITY_OTG_FS); + error = USBH_MSC_RdWrProcess(phost, MSC_Handle->rw_lun); if(((int32_t)(phost->Timer - MSC_Handle->timeout) > 0) || (phost->device.is_connected == 0)) { @@ -513,6 +518,8 @@ static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost) MSC_Handle->RdWrCompleteCallback = NULL; } } + + __set_BASEPRI(0); break; default: diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c index 2b1615c..5284cae 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c @@ -388,6 +388,12 @@ void USBH_MSC_BOT_Read_FreePacketCallback(DownstreamPacketTypeDef* freePacket) { MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) Callback_MSC_phost->pActiveClass->pData; + if (MSC_Handle->hbot.state != BOT_DATA_IN_WAIT) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + MSC_Handle->hbot.bot_packet = freePacket; MSC_Handle->hbot.pbuf = freePacket->Data; MSC_Handle->hbot.bot_packet_bytes_remaining = BOT_PAGE_LENGTH; @@ -421,6 +427,12 @@ void USBH_MSC_BOT_Write_ReceivePacketCallback(DownstreamPacketTypeDef* receivedP { MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) Callback_MSC_phost->pActiveClass->pData; + if (MSC_Handle->hbot.state != BOT_DATA_OUT_WAIT) + { + Downstream_PacketProcessor_FreakOut(); + return; + } + MSC_Handle->hbot.bot_packet = receivedPacket; MSC_Handle->hbot.pbuf = receivedPacket->Data; MSC_Handle->hbot.bot_packet_bytes_remaining = dataLength; diff --git a/Downstream/Src/downstream_statemachine.c b/Downstream/Src/downstream_statemachine.c index c78b8eb..157ead3 100644 --- a/Downstream/Src/downstream_statemachine.c +++ b/Downstream/Src/downstream_statemachine.c @@ -13,6 +13,7 @@ #include "usbh_core.h" #include "usbh_msc.h" #include "led.h" +#include "interrupts.h" @@ -153,9 +154,9 @@ void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket) } -//This callback receives various event ids from the host stack, either -//at INT_PRIORITY_OTG_FS or from main(). We should therefore be prepared -//for pre-emption by USB or SPI/DMA interrupts. +//This callback receives various event ids from the host stack, +//either at INT_PRIORITY_OTG_FS or from main(). +//We should therefore elevate our execution priority to INT_PRIORITY_OTG_FS where necessary. void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) { InterfaceCommandClassTypeDef newActiveClass = COMMAND_CLASS_INTERFACE; @@ -172,7 +173,19 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) return; } - //Called from main(). Beware pre-emption! + //Elevate our priority level so we aren't interrupted + __set_BASEPRI(INT_PRIORITY_OTG_FS); + + + //Called from main() + if (id == HOST_USER_UNRECOVERED_ERROR) + { + DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN; + __set_BASEPRI(0); + return; + } + + //Called from main() if (id == HOST_USER_CLASS_ACTIVE) { switch (phost->pActiveClass->ClassCode) @@ -186,11 +199,12 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) //Add other classes here... - //Any unsupported device will cause a slow fault flash. + //Unsupported device classes will cause a slow fault flash. //This is distinct from the fast freakout flash caused by internal errors or attacks. default: LED_Fault_SetBlinkRate(LED_SLOW_BLINK_RATE); DownstreamState = STATE_ERROR; + __set_BASEPRI(0); return; } @@ -198,7 +212,9 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) //If the new device has failed its 'approval' checks, we are sufficiently freaked out. if (newActiveClass == COMMAND_CLASS_INTERFACE) { - DOWNSTREAM_STATEMACHINE_FREAKOUT; + DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN; + __set_BASEPRI(0); + return; } //If we already configured a device class, we cannot change to a different one without rebooting. @@ -206,23 +222,29 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) && (ConfiguredDeviceClass != newActiveClass)) { - DOWNSTREAM_STATEMACHINE_FREAKOUT; + DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN; + __set_BASEPRI(0); + return; } ConfiguredDeviceClass = newActiveClass; if (DownstreamState == STATE_WAIT_DEVICE_READY) { Downstream_GetFreePacket(Downstream_PacketProcessor_Interface_ReplyNotifyDevice); + __set_BASEPRI(0); return; } if (DownstreamState == STATE_DEVICE_NOT_READY) { DownstreamState = STATE_DEVICE_READY; + __set_BASEPRI(0); return; } - DOWNSTREAM_STATEMACHINE_FREAKOUT; + DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN; + __set_BASEPRI(0); + return; } }