Skip to main content
Visitor II
January 18, 2019
Question

USB OTG_FS (device mode) CDC-ACM: IN endpoint transfer complete interrupt never fires after sometime with STM32F411/STM32F413

  • January 18, 2019
  • 10 replies
  • 3850 views

I am working on testing libopencm3 based USB OTG FS stack for STM32F411/STM32F413. And OTG FS stack works fine to begin with without any issues. But, after a while it seems to lock-up waiting for transfer complete interrupt to fire on one of the IN endpoints.

The test script running on the PC repeatedly sends messages to the OTG device and device also sends data back. This seems to run fine for a while but eventually gets locked-up.

I have a debugger hooked and on lock-up i observe that the transfer complete interrupt on an IN endpoint never fired, causing to device to hang.

Browsing for similar issue i have come across multiple posts where people have reported similar problems and it looks like TX FIFO access has some limitations.

Can someone please shed more light on how to fix this bug. We have been debugging this for a while and haven't been successful in fixing this. Any inputs would be highly appreciated.

    This topic has been closed for replies.

    10 replies

    Super User
    January 18, 2019

    > I have a debugger hooked

    Are you sure it does not access the OTG registers *before* the lockup occurs? Debugger reads are intrusive with registers which change content or hardware state upon read (e.g. OTG_GRXSTSP).

    Make sure the FIFO write is not interrupted with any code which would access any other OTG resource, including other FIFOs (OS sounds much like an opportunity to such problem). Make sure the number of FIFO writes is correctly rounded up to whole words, and that all writes are in words and to address properly aligned to word. Observe OTG_DTXFSTSx, make sure there's always enough space available in the given FIFO before start writing, observe its value (as well as DIEPTSIZx, DIEPCTLx, DIEPINTx value) when lockup.

    JW

    MSuheAuthor
    Visitor II
    January 18, 2019

    Thanks for your response, much appreciated. I have couple of queries as below:

    1. Are you suggesting not to use debugger in this case? due to the intrusive nature of reads?

    BTW,

    1. I am always writing a single packet (of size <=64 bytes) to the FIFO and MAX packet size is 64 bytes. And TX FIFO size is also 64 bytes (or 16 words).
    2. Packet size can be odd number of bytes too.
    3. And when the lockup occurs, i notice that DIEPTSIZx is set to 0x80000 (which is packet count of 1 & transfer size of 0). So, packet is still not sent out?
    4. OTG_DTXFSTSx is 0, which indicates FIFO is full.
    5. DIEPCTLx is set to 0x80888040/0x80898040 which indicates endpoint is still enabled.
    6. DIEPINTx is consistently 0x2010 i.e, NAK input bit is 1 & ITTXFE is also 1.

    Please do share your inputs. 

    MSuheAuthor
    Visitor II
    January 18, 2019

    .

    Super User
    January 18, 2019

    Let's not accuse the debugger right now, leave it for later, but make sure all "view" windows (register view, memory view) are closed while running, "live view" features are switched off, and that there are no data breakpoints or any other feature which might be suspicious of potentially involve autonomous unprovoked reads.

    I'm not absolutely sure how to interpret the readout values you presented, but at the first sight they appear to be OK.

    Increase the TX FIFO size so that you'll always see some "residuum". How exactly do you write to the FIFO area? Do you write to a single address in the FIFO area, or are you incrementing the address? Store the intended number of writes before starting writing to FIFO to a static/global variable, so that it could be checked when the problem occurs. Similarly store the value you are writing to DIEPTSIZ for later checking (any other interesting register writes too perhaps).

    JW

    MSuheAuthor
    Visitor II
    January 18, 2019

    Thanks again. To answer your question yes I am incrementing the FIFO address as I write to it.

    will try to save the buffer contents and the register values before initiating the transfer and come back with more data.

    Regards,

    md.suhel7​

    Super User
    January 18, 2019

    And increase the FIFO size so that the remainder when writing maxpacket is not 0.

    And try to not increment the FIFO address when writing.

    JW

    MSuheAuthor
    Visitor II
    January 21, 2019

    I tried to increment the FIFO size to more than the maxpacket and did not increment the FIFO address when writing.

    But, i still notice the USB getting locked up. Any other suggestions?

    MSuheAuthor
    Visitor II
    January 21, 2019

    Also i tried testing without debugger as well and i still notice the lock-up.

    MSuheAuthor
    Visitor II
    January 21, 2019

    Guys, any inputs?

    Super User
    January 21, 2019

    I didn't meant increasing FIFO as a solution. I don't know what's the solution.

    I meant to increase FIFO only to see what's the remainder of space in FIFO (OTG_DTXFSTSx ) when the problem occurs, Also, any change in other registers when the problem occurs?

    Also,

    Store the intended number of writes before starting writing to FIFO to a static/global variable, so that it could be checked when the problem occurs. Similarly store the value you are writing to DIEPTSIZ for later checking (any other interesting register writes too perhaps).

    JW

    MSuheAuthor
    Visitor II
    January 24, 2019

    I did try to repeat my tests and register state is similar to what i reported previously:

    1. When the lockup occurs, i notice that DIEPTSIZx is set to 0x80000 (which is packet count of 1 & transfer size of 0). So, packet is still not sent out?
    2. OTG_DTXFSTSx is 0, which indicates FIFO is full. Sometimes non-zero, based on the length of frame queued to FIFO.
    3. DIEPCTLx is set to 0x80888040/0x80898040 which indicates endpoint is still enabled.
    4. DIEPINTx is consistently 0x2010 i.e, NAK input bit is 1 & ITTXFE is also 1.

    However, this time around i added a software workaround. Wherein, if the IN endpoint stays enabled for one full second and transfer complete interrupt does not fire. I treat it as a lock-up scenario and executed below sequence:

    1. set NAK on the end point.
    2. Disabled the endpoint.
    3. Flushed the TX FIFO's.
    4. And enabled the endpoint again, and initiated a new transfer.

    But the new transfer never finishes. As endpoint again goes to lock-down state where i don't see the XFRC interrupt firing.

    Any inputs?? 

    Super User
    January 24, 2019

    At this point, I'd perhaps use a hardware bus analyzer, and/or investigate at the host side...?

    JW

    MSuheAuthor
    Visitor II
    January 24, 2019

    I do not have a hardware bus analyzer with me, until i get one. Anything else that i can try may be?

    MSuheAuthor
    Visitor II
    January 24, 2019

    I do not have a hardware bus analyzer with me, until i get one. Anything else that i can try may be?

    Super User
    January 24, 2019

    I'm out of ideas by now... Sorry.

    JW

    MSuheAuthor
    Visitor II
    January 24, 2019

    np, thanks for your inputs.

    Visitor II
    January 30, 2021

    I know this is an old thread, but could you solve the lockup issue and determine the root cause?

    I'm working with the same OTG FS peripheral and experience lockup issues ​the seem the same. If you where able to find a solution I would be very interested to know.

    Thank you​