cancel
Showing results for 
Search instead for 
Did you mean: 

Cube USBD USBD_LL_PrepareReceive CDC Example

Daniel Squires
Associate II
Posted on August 11, 2015 at 18:21

Hi,

I'm using the Cube F1 1.2.0 libraries with an STM32F105R8T6 device.

I have adapted the CDC example for the device but am having a problem with the the USB out bulk transfers. They work for some time until a point where no more out transfers succeed.

Having investigated and experimented with toggling LED's at various points In the code I have come to the conclusion that something within USBD_LL_PrepareReceive sometimes fails.

The code normally runs in a loop where having made an initial call to USBD_LL_PrepareReceive the PC is able to send data, this triggers USBD_CDC_DataOut which calls CDC_Itf_Receive which initiate a DMA transfer to the UART. When this transfer completes

HAL_UART_TxCpltCallback is called which calls 

USBD_CDC_ReceivePacket  which in turn calls USBD USBD_LL_PrepareReceive. The PC can then send another packet.

This all works for some time until at some point (apparently randomly) USBD_LL_PrepareReceive has been called but the PC is unable to transfer any more data. I can see in wireshark an URB status of -2 5 seconds after initially attempting the failed send.

I have noticed that if I schedule the writes regularly at say 2mS intervals it seems to work indefinitely, but if I emulate my real world scenario using a random time delay (i.e. 0 to 0.2 seconds) between writes it seems to fail after not very long.

Elsewhere in the forums I have seen comment about the loop being fragile in that if the UART TX callback doesn't fire for some reason the PC can no longer send, but in my case I have verified that the UART transaction completes and that USBD_LL_PrepareReceive is being called - I set an LED on immediately before calling it and off again in USBD_CDC_DataOut.

Any ideas?

4 REPLIES 4
Daniel Squires
Associate II
Posted on August 12, 2015 at 13:15

For now  I am living with a workaround. I am using the Timer callback in the cdc_if to incremrent a value which is reset when data is received from the PC. If this exceeds a short time then i call the USBD_CDC_ReceivePacket function again.

This seems to work even for data the PC has already started trying to send, presumably it sits being NAK'd until this point. The side effect is some packets will arrive and be processed a bit late, but this is better than not working at all.

So far this seems to work ok.

Any suggestions of a proper solution much appreciated.

Daniel Squires
Associate II
Posted on August 12, 2015 at 17:51

The Device  sends to the host (IN pkt),  at specific Intervals determined by timer callback. It seems that if the PC always sends an OUT pkt value within this time that communications works indefinitely.

However, if an IN pkt is sent between the call to USBD_CDC_ReceivePacket(&USBD_Device) and the PC doing an OUT write, the OUT write occasionally fails. Possibly the IN transaction is messing up the state of the OUT endpoint in some way.

drojfjord
Associate II
Posted on November 06, 2015 at 05:31

I have the same problem, I'm using a NUCLEO-F072RB board and the STM32Cube FW_F0 V1.3.0 library. 

I'm using the Custom HID class to send/recv data. I was going to constantly send reports using the systick interrupt every 1 ms, and receive data in the interrupt but that doesn't seem to work  (I'm probably not properly using the library when I do this though, I didn't see any functions to receive reports so I just pull the data from ''Report_buf'' when ''CUSTOM_HID_OutEvent_FS()'' is called), and it stops working the same way you describe. My workaround is to only call ''USBD_CUSTOM_HID_SendReport'' after some data has been received in the host (inside the interrupt).

I think you're right in that it's when read/write happens simultaneously - are we meant to use the HAL_lock() function for this?

Daniel Squires
Associate II
Posted on November 13, 2015 at 11:00

Hi Daniel,

Have you seen this post? It may be related. I never did get to the bottom of this.

[DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Java/STM32Cube%20USB%20CDC%20%28possible%29%20Bug%20Found%20-%20Rx%20Tx%20Race%20condition&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000F9A0E3A95BA69146A17C2E80209ADC21&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/AllItems.aspx?Paged%3DTRUE%26p_StickyPost%3D%26p_DiscussionLastUpdated%3D20150921%252006%253a27%253a45%26p_ID%3D5064%26View%3D%257bA4EEE515%252d04F0%252d42D9%252dAC32%252dA6D8340F101B%257d%26FolderCTID%3D0x012001%26PageFirstRow%3D241&currentviews=189]link

From: wong.daniel

Posted: Friday, November 06, 2015 5:34 AM

Subject: Cube USBD USBD_LL_PrepareReceive CDC Example

I have the same problem, I'm using a NUCLEO-F072RB board and the STM32Cube FW_F0 V1.3.0 library. 

I'm using the Custom HID class to send/recv data. I was going to constantly send reports using the systick interrupt every 1 ms, and receive data in the interrupt but that doesn't seem to work  (I'm probably not properly using the library when I do this though, I didn't see any functions to receive reports so I just pull the data from ''Report_buf'' when ''CUSTOM_HID_OutEvent_FS()'' is called), and it stops working the same way you describe. My workaround is to only call ''USBD_CUSTOM_HID_SendReport'' after some data has been received in the host (inside the interrupt).

I think you're right in that it's when read/write happens simultaneously - are we meant to use the HAL_lock() function for this?