cancel
Showing results for 
Search instead for 
Did you mean: 

USB middleware issue with CDC/VCP: only x packets receivable (HAL 1.1.0 and Host-Device_Lib 2.1.0)

schauer
Associate II
Posted on March 26, 2014 at 17:49

1) with STM32_USB-Host-Device_Lib_V2.1.0:

I implemented a CDC/VCP device just accepting data and throwing it away (no further handling of the received data, just receive). After the receival of several packets, no further packets are received and the Endpoint is set to NAK. But after receival of the packet before the last one DCD_EP_PrepareRx was called to allow more data to come in. The DataOut Handler of the device class was no more called.

2) with Cube and HAL FW 1.1.0:

The device is by default (as generated by Cube) just receiving data but not handling it. After receiving the first packet (CDC_Receive gets called) no further receival is possible and CDC_Receive is never called again.

Has anyone an idea how to create a reliably functioning CDC device? I'm going to develop a far more complex device not just handling a few bytes per second. Is that possible with an STM32F427 + ULPI Phy?
5 REPLIES 5
matteo
Associate II
Posted on March 26, 2014 at 19:58

Hello,

I am far from being an expert, so this might be wrong, but from playing around with a similar problem it seems that the first time you send data to the device USBD_CDC_DataOut gets called. This in turn calls CDC_Receive(), passing along the receive buffer.

Since by default the CDC_Receive does nothing with the data, it looks like something gets stuck. I'm still trying to figure this out, by my working guess right is that this has something to do with the TxState and/or RxState fields of pdev->pClassData.

From a first check on the code it seems that RxState is never set to 1.

Cheers,

Matteo

schauer
Associate II
Posted on March 27, 2014 at 15:52

for HAL FW 1.1.0:

I did some rework over the generated code and I'm now able to receive unlimited(?) data via VCP. I'm going to point the troublesome parts out in here after fixing the transmit side of the VCP.

Currently I'm only able to transmit exactly one packet via the library and a second does not make it on the wire, but transmit was called and in tokens were available.

gabrielharrison
Associate II
Posted on April 17, 2014 at 11:37

Hi,

I've just come across the same issue as you. It looks like the underlying USB_WritePacket is blocking and maybe hpcd->Lock should be used instead. What was your solution?

Gabriel
schauer
Associate II
Posted on April 17, 2014 at 13:49

Hello Gabriel,

I changed to use the ''new'' HAL and no longer the Host-Device Lib. That merely because the Host-Device Lib is no longer supported. The generated HAL CDC code has some ''issues'': 1) After CDC_Receive is called, USBD_LL_PrepareReceive is never called again. So, the USB NAK's data on that endpoint. So you need to add a possibility that USBD_LL_PrepareReceive is called, either directly or indirectly by your concrete CDC implementation. So, within USBD_CDC.c and/or the appropriate ''_if'' file. It could be handled in USBD_CDC.c, USBD_ACD_DataOut by adding

USBD_LL_PrepareReceive(pdev, epnum, hcdc->RxBuffer, hcdc->RxLength);

directly after

((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(pdev, hcdc->RxBuffer, hcdc->RxLength);

2) It might happen, on transmit, that the internal handling within USBD_CDC.c stucks, so that you could never again transmit data. I changed that, so, that I could recover from that situation. In my case it happened, that hcdc->TxState keeps at ''1'' at it is not reset to ''0'' by the interrupt. So before returning an error by TransmitPacket, I check if there is still data to be sent. In ''ll_usb'' I added:

uint32_t USB_EPTxCount(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) {
USB_OTG_INEndpointTypeDef *rep = USBx_INEP(ep->num);
uint32_t retVal;
retVal = ((rep->DIEPTSIZ & (USB_OTG_DIEPTSIZ_PKTCNT)) >> 19) * ep->maxpacket;
retVal += (rep->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ);
return retVal;
}

in ''hal_pcd'':

uint32_t HAL_PCD_EP_GetTxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) {
uint32_t retVal;
//TODO: Check if we need a lock here. Its just a register read anyway
retVal = USB_EPTxCount(hpcd->Instance, &hpcd->IN_ep[ep_addr & 0x7F]);
return retVal;
}

and in ''usbd_conf'' I added:

uint32_t USBD_LL_GetTxCount (USBD_HandleTypeDef *pdev, uint8_t ep_addr) {
return HAL_PCD_EP_GetTxCount(pdev->pData, ep_addr);
}

If USBD_LL_GetTxCount returns 0 I reset hcdc->TxState.
gabrielharrison
Associate II
Posted on April 28, 2014 at 14:47

Hi,

Thanks for the details. I've continued to have issues even when resetting the TxState and worked out that it is speed related and also found this old thread which suggests it may be a Windows driver issue. With HyperTerminal it crashes if I don't put a HAL_Delay in the send function.

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/problems%20with%20USB%20lib%20CDC%20example&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentview...

We tweaked our window app to simply read the COM port and throw away the data. The firmware is then happy running at full speed.

Gabriel