cancel
Showing results for 
Search instead for 
Did you mean: 

Bug in Stm32F4 Cube v 1.13 with USB Controller

johannes2399
Associate II
Posted on September 14, 2016 at 09:47

Hello,

I think I found a bug in the STM32F4 USB controller which is not addressed correctly by the cube library v1.13 and which is not documentend as well. I'm developing on the STM32F437IIH and I use the USB OTG_FS. The problem occurrs only with at least 2 USB endpoints. Endpoint 1 (IN and OUT used) and endpoint 2 (only IN used) are used in bulk mode. The problem occurrs if I'm writing on Endpoint 2 in the funtion HAL_PCD_IRQHandler ->PCD_WriteEmptyTxFifo ->USB_WritePacket from a low priority interrupt. The important routine here is:

for
(i = 0U; i < count32b; i++, src += 4U)
{
USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src);
}

If during writing to this data fifo a second higher priority interrupt is interrupting this routine and a register access is happening in the higher priority interrupt (i.e. inUSB_EPStartXfer to start writing on USB EP 1) then the state machine for the EP2 gets confused and this leads to the transmission of the so far written USB data in the fifo and a CRC error. After 3 erroneous transmissions the controller stops transmitting data on the USB for this endpoint. Because there is an array to distinguish between different endoints I would expect that I can access the data fifo for different endpoints independently. But this doesn't seem to work. This routine would cause such a behaviour during an interrupt.

USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);

My solution to this problem would be to implement a lock bit or function before and after the data FIFO write routine which must be read before an access to a USB register. I tested my solution and it worked for me as long as I avoided to access a register of the USB controller during writing to the EP2. Is there anybody who had similiar problems? How can I get in contact with the cube developers to discuss and report this bug?
10 REPLIES 10
Walid FTITI_O
Senior II
Posted on September 16, 2016 at 20:57

Hi ge.johannes,

Thanks for your feedbacks. I report int internally for check.

-Hannibal-

johannes2399
Associate II
Posted on September 26, 2016 at 16:40

Thanks Hannibal,

We are a company working in the medical domain and would like to use the cube library as the basis for our development.

Could you reproduce the bug internally? If yes do you know when a fix will be implemented in a new version of the cube library?

Because we don't want to change the cube libary to fix this bug it would be crucial to us for having a bug fix in the upcoming version of the cube library.

Thanks,

 Johannes

Marco1
Associate II
Posted on October 04, 2016 at 11:52

Check my new post, can be the same problem ?

johannes2399
Associate II
Posted on October 14, 2016 at 10:40

Hi Marco,

I just checked your solution by moving the line

USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);

before if (dma == 1). I did this for both functions USB_EP0StartXfer and USB_EPStartXfer. The code looks like this:

USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
if (dma == 1)
{
USBx_INEP(ep->num)->DIEPDMA = (uint32_t)(ep->dma_addr);
}
else
{
/* Enable the Tx FIFO Empty Interrupt for this EP */
if (ep->xfer_len > 0U)
{
USBx_DEVICE->DIEPEMPMSK |= 1U << (ep->num);
}
}

But unfortunatelyit didn't solve my problem with the wrong CRC in the USB packet. Thanks for your help anyway.
Chris H
Associate II
Posted on January 05, 2017 at 01:58

I have the same issue it seems, It is very serious. Debugged this for quite a while until i found this post here.

I amalso getting bad transfers on EP2 (and possibly any of the higher EP1 above 1) and have it traced down to exactly this function to be called with the correct data being supplied. 16 Byte Buffer is defined but only 2 reach the PC and it is totally wrong data. Sometimes the Beagle 5000 reports bad CRC as well. EP1 is all ok.

Here is what I see in the USB Analyzer:

0690X00000605z8QAA.png

This is what is called:

USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src);�?

And here is the Route Call Stack just before the sent:

0690X00000605zIQAQ.png

And Finally here is the Buffer to Send:

0690X00000605pEQAQ.png

For the Report descriptor it is fine, it works on many commercial products we did.

