Improved Downstream error handling:

- More sensible handling of error cases on SPI interface
- Improved Freakout macros
- Implemented automatic fault LED blinking
pull/7/head
Robert Fisk 9 years ago
parent 0e1fed6047
commit c1b2c191c4

@ -35,6 +35,11 @@
#define STAT_LED_ON (STAT_LED_PORT->BSRR = (STAT_LED_PIN << BSRR_SHIFT_LOW)) //Stat LED is active-low
#define STAT_LED_OFF (STAT_LED_PORT->BSRR = (STAT_LED_PIN << BSRR_SHIFT_HIGH))
//#define RUN_LED_ON......
#define FAULT_LED_ON STAT_LED_ON
#define FAULT_LED_OFF STAT_LED_OFF
//#define SPI_DMA_ACTIVE_PIN GPIO_PIN_5 /////////Temporary indicator of SPI & DMA activity
//#define SPI_DMA_ACTIVE_PORT GPIOB
//#define SPI_DMA_ACTIVE_ON SPI_DMA_ACTIVE_PORT->BSRR = (SPI_DMA_ACTIVE_PIN << BSRR_SHIFT_LOW)

@ -16,8 +16,7 @@
#define MSC_FIXED_LUN 0
typedef void (*DownstreamMSCCallbackPacketTypeDef)(HAL_StatusTypeDef result,
DownstreamPacketTypeDef* receivedPacket,
typedef void (*DownstreamMSCCallbackPacketTypeDef)(DownstreamPacketTypeDef* receivedPacket,
uint16_t dataLength);

@ -17,26 +17,24 @@
#define DOWNSTREAM_PACKET_LEN_MIN (DOWNSTREAM_PACKET_HEADER_LEN)
#define SPI_INTERFACE_FREAKOUT_RETURN_VOID \
#define DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID \
do { \
LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \
Downstream_PacketProcessor_SetErrorState(); \
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_ERROR; \
while (1); \
/*UpstreamInterfaceState = INTERFACE_STATE_ERROR;*/ \
/*return;*/ \
} while (0);
#define SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR \
#define DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR \
do { \
LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \
Downstream_PacketProcessor_SetErrorState(); \
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_ERROR; \
while (1); \
/*UpstreamInterfaceState = INTERFACE_STATE_ERROR;*/ \
/*return HAL_ERROR;*/ \
} while (0);
#define SPI_INTERFACE_FREAKOUT_NO_RETURN \
do { \
while (1); \
/*while (1);*/ \
} while (0);
typedef enum

@ -16,19 +16,31 @@
typedef enum
{
STATE_DEVICE_NOT_READY,
STATE_DEVICE_READY, //HOST_USER_CLASS_ACTIVE callback arrives first
STATE_WAIT_DEVICE_READY, //COMMAND_INTERFACE_NOTIFY_DEVICE message arrives first
STATE_DEVICE_READY, //Go here if HOST_USER_CLASS_ACTIVE callback arrives first
STATE_WAIT_DEVICE_READY, //Go here if COMMAND_INTERFACE_NOTIFY_DEVICE message arrives first
STATE_ACTIVE,
STATE_ERROR
} DownstreamStateTypeDef;
#define DOWNSTREAM_STATEMACHINE_FREAKOUT \
do { \
LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \
DownstreamState = STATE_ERROR; \
return; \
} while (0);
void Downstream_InitStateMachine(void);
void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id);
void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket);
void Downstream_PacketProcessor_ErrorReply(DownstreamPacketTypeDef* replyPacket);
void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket);
void Downstream_PacketProcessor_SetErrorState(void);
void Downstream_PacketProcessor_FreakOut(void);
#endif /* INC_DOWNSTREAM_STATEMACHINE_H_ */

