Urgent Help Needed: USB CDC Transmit Stuck, hcdc->TxState Never Resets!
Hello ST Community,
I'm developing a USB CDC communication project on an STM32L476RET6 microcontroller, using STM32CubeIDE. While I can successfully receive data from a PC using PuTTY, I'm facing a challenge with transmitting data back to the PC using the CDC_Transmit_FS function.
Environment:
- MCU: STM32L476RET6
- IDE: STM32CubeIDE
- USB Configuration: Configured as a CDC Virtual COM Port
- OS: Windows 10
Issue Description: Data reception from the PC works flawlessly. However, when attempting to transmit data back using CDC_Transmit_FS, the function seems to never complete. The code gets indefinitely stuck waiting for hcdc->TxState to reset to 0, which, based on my understanding, should happen via an interrupt once the transmission completes.
Troubleshooting Done:
- Confirmed correct USB descriptor configurations.
- Debugged to pinpoint that the halt occurs during data transmission, specifically waiting for hcdc->TxState to reset.
Questions:
- Are there any known issues with USB CDC on STM32L476RET6 that might cause this behaviour?
- Could there be any CubeMX configuration or USER CODE that I might have overlooked that could lead to this issue?
I've attached relevant code snippets for context. The problem arises when sending the "FLASHING_START" command, which is successfully received by the STM32, but any subsequent attempt to send data back to the PC doesn't complete.
Code Snippets:
Message Handler:
void messageHandler(uint8_t* Buf)
{
if(string_compare((char*)Buf, ERASE_FLASH_MEMORY, strlen(ERASE_FLASH_MEMORY))
&& flashStatus != Unlocked)
{
eraseMemory();
CDC_Transmit_FS((uint8_t*)"Flash: Erased!\n", strlen("Flash: Erased!\n"));
}else if(string_compare((char*)Buf, FLASHING_START, strlen(FLASHING_START)))
{
CDC_Transmit_FS((uint8_t*)"Can we print some text?\n", strlen("Can we print some text?\n")); // THIS IS WHERE ALL MY PROBLEMS BEGIN
unlockFlashAndEraseMemory();
CDC_Transmit_FS((uint8_t*)"Flash: Unlocked!\n", strlen("Flash: Unlocked!\n"));
}else if(string_compare((char*)Buf, FLASHING_FINISH, strlen(FLASHING_FINISH))
&& flashStatus == Unlocked)
{
lockFlash();
CDC_Transmit_FS((uint8_t*)"Flash: Success!\n", strlen("Flash: Success!\n"));
}else if(string_compare((char*)Buf, FLASHING_ABORT, strlen(FLASHING_ABORT))
&& flashStatus == Unlocked)
{
lockFlash();
eraseMemory();
CDC_Transmit_FS((uint8_t*)"Flash: Aborted!\n", strlen("Flash: Aborted!\n"));
}else
{
CDC_Transmit_FS((uint8_t*)"Error: Incorrect step or unknown command!\n",
strlen("Error: Incorrect step or unknown command!\n"));
}
}
CDC Transmit Function:
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
uint32_t startTick = HAL_GetTick();
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc == NULL) {
return USBD_FAIL;
}
// Wait for previous transmission to complete or for timeout
while (hcdc->TxState != 0) {
// Check for timeout
if ((HAL_GetTick() - startTick) > CDC_TRANSMIT_TIMEOUT_MS) {
return USBD_FAIL; // Transmission timed out
}
}
// Set the transmission buffer and length
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
// Start the transmission
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
if (result == USBD_OK) {
// Wait for transmission to complete or for timeout
startTick = HAL_GetTick();
while (hcdc->TxState != 0) { // THIS NEVER RESETS TO ZERO!
// Check for timeout
if ((HAL_GetTick() - startTick) > CDC_TRANSMIT_TIMEOUT_MS) {
return USBD_FAIL; // Transmission timed out
}
}
}
/* USER CODE END 7 */
return result;
}
Any insights or recommendations from the community would be immensely appreciated.
Thank you for your support!
Adrian.