So based on the above suspicion in the original post i changed to this :

__disable_irq(); USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src); __enable_irq();�?�?�?�?

But it does not help, still the same:

0690X00000605zcQAA.png

If I try the same thing via EP3 it also fails:

0690X000006059EQAQ.png

But if I specify EP1 in my send routine (illegally, of course just for test) :

0690X00000605zXQAQ.png

At this point I have serious doubts, it is not the user code, but either it is something not setup correctly in the LIB when opening the higher EP (I did have to set the TxFifo Manually) or it is something in the USB Engine itself that goes wrong.

This is what i use to setup the EPs:

static uint8_t USBD_CUSTOM_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
 uint8_t ret = 0;
 USBD_CUSTOM_HID_HandleTypeDef *hhid;
 /* Open EP IN */
 USBD_LL_OpenEP(pdev,
 CUSTOM_HID_EPIN_ADDR,
 USBD_EP_TYPE_INTR,
 0x40); 
 USBD_LL_OpenEP(pdev,
 0x82,
 USBD_EP_TYPE_INTR,
 0x10); 
 USBD_LL_OpenEP(pdev,
 0x83,
 USBD_EP_TYPE_INTR,
 0x40); 
 
 /* Open EP OUT */
 USBD_LL_OpenEP(pdev,
 0x03,
 USBD_EP_TYPE_INTR,
 0x40);
 
 pdev->pClassData = USBD_malloc(sizeof (USBD_CUSTOM_HID_HandleTypeDef));
 
 if(pdev->pClassData == NULL)
 {
 ret = 1; 
 }
 else
 {
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
 
 hhid = (USBD_CUSTOM_HID_HandleTypeDef*) pdev->pClassData;
 
 
 ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->Init();
 
 // Prepare Out endpoint to receive 1st packet
 USBD_LL_PrepareReceive(pdev, 0x03, hhid->Report_buf, 
 EP3_PKT_SIZE);
 HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10);
 HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x40);
 }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on January 05, 2017 at 17:19

I have now found a workaround to this issue:

0690X00000605sXQAQ.png

I am pretty sure it is an issue with the IC and the Library. If anybody else is facing this problem, I have already used my customer channel to report and there is a workaround document from ST which I don't have as of now, but basically they said it will be worked around in the next Update of the Cube. 

If anybody else needs a quick fix the problem is the allocation of the FiFoTxBuffer. The library allocates to much buffer (2x) and interferes with the next EP due to this somehow. I do not know if this is a design issue (as ST claims) or just a bug that there isn't that much Fifo and corrupts other EP registers in the chip. In my case in order not to edit the library I have reduced the TxBuffer accordingly. 

Posted on January 05, 2017 at 17:27

Update: I have now gotten the Document from ST but this is unrelated, it does not solve this issue. The document is per the original suspicion in this thread by Johannes Lange, but this is not the actual root cause of the corruption as disabled Interrupts or flags do not help. First of all this function is only called from an interrupt in the Library and blocking other interrupts does not change the problem at all. hanging the FiFo Size itself however does solve this issue. 

Posted on March 15, 2017 at 01:11

Hi all,

I am facing analogous issues with USB HS and DMA on STM32F723 DISCO.

As soon as I enable DMA, the board is no more enumerated.

I have found this comment in the HAL_PCDEx_SetTxFiFo function code (Cube lib 1.6.0):

'When DMA is used 3n * FIFO locations should be reserved for internal DMA registers'

How should I take this into account? In fact I don't understand exactly the need.

Any help would be appreciated!

-- 

Jean-Pierre Fortune

Posted on March 17, 2017 at 16:52

Finally I achieved to make the USB HS work with DMA by reducing the Tx Fifo size :

in usbd_conf.c

HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_HS, 0, 0x80);

becomes

HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_HS, 0, 0x40);

I am now trying to increase the bandwith by sending more than one transaction per microframe but I can't find any example showing this with a STM32 chip.

-- 

Jean-Pierre Fortune