@ -0,0 +1,26 @@
/*
* led.h
*
* Created on: 19/08/2015
* Author: Robert Fisk
*/
#ifndef INC_LED_H_
#define INC_LED_H_
void LED_Init(void);
void LED_Fault_SetBlinkRate(uint16_t newBlinkRate);
void LED_DoBlinks(void);
#define STARTUP_FLASH_DELAY 500 //units = ticks = ms
//LEDs are on for BLINK_RATE ticks, then off for BLINK_RATE ticks
#define LED_FAST_BLINK_RATE 100
#define LED_SLOW_BLINK_RATE 500
#endif /* INC_LED_H_ */

@ -37,8 +37,7 @@ static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t
static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost);
void USBH_MSC_BOT_Read_FreePacketCallback(DownstreamPacketTypeDef* freePacket);
void USBH_MSC_BOT_Read_PrepareURB(USBH_HandleTypeDef *phost);
void USBH_MSC_BOT_Write_ReceivePacketCallback(HAL_StatusTypeDef result,
DownstreamPacketTypeDef* receivedPacket,
void USBH_MSC_BOT_Write_ReceivePacketCallback(DownstreamPacketTypeDef* receivedPacket,
uint16_t dataLength);
void USBH_MSC_BOT_Write_PrepareURB(USBH_HandleTypeDef *phost);
@ -178,8 +177,11 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
case BOT_DATA_IN:
/* Get first packet */
Callback_MSC_phost = phost;
Downstream_GetFreePacket(USBH_MSC_BOT_Read_FreePacketCallback);
MSC_Handle->hbot.state = BOT_DATA_IN_WAIT;
if (Downstream_GetFreePacket(USBH_MSC_BOT_Read_FreePacketCallback) != HAL_OK)
{
MSC_Handle->hbot.state = BOT_ERROR_IN;
}
break;
case BOT_DATA_IN_WAIT:
@ -189,6 +191,7 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
{
MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->hbot.this_URB_size;
MSC_Handle->hbot.bot_packet_bytes_remaining -= MSC_Handle->hbot.this_URB_size;
MSC_Handle->hbot.pbuf += MSC_Handle->hbot.this_URB_size;
if (MSC_Handle->hbot.cbw.field.DataTransferLength == 0)
{
@ -218,7 +221,6 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
else
{
//Continue filling the current bot_packet
MSC_Handle->hbot.pbuf += MSC_Handle->hbot.this_URB_size;
USBH_MSC_BOT_Read_PrepareURB(phost);
}
}
@ -254,6 +256,7 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
{
MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->hbot.this_URB_size;
MSC_Handle->hbot.bot_packet_bytes_remaining -= MSC_Handle->hbot.this_URB_size;
MSC_Handle->hbot.pbuf += MSC_Handle->hbot.this_URB_size;
if (MSC_Handle->hbot.cbw.field.DataTransferLength == 0)
{
@ -268,14 +271,12 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
//Get next bot_packet
if (Downstream_MSC_GetStreamDataPacket(USBH_MSC_BOT_Write_ReceivePacketCallback) != HAL_OK)
{
MSC_Handle->hbot.state = BOT_ERROR_IN;
break;
MSC_Handle->hbot.state = BOT_ERROR_OUT;
}
}
else
{
//Continue reading the current bot_packet
MSC_Handle->hbot.pbuf += MSC_Handle->hbot.this_URB_size;
USBH_MSC_BOT_Write_PrepareURB(phost);
}
}
@ -415,18 +416,11 @@ void USBH_MSC_BOT_Read_PrepareURB(USBH_HandleTypeDef *phost)
}
void USBH_MSC_BOT_Write_ReceivePacketCallback(HAL_StatusTypeDef result,
DownstreamPacketTypeDef* receivedPacket,
void USBH_MSC_BOT_Write_ReceivePacketCallback(DownstreamPacketTypeDef* receivedPacket,
uint16_t dataLength)
{
MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) Callback_MSC_phost->pActiveClass->pData;
if (result != HAL_OK)
{
MSC_Handle->hbot.state = BOT_ERROR_OUT;
return;
}
MSC_Handle->hbot.bot_packet = receivedPacket;
MSC_Handle->hbot.pbuf = receivedPacket->Data;
MSC_Handle->hbot.bot_packet_bytes_remaining = dataLength;

@ -40,13 +40,11 @@ HAL_StatusTypeDef Downstream_MSC_ApproveConnectedDevice(void)
if ((MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr == 0) ||
(MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr == UINT32_MAX))
{
//FreakOut?????
return HAL_ERROR;
}
if (MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size != MSC_SUPPORTED_BLOCK_SIZE)
{
//FreakOut?????
return HAL_ERROR;
}
@ -75,8 +73,7 @@ void Downstream_MSC_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
break;
default:
//FreakOut?????
Downstream_PacketProcessor_ErrorReply(receivedPacket);
Downstream_PacketProcessor_FreakOut();
}
}
@ -118,8 +115,7 @@ void Downstream_MSC_PacketProcessor_BeginRead(DownstreamPacketTypeDef* receivedP
if (receivedPacket->Length != (DOWNSTREAM_PACKET_HEADER_LEN + (4 * 3)))
{
//FreakOut?????
Downstream_PacketProcessor_ErrorReply(receivedPacket);
Downstream_PacketProcessor_FreakOut();
return;
}
@ -130,8 +126,7 @@ void Downstream_MSC_PacketProcessor_BeginRead(DownstreamPacketTypeDef* receivedP
((readBlockAddress + readBlockCount - 1) >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) ||
(readByteCount > UINT32_MAX))
{
//FreakOut?????
Downstream_PacketProcessor_ErrorReply(receivedPacket);
Downstream_PacketProcessor_FreakOut();
return;
}
@ -173,8 +168,7 @@ void Downstream_MSC_PacketProcessor_BeginWrite(DownstreamPacketTypeDef* received
if (receivedPacket->Length != (DOWNSTREAM_PACKET_HEADER_LEN + (4 * 3)))
{
//FreakOut?????
Downstream_PacketProcessor_ErrorReply(receivedPacket);
Downstream_PacketProcessor_FreakOut();
return;
}
@ -185,8 +179,7 @@ void Downstream_MSC_PacketProcessor_BeginWrite(DownstreamPacketTypeDef* received
((writeBlockAddress + writeBlockCount - 1) >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) ||
(writeByteCount > UINT32_MAX))
{
//FreakOut?????
Downstream_PacketProcessor_ErrorReply(receivedPacket);
Downstream_PacketProcessor_FreakOut();
return;
}
@ -214,7 +207,7 @@ void Downstream_MSC_PacketProcessor_BeginWrite(DownstreamPacketTypeDef* received
}
//Used by USB MSC host driver
HAL_StatusTypeDef Downstream_MSC_PutStreamDataPacket(DownstreamPacketTypeDef* packetToSend,
uint32_t dataLength)
{
@ -225,6 +218,7 @@ HAL_StatusTypeDef Downstream_MSC_PutStreamDataPacket(DownstreamPacketTypeDef* pa
}
//Used by USB MSC host driver
HAL_StatusTypeDef Downstream_MSC_GetStreamDataPacket(DownstreamMSCCallbackPacketTypeDef callback)
{
GetStreamDataCallback = callback;
@ -260,14 +254,13 @@ void Downstream_MSC_GetStreamDataPacketCallback(DownstreamPacketTypeDef* replyPa
(replyPacket->Length <= DOWNSTREAM_PACKET_HEADER_LEN) || //Should be at least one data byte in the packet.
(replyPacket->Length > ByteCount))
{
//FreakOut?????
GetStreamDataCallback(HAL_ERROR, NULL, NULL);
Downstream_PacketProcessor_FreakOut();
return;
}
dataLength = replyPacket->Length - DOWNSTREAM_PACKET_HEADER_LEN;
ByteCount -= dataLength;
GetStreamDataCallback(HAL_OK, replyPacket, dataLength); //usb_msc_scsi will use this packet, so don't release now
GetStreamDataCallback(replyPacket, dataLength); //usb_msc_scsi will use this packet, so don't release now
if (ByteCount > 0)
{
Downstream_MSC_GetStreamDataPacket(NULL); //Try to get the next packet now, before USB asks for it

@ -6,20 +6,22 @@
*/
#include <downstream_interface_def.h>
#include <downstream_spi.h>
#include "downstream_interface_def.h"
#include "downstream_spi.h"
#include "downstream_statemachine.h"
#include "board_config.h"
#include "led.h"
SPI_HandleTypeDef Hspi1;
DownstreamPacketTypeDef DownstreamPacket0;
DownstreamPacketTypeDef DownstreamPacket1;
DownstreamPacketTypeDef* CurrentWorkingPacket;
DownstreamPacketTypeDef* NextTxPacket;
DownstreamPacketTypeDef* NextTxPacket = NULL;
InterfaceStateTypeDef DownstreamInterfaceState;
FreePacketCallbackTypeDef PendingFreePacketCallback; //Indicates someone is waiting for a packet buffer to become available
SpiPacketReceivedCallbackTypeDef ReceivePacketCallback; //Indicates someone is waiting for a received packet
InterfaceStateTypeDef DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE;
FreePacketCallbackTypeDef PendingFreePacketCallback = NULL; //Indicates someone is waiting for a packet buffer to become available
SpiPacketReceivedCallbackTypeDef ReceivePacketCallback = NULL; //Indicates someone is waiting for a received packet
@ -35,11 +37,6 @@ void Downstream_InitSPI(void)
DownstreamPacket0.Busy = NOT_BUSY;
DownstreamPacket1.Busy = NOT_BUSY;
NextTxPacket = NULL;
PendingFreePacketCallback = NULL;
ReceivePacketCallback = NULL;
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE;
}
@ -61,19 +58,18 @@ void SPI1_Init(void)
}
//Used by...
//Used by downstream state machine and USB host classes.
HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback)
{
//Sanity checks
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
return HAL_ERROR;
}
//Do we already have a queued callback?
if (PendingFreePacketCallback != NULL)
{
SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
}
//Check if there is a free buffer now
@ -96,40 +92,20 @@ HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback)
}
//DownstreamPacketTypeDef* Downstream_GetFreePacketImmediately(void)
//{
// //Sanity checks
// if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
// {
// SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
// }
//
// //We are expecting a free buffer now
// if (DownstreamPacket0.Busy == NOT_BUSY)
// {
// DownstreamPacket0.Busy = BUSY;
// return &DownstreamPacket0;
// }
// if (DownstreamPacket1.Busy == NOT_BUSY)
// {
// DownstreamPacket1.Busy = BUSY;
// return &DownstreamPacket1;
// }
//
// //Should not happen:
// SPI_INTERFACE_FREAKOUT_NO_RETURN;
//}
//Used by...
//Used by Downstream state machine and USB host classes.
void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease)
{
FreePacketCallbackTypeDef tempCallback;
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
return;
}
if ((packetToRelease != &DownstreamPacket0) &&
(packetToRelease != &DownstreamPacket1))
{
SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
if (PendingFreePacketCallback != NULL)
@ -146,14 +122,19 @@ void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease)
//Used by Downstream state machine (and USB classes?).
//Used by Downstream state machine and USB classes.
//Ok to call when idle or transmitting.
//Not OK to call when receiving or awaiting reception.
HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callback)
{
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
return HAL_ERROR;
}
if (ReceivePacketCallback != NULL)
{
SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
}
ReceivePacketCallback = callback;
return Downstream_CheckPreparePacketReception();
@ -163,11 +144,6 @@ HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef call
//Internal use only
HAL_StatusTypeDef Downstream_CheckPreparePacketReception(void)
{
if (DownstreamInterfaceState > DOWNSTREAM_INTERFACE_TX_PACKET_WAIT)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
}
if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_IDLE)
{
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_RX_SIZE_WAIT;
@ -182,7 +158,7 @@ void Downstream_PreparePacketReception(DownstreamPacketTypeDef* freePacket)
{
if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_RX_SIZE_WAIT)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
CurrentWorkingPacket = freePacket;
//CurrentWorkingPacket->Length = 0;
@ -191,7 +167,7 @@ void Downstream_PreparePacketReception(DownstreamPacketTypeDef* freePacket)
(uint8_t*)&CurrentWorkingPacket->Length,
(2 + 1)) != HAL_OK) //"When the CRC feature is enabled the pData Length must be Size + 1"
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
UPSTREAM_TX_REQUEST_ASSERT;
@ -206,10 +182,9 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
UPSTREAM_TX_REQUEST_DEASSERT;
if ((DownstreamInterfaceState != DOWNSTREAM_INTERFACE_RX_SIZE_WAIT) &&
(DownstreamInterfaceState != DOWNSTREAM_INTERFACE_RX_PACKET_WAIT))
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
return;
}
if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_SIZE_WAIT)
@ -217,14 +192,14 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
if ((CurrentWorkingPacket->Length < DOWNSTREAM_PACKET_LEN_MIN) ||
(CurrentWorkingPacket->Length > DOWNSTREAM_PACKET_LEN))
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_RX_PACKET_WAIT;
if ((HAL_SPI_Receive_DMA(&Hspi1,
&CurrentWorkingPacket->CommandClass,
CurrentWorkingPacket->Length + 1)) != HAL_OK) //"When the CRC feature is enabled the pData Length must be Size + 1"
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
UPSTREAM_TX_REQUEST_ASSERT;
return;
@ -235,7 +210,7 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE;
if (ReceivePacketCallback == NULL)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
//Packet processor may want to receive another packet immediately,
//so clear ReceivePacketCallback before the call.
@ -243,7 +218,10 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
tempPacketCallback = ReceivePacketCallback;
ReceivePacketCallback = NULL;
tempPacketCallback(CurrentWorkingPacket);
return;
}
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
@ -253,21 +231,26 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
//It doesn't make sense to call when receiving or awaiting reception.
HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWrite)
{
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
return HAL_ERROR;
}
//Sanity checks
if ((packetToWrite != &DownstreamPacket0) &&
(packetToWrite != &DownstreamPacket1))
{
SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
}
if ((packetToWrite->Busy != BUSY) ||
(packetToWrite->Length < DOWNSTREAM_PACKET_LEN_MIN) ||
(packetToWrite->Length > DOWNSTREAM_PACKET_LEN))
{
SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
}
if (NextTxPacket != NULL)
{
SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
}
switch (DownstreamInterfaceState)
@ -285,13 +268,13 @@ HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWri
(uint8_t*)&CurrentWorkingPacket->Length,
2 + 1) != HAL_OK) //"When the CRC feature is enabled the pRxData Length must be Size + 1"
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
}
UPSTREAM_TX_REQUEST_ASSERT;
break;
default:
SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR;
DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR;
}
return HAL_OK;
@ -306,16 +289,21 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
UPSTREAM_TX_REQUEST_DEASSERT;
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
return;
}
if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_TX_SIZE_WAIT)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
if (CurrentWorkingPacket->Length != 0)
{
//Currently we just freak out if Upstream sends us an unexpected command.
//Theoretically we could reset our downstream state machine and accept the new command...
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_PACKET_WAIT;
@ -323,7 +311,7 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
&CurrentWorkingPacket->CommandClass,
CurrentWorkingPacket->Length)) != HAL_OK)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
UPSTREAM_TX_REQUEST_ASSERT;
}
@ -335,9 +323,14 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
UPSTREAM_TX_REQUEST_DEASSERT;
if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR)
{
return;
}
if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_TX_PACKET_WAIT)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
Downstream_ReleasePacket(CurrentWorkingPacket);
@ -353,7 +346,7 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
(uint8_t*)&CurrentWorkingPacket->Length,
2 + 1) != HAL_OK) //"When the CRC feature is enabled the pRxData Length must be Size + 1"
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}
UPSTREAM_TX_REQUEST_ASSERT;
return;
@ -371,6 +364,6 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
//Something bad happened! Possibly CRC error...
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID;
}

