2013-05-02 12:47 PM
ST libraries in problem: STM32_USB-Host-Device_Lib_V2.1.0
Fixed usb_dcd_int.c is attached to this post. On this post, bil.til had pointed out on the problem of flooded ''empty FIFO'' interrupts on STM32_USB-FS-Device_Lib_V3.3.0 https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex%5fmx%5fstm32%2fYet%20another%20STM32F1057%20USB%20OTG%20driver%20issue%20%28VCP%20device%29 This problem was carried over to the USB device implementation of STM32_USB-Host-Device_Lib. On recent libraries, ST have tried to fix this problem, but they didn't follow bil.til's solution. bil.til suggests that the ''empty FIFO'' interrupt should be masked in DCD_WriteEmptyTxFifo(), which is called by ''empty FIFO'' interrupt. But ST masks ''empty FIFO'' interrupt at the transfer completion interrupt, as follows.STM32_USB-Host-Device_Lib_V2.1.0\Libraries\STM32_USB_OTG_Driver\src\usb_dcd_int.c
static uint32_t DCD_HandleInEP_ISR(USB_OTG_CORE_HANDLE *pdev)
{
...
while ( ep_intr )
{
if (ep_intr&0x1) /* In ITR */
{
diepint.d32 = DCD_ReadDevInEP(pdev , epnum); /* Get In ITR status */
if ( diepint.b.xfercompl ) // <--- transfer completion interrupt
{
fifoemptymsk = 0x1 <<
epnum
; // <--- ST's bad solution
USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0); // <---
As the result, flooded ''empty FIFO'' interrupts still make the firmware crawl until host would initiate IN transactions. As you know, host doesn't always put IN transactions immediately after the firmware calls DCD_EP_Tx().
Here is the
REAL fix, followed to bil.til solution.
STM32_USB-Host-Device_Lib_V2.1.0\Libraries\STM32_USB_OTG_Driver\src\usb_dcd_int.c
static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum)
{
...
while (txstatus.b.txfspcavail > len32b &&
ep->xfer_count <
ep-
>xfer_len &&
ep->xfer_len != 0)
{
/* Write the FIFO */
len = ep->xfer_len - ep->xfer_count;
if (len > ep->maxpacket)
{
len = ep->maxpacket;
}
len32b = (len + 3) / 4;
USB_OTG_WritePacket (pdev , ep->xfer_buff, epnum, len);
ep->xfer_buff += len;
ep->xfer_count += len;
// <--------- fix: from here
if( ep->xfer_count >= ep->xfer_len){
uint32_t fifoemptymsk = 1 <<
epnum
;
USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
break;
}
// <--------- fix: to here
txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS);
}
return 1;
}
Tsuneo
2014-01-21 04:29 AM
Hello Tsuneo,
Thanks for reporting this problem. Your solution is not complete. There is one more occurrence ofCLEAR_IN_EP_INTR(1, emptyintr);
It is in the same file and you have to replace this macro with :
fifoemptymsk = 0x1 << 1;
USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0)Regards,Ivo2014-06-24 06:49 PM
Hello,
Lvo
Thanks for your great sharing which helped me solve the most problems. Unfortunately, I encounted one more problem with the function DCD_WriteEmptyTxFifo(), specifically with the code line txstatus.d32 = USB_OTG_READ_REG32( &pdev->regs.INEP_REGS[epnum]->DTXFSTS); the problem is the value of txstatus.d32 is never updated with DTXFSTS. therefore the while condition txstatus.b.txfspcavail > len32b can not be satisfied. I want to ask you guys whether or not you met the same problem with EP2 other than EP0? how did you fix this problem? Really appreciated your great help! Best regards! --Ying