This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Pipeline issue on return from FIQ

Note: This was originally posted on 17th August 2009 at http://forums.arm.com

I'm using an ARM9 (Cirrus EP9302). My FIQ interrupt handler returns using "subs pc, lr, #4" instruction. The way the handler was originally written, the previous instruction was an "str r9,[r8]" with r8 pointing to some I/O. This version crashes in all kinds of ways. Inserting one "nop" instruction, before the "subs" solves the problem.

This looks to me (but I'm not sure) as if the switching of the FIQ registers happens while the "str" instruction is still in progress, and it stores to whatever address the normal (supervisor) mode r8 points to. I could not find any documentation of the pipeline behavior during return from FIQ interrupt.

I have a working solution, but I don't like when I don't understand how it works. It may rise again behind me and bite...

Any help?
  • Note: This was originally posted on 18th August 2009 at http://forums.arm.com

    Thanks ttfn, this was the answer. I moved the interrupt clear instruction earlier in the handler and the problem disappeared.
  • Note: This was originally posted on 20th August 2009 at http://forums.arm.com

    Thanks Marcus, but my I/O range is neither buffered nor cached. The problem is  (as ttfn wrote) that the execution pipeline does not finish the write operation for couple of cycles, leaving the interrupt enabled passed the return from interrupt instruction.

    Eliminating the "nop" saved one cycle, which is significant for a handler executing as often as mine.
  • Note: This was originally posted on 21st August 2009 at http://forums.arm.com

    Thanks Marcus, the link you've provided is exactly the information that would have saved me this this trouble - they recomend acknowledging the interrupt as soon as possible.
  • Note: This was originally posted on 19th August 2009 at http://forums.arm.com

    Thanks ttfn, this was the answer. I moved the interrupt clear instruction earlier in the handler and the problem disappeared.


    Sure, but this is in no way better than adding a NOP instruction as you did earlier. If you want to be absolutely sure you'd have to declare that peripheral region as non-bufferable or use a "drain write buffer" barrier before returning from the ISR.

    [url="http://infocenter.arm.com/help/topic/com.arm.doc.ddi0151c/Chebfdhc.html"]http://infocenter.arm.com/help/topic/com.a...c/Chebfdhc.html[/url]

    Best regards
    Marcus
  • Note: This was originally posted on 21st August 2009 at http://forums.arm.com

    Eliminating the "nop" saved one cycle, which is significant for a handler executing as often as mine.

    Sure, what I meant with "no better than" was that placing the write at an arbitrary distance from the return until it happens to work in a given situation still lacks formal proof that this won't bite you later. Don't get me wrong, I am sure what you are doing is perfectly fine for all practical purposes. But the issue involves more than just the pipeline hazard described here: [url="http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ka3788.html"]http://infocenter.arm.com/help/topic/com.a...aqs/ka3788.html[/url]

    In general, we cannot tell how long the (maximum) latency is, between writing to the interrupt-clear register in a device, and the interrupt controller registering this fact, unless the device vendor tells us (which they rarely do).

    The only generic (and completely inappropriate in real applications) way to tell, is to poll the interrupt status in the interrupt controller itself until the corresponding bit indicates the signal has been deasserted, before returning from the ISR.

    Best regards
    Marcus
  • Note: This was originally posted on 18th August 2009 at http://forums.arm.com

    I think that unlikely, as on the ARM9 all instructions are issued and executed in order.  So the STR instruction will be being executed while the SUBS is still decoding.

    My guess would be timing.  What does the STR do?  Clear the source of the interrupt?  If so, its possible that the write is not completing on the bus before the exception return.  Potentially meaning that you re-take the exception.
  • Note: This was originally posted on 21st August 2009 at http://forums.arm.com

    The only generic (and completely inappropriate in real applications) way to tell, is to poll the interrupt status in the interrupt controller itself until the corresponding bit indicates the signal has been deasserted, before returning from the ISR.


    Even this is flawed in multiple ways; for a random interrupt source this scheme will likely result in deadlock as it is not possible to tell the difference between the interrupt not having yet been cleared vs it having become near instantaneously repended via a new event; secondly there is no guaranteed delay between the interrupt controller and the actual processor interrupt pin, thus reading the bit being clear and the same information arriving at the processor's interrupt decision logic may still be decoupled by a few cycles.

    The only generic scheme is to clear the source as early as possible, and for software to support spurious interrupts.

    hth
    s.