This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LM4F120 interrupt latency

Hello,

I have a design where I have an externally driven rising edge generate a GPIO interrupt on the LM4F120. In the ISR for this interrupt, the first (C) instruction is:

          HWREG(WTIMER3_BASE + TIMER_O_CTL) = usTimerCtl;

which starts either one or both of the WTIMER3 timers in PWM output mode. The rest of the configuration for the timers in this mode has been setup prior to the interrupt.

I'm running the LM4F120 at 80MHz off the PLL, and the clock generating the rising edge is running at a much faster frequency.

When scoping the time from the incoming edge that causes the GPIO interrupt to the output on the PWM, I'm seeing a range of 50ns. In other words it appears there is a variability of 5 cycles in the interrupt latency here. I would expect basically a variability of essentially 2 cycles, since the asynchronous edge coming in could arrive just before or just after the 80MHz clock edge of the LM4F120. There should be no other interrupts occurring at this time. I've prioritized the GPIO interrupt at the highest level just in case.

I thought that the interrupt latency was deterministic on the LM4F120? So there must be something else occurring here. Any ideas?

(An interesting (perhaps related) question is how many cycles it should take for a timer to start when its enable bit is written?)

Thank you for any assistance you may be able to provide!

  • Hi,

    The ARM Cortex-M4 standard manual states the followings about interrupt latency:

    • There is a maximum of a twelve cycle latency from asserting the interrupt to execution of the first instruction of the ISR when the memory being accessed has no wait states being applied. The first instruction to be executed is fetched in parallel to the stack push.

    • Returns from interrupts similarly take twelve cycles where the instruction being returned to is fetched in parallel to the stack pop.

    • Tail chaining requires six cycles when using zero wait state memory. No stack pushes or pops are performed and only the instruction for the next ISR is fetched. 

    If you need a faster GPIO, then try a AHB port instead the usual APB port. 
    If you wish to measure/check the execution time of various code then you can use the following code:
    Insert in your file (at right places):
    #include "inc/hw_nvic.h"
    #define DWT_O_CYCCNT 0x00000004
    static        uint32_t                  c_start, c_stop;
    void EnableTiming(void){
    static int enabled = 0;
    if (!enabled){
       HWREG(NVIC_DBG_INT) |= 0x01000000;            /*enable TRCENA bit in NVIC_DBG_INT*/
       HWREG(DWT_BASE + DWT_O_CYCCNT) = 0;  /* reset the counter */
       HWREG(DWT_BASE) |= 0x01;                                /* enable the counter */
       enabled = 1;
     }
    }
    and then, in the code to be examined write these, after a call of EnableTimig():
     c_start = HWREG(DWT_BASE + DWT_O_CYCCNT); // at the beginning of the code
     // your code follows here
     c_stop = HWREG(DWT_BASE + DWT_O_CYCCNT); // at the end of the code
    then c_stop - c_start is the execution number of cycles for the code; just multiply with clock period to find out the execution time of the code.
    Petrei
  • Petrei said:
    If you need a faster GPIO, then try a AHB port instead the usual APB port. 

     While this is usually well advised - poster is employing a Timer - configured as PWM output.  This may impact hoped for benefit.

     Beyond this - Sue Cozart has past advised here that AHB's "speed-up" is much confined to, "back to back" AHB accesses - which may not hold fully true - in this instance.
     
    Experimentation/"real-world" confirmation - this case - quick/easy.  (but this reporter would place large chip-stack upon failure of AHB use to speed this interrupt response...)
     
    Might another approach solve, "externally driven rising edge generate a GPIO interrupt" (and resultant output PWM - as quickly as possible)?"
     
    My suggestion - route that high speed rising edge to a very fast "OR" gate - thus that trigger pulse fulfills the need for, "instant output."  Upon the Timer's "awakening" its normal output drives the other "OR" gate input - while "blocking/disabling" any further impact of the high speed pulse. 
     
    In this manner - both your "instant response" and subsequent (tad delayed) PWM output combine to, "meet your expressed requirement."
     
    Green Verify Answer tick - gratefully accepted... 
  • Thanks for the replies.

    Yes, as cb1_mobile points out, the time I am measuring is from an incoming rising edge (which is configured to generate a GPIO interrupt) to the edge of a PWM timer output, which has been pre-configured to a particular width/period, and started on the first line of source within the GPIO interrupt ISR. So there are no GPIO register accesses here, regardless of whether APB or AHB is used.

    I have read the 12-cycle/6-cycle interrupt latency descriptions as well, and seen this in the Stellaris example videos also.

    I am seeing in practice right now about a 34 cycle offset between what I need to program into the timer and what I would have to if the PWM could somehow start automatically on the incoming GPIO edge. I had expected to have to offset by 12 (since no other interrupts will be active at this time, it would never be chained, so always require the full 12 cycles for the push, etc.) plus however many instructions the line of C code compiled to before actually writing to the timer control register to enable the timer (5 instructions, including the PUSH). This means I would expect to have to program for 17 cycles less than desired, but am needing to offset by about 34. On top of this, it is actually not deterministic - with constant timer values programmed, the first PWM edge transitions over a range over FIVE 80MHz cycles it looks like.

  • Perhaps the more advanced ARM devices - also available this vendor - bear your investigation.

    Appears that our posts may have crossed - kindly check the tail of my previous post - in which simple HW addition appears to "meet" your requirement...

  • Ah, yes cb1_mobile, I hadn't seen the end of your last post when I wrote my last reply.

    Yes, you're right, there would be other better solutions, including using a PLD/FPGA that could start counting down the timer as the incoming edge is latched.

    The Stellaris Launchpad LM4F120XL is what I had here, and by reading the "fixed interrupt latency" text I thought I could offset by this amount and be close to what I want.

    I'm still puzzled about why I'm not seeing the published interrupt latency on the scope...this is what I'd like to understand.

    For one, does anyone know after writing to a (wide) timer control register to enable one (or both) timer(s), how long does it take for the timer to start counting? If it is not on the next cycle, is the delay deterministic, or have other dependencies?

  • Variation in response time you report seems outside our measured, "norm."  Thus - you may consider:

    Might this be a Timer specific issue?  (i.e. config and try an alternate...)

    Might this be a Wide-Timer issue?  (try a "normal timer")

    Might some unwanted "pre-scale" operation be impacting?

    Further - we often resolve such issues by greatly reducing (i.e. eliminating) all other running code blocks - even when clients (or we) "know" they are not impactful!  (i.e. Jon: "There should be no other interrupts occurring at this time...")