Urgent Help Needed: USB CDC Transmit Stuck, hcdc->TxState Never Resets!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-28 5:34 AM
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.
Solved! Go to Solution.
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-01 7:23 AM
Hi @AChap.1
Which Cube firmware revision are you using? 1.18.0? If I understand correctly, you are using Putty to print from STM32 using UART?
I think if all necessary endpoints are properly initialized in your code, you would not face this issue.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-28 10:29 AM
Hello @AChap.1
I was wondering if you have already tried to use the example project provided.
Could you watch in live debug your data struct hUsbDeviceFS while setting transmission buffer and its length then while starting the transmission. I guess Len should be uint32_t.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-28 11:12 AM - edited ‎2024-02-29 12:58 AM
Hi @FBL,
I managed to find the ST Open Bootloader after you mentioned examples.
However, this is for the STM32G0. Are there similar examples for STM32L4?
Thanks,
Adrian.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-28 12:32 PM - edited ‎2024-02-29 12:59 AM
Hi @FBL,
Regarding observing the data struct hUsbDeviceFS:
At the point of this line of code: USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
This is the structure:
Name : hUsbDeviceFS
Details:{id = 0 '\0', dev_config = 1, dev_default_config = 0, dev_config_status = 0, dev_speed = USBD_SPEED_FULL, ep_in = {{status = 0, total_length = 7, rem_length = 7, maxpacket = 64, is_used = 1, bInterval = 0}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 1, bInterval = 0}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 1, bInterval = 16}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 0, bInterval = 0} <repeats 13 times>}, ep_out = {{status = 0, total_length = 7, rem_length = 7, maxpacket = 64, is_used = 1, bInterval = 0}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 1, bInterval = 0}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 0, bInterval = 0} <repeats 14 times>}, ep0_state = 5, ep0_data_len = 7, dev_state = 3 '\003', dev_old_state = 1 '\001', dev_address = 12 '\f', dev_connection_status = 0 '\0', dev_test_mode = 0 '\0', dev_remote_wakeup = 0, ConfIdx = 0 '\0', request = {bmRequest = 161 '¡', bRequest = 33 '!', wValue = 0, wIndex = 0, wLength = 7}, pDesc = 0x20000150 <FS_Desc>, pClass = 0x20000038 <USBD_CDC>, pClassData = 0x20001c0c <mem>, pUserData = 0x2000013c <USBD_Interface_fops_FS>, pData = 0x20001700 <hpcd_USB_OTG_FS>, pBosDesc = 0x0, pConfDesc = 0x200000b4 <USBD_CDC_CfgFSDesc>}
At the point of this line of code: result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
This is the structure:
Name : hUsbDeviceFS
Details:{id = 0 '\0', dev_config = 1, dev_default_config = 0, dev_config_status = 0, dev_speed = USBD_SPEED_FULL, ep_in = {{status = 0, total_length = 7, rem_length = 7, maxpacket = 64, is_used = 1, bInterval = 0}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 1, bInterval = 0}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 1, bInterval = 16}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 0, bInterval = 0} <repeats 13 times>}, ep_out = {{status = 0, total_length = 7, rem_length = 7, maxpacket = 64, is_used = 1, bInterval = 0}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 1, bInterval = 0}, {status = 0, total_length = 0, rem_length = 0, maxpacket = 0, is_used = 0, bInterval = 0} <repeats 14 times>}, ep0_state = 5, ep0_data_len = 7, dev_state = 3 '\003', dev_old_state = 1 '\001', dev_address = 12 '\f', dev_connection_status = 0 '\0', dev_test_mode = 0 '\0', dev_remote_wakeup = 0, ConfIdx = 0 '\0', request = {bmRequest = 161 '¡', bRequest = 33 '!', wValue = 0, wIndex = 0, wLength = 7}, pDesc = 0x20000150 <FS_Desc>, pClass = 0x20000038 <USBD_CDC>, pClassData = 0x20001c0c <mem>, pUserData = 0x2000013c <USBD_Interface_fops_FS>, pData = 0x20001700 <hpcd_USB_OTG_FS>, pBosDesc = 0x0, pConfDesc = 0x200000b4 <USBD_CDC_CfgFSDesc>}
I have to admit, I’m not sure what I’m looking for, as I’m not familiar with the low level workings of the USB peripheral.
I hope it sheds some light on the problem.
Thanks,
Adrian.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-29 8:57 AM
Hello @AChap.1
Applications shared for now, apart from FAQ article, based on the Open Bootloader library are : STM32L5 STM325WB and STM32WL See here
About hUsbDeviceFS, it is the same structure shared. I suggest you checking section 6.5.6 How to use UM1734_STM32Cube.book
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-29 2:54 PM
Is the messageHandler() routine called from CDC reception callback? If so, then 1. it cannot wait for the timer. 2: It cannot wait for any USB context change since the change may only occur as a result of USB interrupt.
On the other hand, if it is called from main, then calling CDC_Transmit() from it will sooner or later cause the USB stack to hang.
;)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-01 4:04 AM
Thanks @gbm for the suggestion on handling USB communications in a non-blocking manner. Based on what you mentioned, I'm thinking about integrating an event-driven approach where data transmission is attempted only when the USB isn't busy. Here's a quick outline of what I'm considering:
if (usbDataReady && (hcdc->TxState == 0)) {
CDC_Transmit_FS(dataBuffer, dataLength);
usbDataReady = false; // Reset flag after attempting transmission
}
This seems like a practical way to keep the bootloader lean while managing USB tasks efficiently. Appreciate the input.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-01 5:12 AM
Hello @FBL
Thank you for detailing the specific applications of the Open Bootloader library. I observed that the provided examples primarily cater to the STM32L5, STM32WB, and STM32WL series. Despite the absence of an STM32L4 series example, I'm keen to know if the Open Bootloader could still be adapted for the STM32L476RET6.
Regarding the USB communication issues, based on the documentation you shared, I've thoroughly reviewed the setup. This prompted me to consider the possibility of an underlying issue within the HAL code. Upon discovering an update for the STM32L4 series, I was hopeful it might rectify the problem. However, post-update, my device no longer connects to PuTTY as it previously did, despite no alterations to settings or code.
Considering successful USB CDC communication implementations with similar STM32 models by others, I'm inclined to suspect the issue might originate from my side. I would value any insights or advice you might offer on this matter.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-01 7:23 AM
Hi @AChap.1
Which Cube firmware revision are you using? 1.18.0? If I understand correctly, you are using Putty to print from STM32 using UART?
I think if all necessary endpoints are properly initialized in your code, you would not face this issue.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-03-03 7:46 AM
Hi @FBL
I've started a new project with Cube version 1.18.0, and it works.
Thank you for your help, and let everyone know I really appreciate the work you all do.
Adrian.
