cancel
Showing results for 
Search instead for 
Did you mean: 

Yet another STM32F105/7 USB OTG driver issue (VCP device)

sanderson
Associate
Posted on November 07, 2011 at 22:32

Hello all,

I've taken the VCP example from the USB OTG Driver/Library v3.3.0 and incorporated it with my embedded application.  I've seen some strange latencies introduced in the app due to the USB interrupt, so I started instrumenting/timing the USB IRQ handler.  I see that most of the time the IRQ handler takes about 4.5uS to execute, with a maximum time of 24uS or so.  Not too shabby, but that didn't explain my weird latencies.  Then I looked at how many IRQs happen per second:

When idle I get 1000 IRQs per second, as expected (the SOF IRQ).

When transmitting about 200Kbytes/second I get about 32,000 IRQs per second!   This is where it gets odd.  I have a 64 byte EP packet size so I figure I should get about 4 IN EP IRQs per mS, which it turns out is basically correct.  This accounts for about 4K of those 32K interrupts.  The other 27-28K of interrupts are the transmit fifo empty interrupt, which based on the IRQ handler in usb_dcd_int.c should be cleared by the macro call: CLEAR_IN_EP_INTR(epnum, emptyintr).   Is this normal?  I guess I don't have a complete understanding of when these IRQs are supposed to happen in relation to each other.

One other note: I've seen the VCP driver not function through a USB hub, but work fine directly attached to a PC--is this a known bug/limitiation?

Thanks for any advice/assistance!

-sa

#connectivity-usb-otg-fs-vcp #usb-vcp-stm32_usb-s-device_lib
9 REPLIES 9
gareth2
Associate II
Posted on November 08, 2011 at 11:15

Hi Anderson,

I have been experiencing the same issues, with a slighlty different approach I was trying to test how fast i could transfer data across the usb using this class. The result was extremely low and linked direclty to the APP_RX_Data buffer size. It seems that once data is in this buffer the USB would start transmission and then take over the rest of it in the ISR routines. This would then continue (without returning to run any of main!!) until the buffer was empty. I too deduced that it was spending far too long in the an ISR routine, but as yet have not come up with a solution.

flyer31
Senior
Posted on March 29, 2012 at 11:41

This is definitely due to an error in the STM32 USB lib in device mode:

As soon as you load the first time an IN endpoint (non-zero - done in the function DCD_EP_Tx), then the function USB_OTG_EPStartXfer will set the corresponding bit for this endpoint number in the register DREGS->DIEPEMPMSK to 1.

After this, every time, when the transmit FIFO is empty for this endpoint, there will come an interrupt.

The error in STM32 USB lib is, that this interrupt mask bit is never reset again (if you look for DIEPEMPMSK in the project files, you will see that it comes only once, at this ''set'' point - it is never cleared).

After this time, you are therefore ''flooded'' with such ''empty FIFO'' interrupts - even after the transfer is completed (flag TXFE in DIEPINTx register - this flag can neither be reset or masked out directly - only possibility to get rid of this interrupt, is to kill the corresponding bit in the DIEPEMPMSK register, as I see it).

To avoid this, please add the following code in the function DCD_WriteEmptyTxFifo (this function handles the ''Empty TX FIFO'' interrupt):

In the while loop, at the end of this function, you find the 2 lines:

    ep->xfer_buff  += len;

    ep->xfer_count += len;

After this, please insert the following code (to reset the DIEPEMPMSK-Bit, if all bytes have been transferred to the TX FIFO):

    if( ep->xfer_count >= ep->xfer_len){

      uint32_t fifoemptymsk = 1 << ep->num;

      USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);

      break;

    }

(the ''break;'' is not important - the while loop anyway will quit on next while condition - it just saves you checking this next while condition).

root
Associate II
Posted on April 04, 2012 at 21:32

Hello,

Where to I send the bottle of Champagne ? 🙂

These 4 lines of code decrease my whole board consumption from 80/90mA down to 40/50mA !!!!!!! That's a 50% reduction (and the MCU is not alone on the board ... one flashing LED, etc)

And it also removed some unexpected freezes in my application.

Thank you so much for this hint !!!

The original ST USB stack is really far from perfect :(

Thomas.
root
Associate II
Posted on April 04, 2012 at 21:33

Hello,

Where to I send the bottle of Champagne ? 🙂

These 4 lines of code decrease my whole board consumption from 80/90mA down to 40/50mA !!!!!!! That's a 50% reduction (and the MCU is not alone on the board ... one flashing LED, etc)

And it also removed some unexpected freezes in my application.

Thank you so much for this hint !!!

The original ST USB stack is really far from perfect :(

Thomas.
flyer31
Senior
Posted on April 10, 2012 at 16:37

Sorry that I need to keep incognito ... . A bottle of Champagner, and you seem to be from France, that really sounds like a nearly divine offer.

But your virtual bottle also is nice already (at first I was quite a bit disappointed that no reactions came to my post ... should be a relieve for quite many poeple ...).

gregg
Associate II
Posted on July 23, 2012 at 21:59

Just wanted to say, a HUGE thanks for helping me on this one!!  I was sure that flag wasn't being cleared, but this post nailed it down neatly for me. 

Thanks again!

Ixox
Associate II
Posted on August 11, 2013 at 13:57

Beautifull... thanks a lot.

An other virtual Champagne bottle from Paris 🙂

Xavier

arunaupul
Associate
Posted on March 26, 2014 at 06:15

Hii bil til, This post was really really helpful. I was implementing MSC+CDC composite device and after change endpoint numbers it gave me the same error. Thank you very much. Now I have successfully implemented my project.  

-Aruna

DiBosco
Senior
Posted on September 15, 2016 at 16:06

Hi,

I realise this is a super-old post, but I'm hoping someone on it gets notifications of replies and can help.

I've been trying for weeks to get USB going on an F107. It works on an F103 with the device interface, but I just cannot get it working on the F107 with the OTG interface properly.

I can get it so that it does a loopback test, but it just constantly goes into the OTG_FS_IRQHandler. Looks like it's getting a start of frame interrupt that just starves all other tasks. If I disable the start of frame interrupt, I get nothing in.

I have searched high and low, tried many, many different downloads, libraries, ST example projects and simply cannot this to work.

Does anyone have some code I could have that uses the v3.3 or (maybe 3.4) libraries that I can integrate with my old version of FreeRTOS.

Please, please don't suggest I use the cube or newer libraries as we have so much invested in this version of FreeRTOs with these old libraries and we just can't go changing all that.

Many thanks for any help!