Added priority elevation to Downstream USB host processing code that

interacts with SPI.

It elevates to USB_OTG priority to avoid preemption by SPI, DMA, or USB
interrupts thus avoiding synchronisation issues between USB host stack
and SPI interface.

Also minor improvements to Downstream error handling.
pull/7/head
Robert Fisk 9 years ago
parent c1b2c191c4
commit fc522bae0a

@ -32,6 +32,13 @@ typedef enum
} while (0); } while (0);
#define DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN \
do { \
LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \
DownstreamState = STATE_ERROR; \
} while (0);
void Downstream_InitStateMachine(void); void Downstream_InitStateMachine(void);

@ -42,6 +42,7 @@
#include "usbh_msc.h" #include "usbh_msc.h"
#include "usbh_msc_bot.h" #include "usbh_msc_bot.h"
#include "usbh_msc_scsi.h" #include "usbh_msc_scsi.h"
#include "interrupts.h"
/** @addtogroup USBH_LIB /** @addtogroup USBH_LIB
@ -498,6 +499,10 @@ static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost)
case MSC_READ: case MSC_READ:
case MSC_WRITE: 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); error = USBH_MSC_RdWrProcess(phost, MSC_Handle->rw_lun);
if(((int32_t)(phost->Timer - MSC_Handle->timeout) > 0) || (phost->device.is_connected == 0)) 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; MSC_Handle->RdWrCompleteCallback = NULL;
} }
} }
__set_BASEPRI(0);
break; break;
default: default:

@ -388,6 +388,12 @@ void USBH_MSC_BOT_Read_FreePacketCallback(DownstreamPacketTypeDef* freePacket)
{ {
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) Callback_MSC_phost->pActiveClass->pData; 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.bot_packet = freePacket;
MSC_Handle->hbot.pbuf = freePacket->Data; MSC_Handle->hbot.pbuf = freePacket->Data;
MSC_Handle->hbot.bot_packet_bytes_remaining = BOT_PAGE_LENGTH; 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; 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.bot_packet = receivedPacket;
MSC_Handle->hbot.pbuf = receivedPacket->Data; MSC_Handle->hbot.pbuf = receivedPacket->Data;
MSC_Handle->hbot.bot_packet_bytes_remaining = dataLength; MSC_Handle->hbot.bot_packet_bytes_remaining = dataLength;

@ -13,6 +13,7 @@
#include "usbh_core.h" #include "usbh_core.h"
#include "usbh_msc.h" #include "usbh_msc.h"
#include "led.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 //This callback receives various event ids from the host stack,
//at INT_PRIORITY_OTG_FS or from main(). We should therefore be prepared //either at INT_PRIORITY_OTG_FS or from main().
//for pre-emption by USB or SPI/DMA interrupts. //We should therefore elevate our execution priority to INT_PRIORITY_OTG_FS where necessary.
void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
{ {
InterfaceCommandClassTypeDef newActiveClass = COMMAND_CLASS_INTERFACE; InterfaceCommandClassTypeDef newActiveClass = COMMAND_CLASS_INTERFACE;
@ -172,7 +173,19 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
return; 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) if (id == HOST_USER_CLASS_ACTIVE)
{ {
switch (phost->pActiveClass->ClassCode) switch (phost->pActiveClass->ClassCode)
@ -186,11 +199,12 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
//Add other classes here... //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. //This is distinct from the fast freakout flash caused by internal errors or attacks.
default: default:
LED_Fault_SetBlinkRate(LED_SLOW_BLINK_RATE); LED_Fault_SetBlinkRate(LED_SLOW_BLINK_RATE);
DownstreamState = STATE_ERROR; DownstreamState = STATE_ERROR;
__set_BASEPRI(0);
return; 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 the new device has failed its 'approval' checks, we are sufficiently freaked out.
if (newActiveClass == COMMAND_CLASS_INTERFACE) 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. //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) && if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) &&
(ConfiguredDeviceClass != newActiveClass)) (ConfiguredDeviceClass != newActiveClass))
{ {
DOWNSTREAM_STATEMACHINE_FREAKOUT; DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN;
__set_BASEPRI(0);
return;
} }
ConfiguredDeviceClass = newActiveClass; ConfiguredDeviceClass = newActiveClass;
if (DownstreamState == STATE_WAIT_DEVICE_READY) if (DownstreamState == STATE_WAIT_DEVICE_READY)
{ {
Downstream_GetFreePacket(Downstream_PacketProcessor_Interface_ReplyNotifyDevice); Downstream_GetFreePacket(Downstream_PacketProcessor_Interface_ReplyNotifyDevice);
__set_BASEPRI(0);
return; return;
} }
if (DownstreamState == STATE_DEVICE_NOT_READY) if (DownstreamState == STATE_DEVICE_NOT_READY)
{ {
DownstreamState = STATE_DEVICE_READY; DownstreamState = STATE_DEVICE_READY;
__set_BASEPRI(0);
return; return;
} }
DOWNSTREAM_STATEMACHINE_FREAKOUT; DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN;
__set_BASEPRI(0);
return;
} }
} }

Loading…
Cancel
Save