@ -12,11 +12,12 @@
#include "downstream_msc.h"
#include "usbh_core.h"
#include "usbh_msc.h"
#include "led.h"
DownstreamStateTypeDef DownstreamState;
InterfaceCommandClassTypeDef ConfiguredDeviceClass;
DownstreamStateTypeDef DownstreamState = STATE_DEVICE_NOT_READY;
InterfaceCommandClassTypeDef ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE;
void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket);
@ -26,8 +27,6 @@ void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketType
void Downstream_InitStateMachine(void)
{
DownstreamState = STATE_DEVICE_NOT_READY;
ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE;
Downstream_InitSPI();
//Prepare to receive our first packet from Upstream!
@ -37,12 +36,18 @@ void Downstream_InitStateMachine(void)
void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
{
if (DownstreamState >= STATE_ERROR)
{
Downstream_ReleasePacket(receivedPacket);
return;
}
switch (receivedPacket->CommandClass)
{
case COMMAND_CLASS_INTERFACE:
if (DownstreamState > STATE_DEVICE_READY)
{
SPI_INTERFACE_FREAKOUT_RETURN_VOID;
DOWNSTREAM_STATEMACHINE_FREAKOUT;
}
Downstream_PacketProcessor_Interface(receivedPacket);
break;
@ -50,8 +55,7 @@ void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
case COMMAND_CLASS_MASS_STORAGE:
if (DownstreamState != STATE_ACTIVE)
{
Downstream_PacketProcessor_ErrorReply(receivedPacket);
return;
DOWNSTREAM_STATEMACHINE_FREAKOUT;
}
Downstream_MSC_PacketProcessor(receivedPacket);
break;
@ -59,8 +63,22 @@ void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket)
//Add other classes here...
default:
Downstream_PacketProcessor_ErrorReply(receivedPacket);
DOWNSTREAM_STATEMACHINE_FREAKOUT;
}
}
//Used by downstream_spi freakout macro, indicates we should stop everything.
void Downstream_PacketProcessor_SetErrorState(void)
{
DownstreamState = STATE_ERROR;
}
//Used by downstream class interfaces
void Downstream_PacketProcessor_FreakOut(void)
{
DOWNSTREAM_STATEMACHINE_FREAKOUT;
}
@ -70,8 +88,10 @@ void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacke
switch (receivedPacket->Command)
{
case COMMAND_INTERFACE_ECHO:
Downstream_TransmitPacket(receivedPacket);
if (Downstream_TransmitPacket(receivedPacket) == HAL_OK)
{
Downstream_ReceivePacket(Downstream_PacketProcessor);
}
return;
case COMMAND_INTERFACE_NOTIFY_DEVICE:
@ -87,12 +107,12 @@ void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacke
Downstream_ReleasePacket(receivedPacket);
return;
}
Downstream_PacketProcessor_ErrorReply(receivedPacket);
DOWNSTREAM_STATEMACHINE_FREAKOUT;
return;
default:
Downstream_PacketProcessor_ErrorReply(receivedPacket);
DOWNSTREAM_STATEMACHINE_FREAKOUT;
}
}
@ -103,27 +123,34 @@ void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketType
replyPacket->CommandClass = COMMAND_CLASS_INTERFACE;
replyPacket->Command = COMMAND_INTERFACE_NOTIFY_DEVICE;
replyPacket->Data[0] = ConfiguredDeviceClass;
Downstream_TransmitPacket(replyPacket);
if (Downstream_TransmitPacket(replyPacket) == HAL_OK)
{
DownstreamState = STATE_ACTIVE;
Downstream_ReceivePacket(Downstream_PacketProcessor);
}
}
void Downstream_PacketProcessor_ErrorReply(DownstreamPacketTypeDef* replyPacket)
{
replyPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN;
replyPacket->CommandClass = COMMAND_CLASS_ERROR;
Downstream_TransmitPacket(replyPacket);
if (Downstream_TransmitPacket(replyPacket) == HAL_OK)
{
Downstream_ReceivePacket(Downstream_PacketProcessor);
}
}
void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket)
{
Downstream_TransmitPacket(replyPacket);
if (Downstream_TransmitPacket(replyPacket) == HAL_OK)
{
Downstream_ReceivePacket(Downstream_PacketProcessor);
}
}
//This callback receives various event ids from the host stack, either
@ -133,6 +160,11 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
{
InterfaceCommandClassTypeDef newActiveClass = COMMAND_CLASS_INTERFACE;
if (DownstreamState >= STATE_ERROR)
{
return;
}
//Called from USB interrupt
if (id == HOST_USER_DISCONNECTION)
{
@ -153,23 +185,31 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
break;
//Add other classes here...
}
//To change device class, we must reboot.
if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) &&
(ConfiguredDeviceClass != newActiveClass))
{
SPI_INTERFACE_FREAKOUT_NO_RETURN;
//Any unsupported device 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;
return;
}
//If the new device has failed its 'approval' checks, we are sufficiently freaked out.
if (newActiveClass == COMMAND_CLASS_INTERFACE)
{
return;
DOWNSTREAM_STATEMACHINE_FREAKOUT;
}
//If we already configured a device class, we cannot change to a different one without rebooting.
//This blocks some BadUSB attacks.
if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) &&
(ConfiguredDeviceClass != newActiveClass))
{
DOWNSTREAM_STATEMACHINE_FREAKOUT;
}
ConfiguredDeviceClass = newActiveClass;
if (DownstreamState == STATE_WAIT_DEVICE_READY)
{
Downstream_GetFreePacket(Downstream_PacketProcessor_Interface_ReplyNotifyDevice);
@ -182,9 +222,7 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id)
return;
}
SPI_INTERFACE_FREAKOUT_NO_RETURN;
DownstreamState = STATE_ERROR;
return;
DOWNSTREAM_STATEMACHINE_FREAKOUT;
}
}

