2024-02-28 05: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:
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:
Questions:
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.
2024-03-01 07: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.
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.
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.
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.
2024-02-29 08: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.
2024-02-29 02: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.
;)
2024-03-01 04: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.
2024-03-01 05: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.
2024-03-01 07: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.
2024-03-03 07: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.