diff --git a/Downstream/Inc/downstream_interface_def.h b/Downstream/Inc/downstream_interface_def.h index 5121572..5c1c85f 100644 --- a/Downstream/Inc/downstream_interface_def.h +++ b/Downstream/Inc/downstream_interface_def.h @@ -49,5 +49,13 @@ typedef enum InterfaceCommandMscTypeDef; +typedef enum +{ + COMMAND_ERROR_GENERIC, + COMMAND_ERROR_DEVICE_DISCONNECTED, +} +InterfaceCommandErrorTypeDef; + + #endif /* INC_DOWNSTREAM_INTERFACE_DEF_H_ */ diff --git a/Downstream/Inc/downstream_spi.h b/Downstream/Inc/downstream_spi.h index a2c0296..9542e4a 100644 --- a/Downstream/Inc/downstream_spi.h +++ b/Downstream/Inc/downstream_spi.h @@ -17,22 +17,12 @@ #define DOWNSTREAM_PACKET_LEN_MIN (DOWNSTREAM_PACKET_HEADER_LEN) -#define DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID \ - do { \ - LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \ - Downstream_PacketProcessor_SetErrorState(); \ - DownstreamInterfaceState = DOWNSTREAM_INTERFACE_ERROR; \ - while (1); \ - /*return;*/ \ - } while (0); - -#define DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR \ - do { \ - LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \ - Downstream_PacketProcessor_SetErrorState(); \ - DownstreamInterfaceState = DOWNSTREAM_INTERFACE_ERROR; \ - while (1); \ - /*return HAL_ERROR;*/ \ +#define DOWNSTREAM_SPI_FREAKOUT \ + do { \ + LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \ + Downstream_PacketProcessor_SetErrorState(); \ + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_ERROR; \ + while (1); \ } while (0); diff --git a/Downstream/Inc/downstream_statemachine.h b/Downstream/Inc/downstream_statemachine.h index ed644d0..8519826 100644 --- a/Downstream/Inc/downstream_statemachine.h +++ b/Downstream/Inc/downstream_statemachine.h @@ -25,14 +25,6 @@ typedef enum #define DOWNSTREAM_STATEMACHINE_FREAKOUT \ - do { \ - LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \ - DownstreamState = STATE_ERROR; \ - return; \ -} while (0); - - -#define DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN \ do { \ LED_Fault_SetBlinkRate(LED_FAST_BLINK_RATE); \ DownstreamState = STATE_ERROR; \ @@ -44,7 +36,7 @@ typedef enum 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_GenericErrorReply(DownstreamPacketTypeDef* replyPacket); void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket); void Downstream_PacketProcessor_SetErrorState(void); void Downstream_PacketProcessor_FreakOut(void); diff --git a/Downstream/Src/downstream_msc.c b/Downstream/Src/downstream_msc.c index e32ace2..3c89941 100644 --- a/Downstream/Src/downstream_msc.c +++ b/Downstream/Src/downstream_msc.c @@ -151,7 +151,7 @@ void Downstream_MSC_PacketProcessor_RdWrCompleteCallback(USBH_StatusTypeDef resu { if (result != USBH_OK) { - Downstream_GetFreePacket(Downstream_PacketProcessor_ErrorReply); + Downstream_GetFreePacket(Downstream_PacketProcessor_GenericErrorReply); return; } Downstream_ReceivePacket(Downstream_PacketProcessor); diff --git a/Downstream/Src/downstream_spi.c b/Downstream/Src/downstream_spi.c index b02b640..c330b3c 100644 --- a/Downstream/Src/downstream_spi.c +++ b/Downstream/Src/downstream_spi.c @@ -26,7 +26,7 @@ SpiPacketReceivedCallbackTypeDef ReceivePacketCallback = NULL; //Indicates some HAL_StatusTypeDef Downstream_CheckPreparePacketReception(void); -void Downstream_PreparePacketReception(DownstreamPacketTypeDef* freePacket); +void Downstream_PrepareReceivePacketSize(DownstreamPacketTypeDef* freePacket); @@ -62,7 +62,8 @@ HAL_StatusTypeDef Downstream_GetFreePacket(FreePacketCallbackTypeDef callback) //Do we already have a queued callback? if (PendingFreePacketCallback != NULL) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR; + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; } //Check if there is a free buffer now @@ -98,7 +99,8 @@ void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease) if ((packetToRelease != &DownstreamPacket0) && (packetToRelease != &DownstreamPacket1)) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } if (PendingFreePacketCallback != NULL) @@ -125,10 +127,14 @@ HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef call return HAL_ERROR; } - if (ReceivePacketCallback != NULL) + if ((DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_SIZE_WAIT) || + (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_RX_PACKET_WAIT) || + (ReceivePacketCallback != NULL)) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR; + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; } + ReceivePacketCallback = callback; return Downstream_CheckPreparePacketReception(); } @@ -137,21 +143,32 @@ HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef call //Internal use only HAL_StatusTypeDef Downstream_CheckPreparePacketReception(void) { + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return HAL_ERROR; + } + if (DownstreamInterfaceState == DOWNSTREAM_INTERFACE_IDLE) { DownstreamInterfaceState = DOWNSTREAM_INTERFACE_RX_SIZE_WAIT; - return Downstream_GetFreePacket(Downstream_PreparePacketReception); + return Downstream_GetFreePacket(Downstream_PrepareReceivePacketSize); } return HAL_OK; } //Internal use only -void Downstream_PreparePacketReception(DownstreamPacketTypeDef* freePacket) +void Downstream_PrepareReceivePacketSize(DownstreamPacketTypeDef* freePacket) { + if (DownstreamInterfaceState >= DOWNSTREAM_INTERFACE_ERROR) + { + return; + } + if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_RX_SIZE_WAIT) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } CurrentWorkingPacket = freePacket; //CurrentWorkingPacket->Length = 0; @@ -160,7 +177,8 @@ 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" { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } UPSTREAM_TX_REQUEST_ASSERT; @@ -185,14 +203,16 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) if ((CurrentWorkingPacket->Length < DOWNSTREAM_PACKET_LEN_MIN) || (CurrentWorkingPacket->Length > DOWNSTREAM_PACKET_LEN)) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } 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" { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } UPSTREAM_TX_REQUEST_ASSERT; return; @@ -203,7 +223,8 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE; if (ReceivePacketCallback == NULL) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } //Packet processor may want to receive another packet immediately, //so clear ReceivePacketCallback before the call. @@ -214,7 +235,8 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) return; } - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + //case default: + DOWNSTREAM_SPI_FREAKOUT; } @@ -233,17 +255,20 @@ HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWri if ((packetToWrite != &DownstreamPacket0) && (packetToWrite != &DownstreamPacket1)) { - DOWNSTREAM_SPI_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)) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR; + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; } if (NextTxPacket != NULL) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR; + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; } switch (DownstreamInterfaceState) @@ -261,13 +286,15 @@ 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" { - DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR; + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; } UPSTREAM_TX_REQUEST_ASSERT; break; default: - DOWNSTREAM_SPI_FREAKOUT_RETURN_HAL_ERROR; + DOWNSTREAM_SPI_FREAKOUT; + return HAL_ERROR; } return HAL_OK; @@ -289,14 +316,16 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_TX_SIZE_WAIT) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } 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... - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_PACKET_WAIT; @@ -304,7 +333,8 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) &CurrentWorkingPacket->CommandClass, CurrentWorkingPacket->Length)) != HAL_OK) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } UPSTREAM_TX_REQUEST_ASSERT; } @@ -323,7 +353,8 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_TX_PACKET_WAIT) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } Downstream_ReleasePacket(CurrentWorkingPacket); @@ -339,7 +370,8 @@ 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" { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; + return; } UPSTREAM_TX_REQUEST_ASSERT; return; @@ -357,6 +389,6 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) //Something bad happened! Possibly CRC error... void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) { - DOWNSTREAM_SPI_FREAKOUT_RETURN_VOID; + DOWNSTREAM_SPI_FREAKOUT; } diff --git a/Downstream/Src/downstream_statemachine.c b/Downstream/Src/downstream_statemachine.c index 157ead3..ab2f1e0 100644 --- a/Downstream/Src/downstream_statemachine.c +++ b/Downstream/Src/downstream_statemachine.c @@ -43,21 +43,38 @@ void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) return; } - switch (receivedPacket->CommandClass) + if (receivedPacket->CommandClass == COMMAND_CLASS_INTERFACE) { - case COMMAND_CLASS_INTERFACE: if (DownstreamState > STATE_DEVICE_READY) { DOWNSTREAM_STATEMACHINE_FREAKOUT; + return; } Downstream_PacketProcessor_Interface(receivedPacket); - break; + return; + } + //If we get a class-specific message when our device is disconnected, + //we need to tell Upstream of the fact (and not freak out). + if (DownstreamState == STATE_DEVICE_NOT_READY) + { + receivedPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN; + receivedPacket->CommandClass = COMMAND_CLASS_ERROR; + receivedPacket->Command = COMMAND_ERROR_DEVICE_DISCONNECTED; + Downstream_PacketProcessor_ClassReply(receivedPacket); + return; + } + + //We should only receive class-specific messages when we are in the Active state. + if (DownstreamState != STATE_ACTIVE) + { + DOWNSTREAM_STATEMACHINE_FREAKOUT; + return; + } + + switch (receivedPacket->CommandClass) + { case COMMAND_CLASS_MASS_STORAGE: - if (DownstreamState != STATE_ACTIVE) - { - DOWNSTREAM_STATEMACHINE_FREAKOUT; - } Downstream_MSC_PacketProcessor(receivedPacket); break; @@ -89,11 +106,9 @@ void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacke switch (receivedPacket->Command) { case COMMAND_INTERFACE_ECHO: - if (Downstream_TransmitPacket(receivedPacket) == HAL_OK) - { - Downstream_ReceivePacket(Downstream_PacketProcessor); - } - return; + Downstream_TransmitPacket(receivedPacket); + Downstream_ReceivePacket(Downstream_PacketProcessor); + break; case COMMAND_INTERFACE_NOTIFY_DEVICE: if (DownstreamState == STATE_DEVICE_READY) @@ -109,7 +124,7 @@ void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacke return; } DOWNSTREAM_STATEMACHINE_FREAKOUT; - return; + break; default: @@ -133,24 +148,21 @@ void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketType } -void Downstream_PacketProcessor_ErrorReply(DownstreamPacketTypeDef* replyPacket) +void Downstream_PacketProcessor_GenericErrorReply(DownstreamPacketTypeDef* replyPacket) { replyPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN; replyPacket->CommandClass = COMMAND_CLASS_ERROR; + replyPacket->Command = COMMAND_ERROR_GENERIC; - if (Downstream_TransmitPacket(replyPacket) == HAL_OK) - { - Downstream_ReceivePacket(Downstream_PacketProcessor); - } + Downstream_TransmitPacket(replyPacket); + Downstream_ReceivePacket(Downstream_PacketProcessor); } void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket) { - if (Downstream_TransmitPacket(replyPacket) == HAL_OK) - { - Downstream_ReceivePacket(Downstream_PacketProcessor); - } + Downstream_TransmitPacket(replyPacket); + Downstream_ReceivePacket(Downstream_PacketProcessor); } @@ -173,14 +185,12 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) return; } - //Elevate our priority level so we aren't interrupted - __set_BASEPRI(INT_PRIORITY_OTG_FS); - + __set_BASEPRI(INT_PRIORITY_OTG_FS); //Elevate our priority level so we aren't interrupted //Called from main() if (id == HOST_USER_UNRECOVERED_ERROR) { - DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN; + DOWNSTREAM_STATEMACHINE_FREAKOUT; __set_BASEPRI(0); return; } @@ -212,7 +222,7 @@ 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_NORETURN; + DOWNSTREAM_STATEMACHINE_FREAKOUT; __set_BASEPRI(0); return; } @@ -222,7 +232,7 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) && (ConfiguredDeviceClass != newActiveClass)) { - DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN; + DOWNSTREAM_STATEMACHINE_FREAKOUT; __set_BASEPRI(0); return; } @@ -242,7 +252,7 @@ void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id) return; } - DOWNSTREAM_STATEMACHINE_FREAKOUT_NORETURN; + DOWNSTREAM_STATEMACHINE_FREAKOUT; __set_BASEPRI(0); return; } diff --git a/Upstream/Inc/upstream_interface_def.h b/Upstream/Inc/upstream_interface_def.h index 24e12de..0745d8c 100644 --- a/Upstream/Inc/upstream_interface_def.h +++ b/Upstream/Inc/upstream_interface_def.h @@ -51,4 +51,13 @@ typedef enum InterfaceCommandMscTypeDef; +typedef enum +{ + COMMAND_ERROR_GENERIC, + COMMAND_ERROR_DEVICE_DISCONNECTED, +} +InterfaceCommandErrorTypeDef; + + + #endif /* INC_UPSTREAM_INTERFACE_DEF_H_ */ diff --git a/Upstream/Inc/upstream_spi.h b/Upstream/Inc/upstream_spi.h index ba1dd00..22241c7 100644 --- a/Upstream/Inc/upstream_spi.h +++ b/Upstream/Inc/upstream_spi.h @@ -27,7 +27,6 @@ - typedef enum { UPSTREAM_INTERFACE_IDLE, diff --git a/Upstream/Inc/upstream_statemachine.h b/Upstream/Inc/upstream_statemachine.h index 8c16c81..53c64fe 100644 --- a/Upstream/Inc/upstream_statemachine.h +++ b/Upstream/Inc/upstream_statemachine.h @@ -33,6 +33,7 @@ typedef enum void Upstream_InitStateMachine(void); void Upstream_StateMachine_SetErrorState(void); HAL_StatusTypeDef Upstream_StateMachine_CheckClassOperationOk(void); +void Upstream_StateMachine_DeviceDisconnected(void); diff --git a/Upstream/Src/upstream_spi.c b/Upstream/Src/upstream_spi.c index 52c79bf..f7ecee6 100644 --- a/Upstream/Src/upstream_spi.c +++ b/Upstream/Src/upstream_spi.c @@ -24,12 +24,16 @@ InterfaceStateTypeDef UpstreamInterfaceState = UPSTREAM_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 +uint8_t TxOkInterruptReceived = 0; uint8_t SentCommandClass; uint8_t SentCommand; -static HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void); -static void Upstream_BeginPacketReception(UpstreamPacketTypeDef* freePacket); +void Upstream_BeginTransmitPacketSize(void); +void Upstream_BeginTransmitPacketBody(void); +HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void); +void Upstream_BeginReceivePacketSize(UpstreamPacketTypeDef* freePacket); +void Upstream_BeginReceivePacketBody(void); @@ -191,6 +195,14 @@ HAL_StatusTypeDef Upstream_TransmitPacket(UpstreamPacketTypeDef* packetToWrite) CurrentWorkingPacket = packetToWrite; SentCommandClass = CurrentWorkingPacket->CommandClass; SentCommand = CurrentWorkingPacket->Command; + + //Downstream may have set TxOk pin before we wanted to transmit. + //In this case we can go ahead and transmit now. + if (TxOkInterruptReceived) + { + TxOkInterruptReceived = 0; + Upstream_BeginTransmitPacketSize(); + } break; default: @@ -217,6 +229,11 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) if (UpstreamInterfaceState == UPSTREAM_INTERFACE_TX_SIZE) { UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_PACKET_WAIT; + if (TxOkInterruptReceived) + { + TxOkInterruptReceived = 0; + Upstream_BeginTransmitPacketBody(); + } return; } @@ -241,6 +258,11 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE_WAIT; CurrentWorkingPacket = NextTxPacket; NextTxPacket = NULL; + if (TxOkInterruptReceived) + { + TxOkInterruptReceived = 0; + Upstream_BeginTransmitPacketSize(); + } return; } @@ -286,7 +308,7 @@ HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void) return HAL_ERROR; } - if (UpstreamInterfaceState > UPSTREAM_INTERFACE_RX_SIZE_WAIT) + if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_RX_SIZE_WAIT) { UPSTREAM_SPI_FREAKOUT; return HAL_ERROR; @@ -295,6 +317,11 @@ HAL_StatusTypeDef Upstream_CheckBeginPacketReception(void) if (UpstreamInterfaceState == UPSTREAM_INTERFACE_IDLE) { UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_SIZE_WAIT; + if (TxOkInterruptReceived) + { + TxOkInterruptReceived = 0; + Upstream_GetFreePacket(Upstream_BeginReceivePacketSize); + } } return HAL_OK; } @@ -311,41 +338,24 @@ void Upstream_TxOkInterrupt(void) switch (UpstreamInterfaceState) { + case UPSTREAM_INTERFACE_IDLE: + TxOkInterruptReceived = 1; + break; + case UPSTREAM_INTERFACE_TX_SIZE_WAIT: - UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE; - SPI1_NSS_ASSERT; - if (HAL_SPI_Transmit_DMA(&Hspi1, - (uint8_t*)&CurrentWorkingPacket->Length, - 2) != HAL_OK) - { - UPSTREAM_SPI_FREAKOUT; - } + Upstream_BeginTransmitPacketSize(); break; case UPSTREAM_INTERFACE_TX_PACKET_WAIT: - UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_PACKET; - SPI1_NSS_ASSERT; - if ((HAL_SPI_Transmit_DMA(&Hspi1, - &CurrentWorkingPacket->CommandClass, - CurrentWorkingPacket->Length)) != HAL_OK) - { - UPSTREAM_SPI_FREAKOUT; - } + Upstream_BeginTransmitPacketBody(); break; case UPSTREAM_INTERFACE_RX_SIZE_WAIT: - Upstream_GetFreePacket(Upstream_BeginPacketReception); + Upstream_GetFreePacket(Upstream_BeginReceivePacketSize); break; case UPSTREAM_INTERFACE_RX_PACKET_WAIT: - UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_PACKET; - SPI1_NSS_ASSERT; - 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" - { - UPSTREAM_SPI_FREAKOUT; - } + Upstream_BeginReceivePacketBody(); break; default: @@ -354,9 +364,35 @@ void Upstream_TxOkInterrupt(void) } +void Upstream_BeginTransmitPacketSize(void) +{ + UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE; + SPI1_NSS_ASSERT; + if (HAL_SPI_Transmit_DMA(&Hspi1, + (uint8_t*)&CurrentWorkingPacket->Length, + 2) != HAL_OK) + { + UPSTREAM_SPI_FREAKOUT; + } +} + + +void Upstream_BeginTransmitPacketBody(void) +{ + UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_PACKET; + SPI1_NSS_ASSERT; + if ((HAL_SPI_Transmit_DMA(&Hspi1, + &CurrentWorkingPacket->CommandClass, + CurrentWorkingPacket->Length)) != HAL_OK) + { + UPSTREAM_SPI_FREAKOUT; + } +} + + //Internal use only. //Called when we want to receive downstream packet, and a packet buffer has become free. -void Upstream_BeginPacketReception(UpstreamPacketTypeDef* freePacket) +void Upstream_BeginReceivePacketSize(UpstreamPacketTypeDef* freePacket) { if (UpstreamInterfaceState >= UPSTREAM_INTERFACE_ERROR) { @@ -381,6 +417,19 @@ void Upstream_BeginPacketReception(UpstreamPacketTypeDef* freePacket) } +void Upstream_BeginReceivePacketBody(void) +{ + UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_PACKET; + SPI1_NSS_ASSERT; + 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" + { + UPSTREAM_SPI_FREAKOUT; + } +} + + //Called at the end of the SPI RX DMA transfer, //at DMA2 interrupt priority. Assume *hspi points to our hspi1. void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) @@ -403,20 +452,34 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) return; } UpstreamInterfaceState = UPSTREAM_INTERFACE_RX_PACKET_WAIT; + if (TxOkInterruptReceived) + { + TxOkInterruptReceived = 0; + Upstream_BeginReceivePacketBody(); + } return; } if (UpstreamInterfaceState == UPSTREAM_INTERFACE_RX_PACKET) { + UpstreamInterfaceState = UPSTREAM_INTERFACE_IDLE; if (ReceivePacketCallback == NULL) { UPSTREAM_SPI_FREAKOUT; return; } - UpstreamInterfaceState = UPSTREAM_INTERFACE_IDLE; - if ((SentCommandClass != (CurrentWorkingPacket->CommandClass & COMMAND_CLASS_MASK)) || - (SentCommand != CurrentWorkingPacket->Command)) + if ((CurrentWorkingPacket->CommandClass == COMMAND_CLASS_ERROR) && + (CurrentWorkingPacket->Command == COMMAND_ERROR_DEVICE_DISCONNECTED)) + { + Upstream_ReleasePacket(CurrentWorkingPacket); + ReceivePacketCallback = NULL; + Upstream_StateMachine_DeviceDisconnected(); + return; + } + + if (((CurrentWorkingPacket->CommandClass & COMMAND_CLASS_MASK) != SentCommandClass) || + (CurrentWorkingPacket->Command != SentCommand)) { UPSTREAM_SPI_FREAKOUT; Upstream_ReleasePacket(CurrentWorkingPacket); diff --git a/Upstream/Src/upstream_statemachine.c b/Upstream/Src/upstream_statemachine.c index 90f01be..bf66935 100644 --- a/Upstream/Src/upstream_statemachine.c +++ b/Upstream/Src/upstream_statemachine.c @@ -14,12 +14,13 @@ #include "usbd_msc.h" -UpstreamStateTypeDef UpstreamState = STATE_TEST_INTERFACE; -InterfaceCommandClassTypeDef ActiveDeviceClass = COMMAND_CLASS_INTERFACE; +UpstreamStateTypeDef UpstreamState = STATE_TEST_INTERFACE; +InterfaceCommandClassTypeDef ConfiguredDeviceClass = COMMAND_CLASS_INTERFACE; -void Upstream_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket); -void Upstream_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket); +void Upstream_StateMachine_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket); +void Upstream_StateMachine_NotifyDevice(UpstreamPacketTypeDef* freePacket); +void Upstream_StateMachine_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket); @@ -42,9 +43,9 @@ void Upstream_InitStateMachine(void) freePacket->Length = UPSTREAM_PACKET_HEADER_LEN + MSC_MEDIA_PACKET; freePacket->CommandClass = COMMAND_CLASS_INTERFACE; freePacket->Command = COMMAND_INTERFACE_ECHO; - testDataValue = 0xFF; //Fill our test packet with some junk + testDataValue = 0xFF; for (i = 0; i < MSC_MEDIA_PACKET; i++) { freePacket->Data[i] = testDataValue; @@ -53,7 +54,7 @@ void Upstream_InitStateMachine(void) if (Upstream_TransmitPacket(freePacket) == HAL_OK) { - Upstream_ReceivePacket(Upstream_TestInterfaceReplyCallback); + Upstream_ReceivePacket(Upstream_StateMachine_TestInterfaceReplyCallback); } } @@ -62,8 +63,8 @@ void Upstream_InitStateMachine(void) void Upstream_StateMachine_SetErrorState(void) { UpstreamState = STATE_ERROR; - if ((ActiveDeviceClass > COMMAND_CLASS_INTERFACE) && - (ActiveDeviceClass < COMMAND_CLASS_ERROR)) + if ((ConfiguredDeviceClass > COMMAND_CLASS_INTERFACE) && + (ConfiguredDeviceClass < COMMAND_CLASS_ERROR)) { USBD_Stop(&hUsbDeviceFS); } @@ -87,7 +88,7 @@ HAL_StatusTypeDef Upstream_StateMachine_CheckClassOperationOk(void) } -void Upstream_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket) +void Upstream_StateMachine_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket) { uint16_t i; uint8_t testDataValue; @@ -121,21 +122,29 @@ void Upstream_TestInterfaceReplyCallback(UpstreamPacketTypeDef* replyPacket) testDataValue += 39; } - //SPI interface passed checks. Now we wait for a device to be attached to downstream. + Upstream_StateMachine_NotifyDevice(replyPacket); +} + + +void Upstream_StateMachine_NotifyDevice(UpstreamPacketTypeDef* freePacket) +{ UpstreamState = STATE_WAIT_DEVICE; - replyPacket->Length = UPSTREAM_PACKET_HEADER_LEN; - replyPacket->CommandClass = COMMAND_CLASS_INTERFACE; - replyPacket->Command = COMMAND_INTERFACE_NOTIFY_DEVICE; - if (Upstream_TransmitPacket(replyPacket) == HAL_OK) + freePacket->Length = UPSTREAM_PACKET_HEADER_LEN; + freePacket->CommandClass = COMMAND_CLASS_INTERFACE; + freePacket->Command = COMMAND_INTERFACE_NOTIFY_DEVICE; + if (Upstream_TransmitPacket(freePacket) == HAL_OK) { - Upstream_ReceivePacket(Upstream_NotifyDeviceReplyCallback); + Upstream_ReceivePacket(Upstream_StateMachine_NotifyDeviceReplyCallback); } } -void Upstream_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket) +void Upstream_StateMachine_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket) { + InterfaceCommandClassTypeDef newActiveClass = COMMAND_CLASS_INTERFACE; + USBD_ClassTypeDef* newClassPointer; + if (UpstreamState >= STATE_ERROR) { return; @@ -157,20 +166,47 @@ void Upstream_NotifyDeviceReplyCallback(UpstreamPacketTypeDef* replyPacket) switch (replyPacket->Data[0]) { case COMMAND_CLASS_MASS_STORAGE: - USBD_RegisterClass(&hUsbDeviceFS, &USBD_MSC); + newActiveClass = COMMAND_CLASS_MASS_STORAGE; + newClassPointer = &USBD_MSC; break; - default: + //Add other supported classes here... + } + + if (newActiveClass == COMMAND_CLASS_INTERFACE) + { + UPSTREAM_STATEMACHINE_FREAKOUT; + return; + } + + //Downstream should never change the active device class without rebooting! + if ((ConfiguredDeviceClass != COMMAND_CLASS_INTERFACE) && + (ConfiguredDeviceClass != newActiveClass)) + { UPSTREAM_STATEMACHINE_FREAKOUT; return; } - USBD_Start(&hUsbDeviceFS); UpstreamState = STATE_DEVICE_ACTIVE; - ActiveDeviceClass = replyPacket->Data[0]; + ConfiguredDeviceClass = newActiveClass; + USBD_RegisterClass(&hUsbDeviceFS, newClassPointer); + USBD_Start(&hUsbDeviceFS); //The USB device stack will now receive commands from our host. - //All we need to do is check for downstream device removal. + //All we need to do is monitor for downstream device disconnection. } +void Upstream_StateMachine_DeviceDisconnected(void) +{ + if ((ConfiguredDeviceClass == COMMAND_CLASS_INTERFACE) || + (ConfiguredDeviceClass >= COMMAND_CLASS_ERROR)) + { + UPSTREAM_STATEMACHINE_FREAKOUT; + return; + } + + USBD_Stop(&hUsbDeviceFS); + Upstream_GetFreePacket(Upstream_StateMachine_NotifyDevice); +} +