@ -34,6 +34,7 @@
#include "stm32f4xx_hal.h"
#include "stm32f4xx.h"
#include "interrupts.h"
#include "led.h"
/* External variables --------------------------------------------------------*/
@ -51,6 +52,7 @@ extern DMA_HandleTypeDef hdma_spi1_tx;
void SysTick_Handler(void)
{
HAL_IncTick();
LED_DoBlinks();
}
/******************************************************************************/

@ -0,0 +1,62 @@
/*
* led.c
*
* Created on: 19/08/2015
* Author: Robert Fisk
*/
#include "stm32f4xx_hal.h"
#include "led.h"
#include "board_config.h"
uint16_t FaultLedBlinkRate = 0;
uint16_t FaultLedBlinkCounter = 0;
uint8_t FaultLedState = 0;
void LED_Init(void)
{
//RUN_LED_ON;
FAULT_LED_ON;
HAL_Delay(STARTUP_FLASH_DELAY);
//RUN_LED_OFF;
FAULT_LED_OFF;
}
void LED_Fault_SetBlinkRate(uint16_t newBlinkRate)
{
FaultLedBlinkRate = newBlinkRate;
if (newBlinkRate == 0)
{
FaultLedState = 0;
FAULT_LED_OFF;
}
}
void LED_DoBlinks(void)
{
if (FaultLedBlinkRate > 0)
{
FaultLedBlinkCounter++;
if (FaultLedBlinkCounter >= FaultLedBlinkRate)
{
FaultLedBlinkCounter = 0;
if (FaultLedState)
{
FaultLedState = 0;
FAULT_LED_OFF;
}
else
{
FaultLedState = 1;
FAULT_LED_ON;
}
}
}
}

@ -31,10 +31,11 @@
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <downstream_spi.h>
#include "stm32f4xx_hal.h"
#include "usb_host.h"
#include "board_config.h"
#include "downstream_statemachine.h"
#include "led.h"
@ -46,8 +47,6 @@ static void GPIO_Init(void);
int main(void)
{
/* MCU Configuration----------------------------------------------------------*/
/* Configure the system clock */
SystemClock_Config();
@ -56,9 +55,10 @@ int main(void)
/* Initialize all configured peripherals */
GPIO_Init();
LED_Init();
USB_Host_Init();
Downstream_InitSPI();
Downstream_InitStateMachine();
while (1)
{

Loading…
Cancel
Save