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.

AM6422: R5F Interrupt delay

Part Number: AM6422

Hello,

We are observing unexpected interrupt response latency on our system and would like to seek advice.

Setup:

  • A GPS PPS (pulse per second) signal is connected to the capture input pin of Timer 3.

  • Upon entering the capture interrupt, we toggle a GPIO pin and measure the time difference between the GPS pulse edge and the GPIO toggle using a logic analyzer. This difference is taken as the interrupt response latency.

  • We also read the Timer 3 counter value inside the ISR and compare it with the hardware‑captured count value. The maximum difference we observed is over 2000 counts, which translates to about 10 µs (depending on timer clock). We believe the hardware capture itself is accurate, so the delay is caused by interrupt response.

Additional test:

  • We configured a 500 µs periodic timer (Timer 7). In its ISR, we record the current timer count.

  • Theoretically, the count difference between consecutive interrupts should be in the order of nanoseconds. However, in practice, we see a difference of about 2 µs, which indirectly confirms that the timer interrupt response also suffers from latency.

Environment:

  • FreeRTOS is used as the RTOS.

  • The timer interrupt priority is set to 1 (highest, except for critical system interrupts).

  • No other user‑defined interrupts are present in the system besides these timers and tasks.

    void AD5711(void)
    {
        inter500us[inter500uscnt] = TimerP_getCount(gTimerBaseAddr[CONFIG_TIMER0]);
        inter500uscnt++;
        if (inter500uscnt >= 1000)
            inter500uscnt = 0;
    }
    
    void Timer3_isr0(void *args)
    {
        uint32_t value = 0x00;
        uint32_t timercnt = 0;
    
        /* Clear status for overflow interrupt */
        value = CSL_REG32_RD(gTimer3BaseAddr + 0x28);
    
        if (value & (0x1U << 2))   /* Capture interrupt */
        {
            // GPIO_pinWriteHigh(gpioDO1BaseAddr, CONFIG_DO1_PIN);   /* optional toggle */
            tim7val = *(uint32_t *)(gTimer7BaseAddr + 0x3c);
            timercnt = CSL_REG32_RD(gTimer7BaseAddr + 0x50);
            GPIO_pinWriteLow(gpioDO1BaseAddr, CONFIG_DO1_PIN);
        }
    }

    Questions:

    1. Are these latencies expected in a FreeRTOS environment, even with high interrupt priority?

    2. Could there be any system overhead (e.g., context saving, cache misses) that causes such delays?

    3. How can we further reduce or quantify the interrupt latency?

    Any suggestions or insights would be greatly appreciated.

    Thank you!

    
    
  • Hi,

    Please allow some time to go through the above and revert back.

    Regards,

    Tushar

  • Hello,

        Are there any conclusions?

  • Hi Wendy,

    Please expect responses shortly.

    Thanks,

    Vaibhav

  • Hi Wendy,

    I would recommend instrumenting the ISR to identify where the time is being spent. I am sharing a code snippet which uses the CycleCounterP API

    available in the MCU+ SDK DPL.

    Enable the cycle counter once at startup:

    #include <kernel/dpl/CycleCounterP.h>
    
    /* Call once from main() or board init, before any interrupts fire */
    CycleCounterP_reset();
    
    Add a log structure and modify the ISR:
    
    #include <kernel/dpl/CycleCounterP.h>
    
    #define LOG_SIZE 500
    
    typedef struct {
    uint32_t hw_capture_ticks; /* T1: hardware-captured count when GPS pulse arrived */
    uint32_t timer_at_entry; /* T2: timer count at first ISR instruction */
    uint32_t pmu_at_entry; /* T2: CPU cycle count at first ISR instruction */
    uint32_t pmu_at_gpio; /* T3: CPU cycle count just before GPIO toggle */
    } IsrLatency_t;
    
    static IsrLatency_t gIsrLog[LOG_SIZE];
    static uint32_t gIsrLogIdx = 0;
    
    void Timer3_isr0(void *args)
    {
    /* Read both counters as the absolute first action */
    uint32_t pmu_entry = CycleCounterP_getCount32();
    uint32_t timer_entry = CSL_REG32_RD(gTimer3BaseAddr + 0x3C); /* TCRR — current count */
    
    uint32_t status = CSL_REG32_RD(gTimer3BaseAddr + 0x28);
    CSL_REG32_WR(gTimer3BaseAddr + 0x28, status); /* clear interrupt */
    
    if (status & (0x1U << 2)) /* capture event */
    {
    /* T1 — written by hardware with zero software delay */
    uint32_t hw_capture = CSL_REG32_RD(gTimer3BaseAddr + 0x50); /* TCAR1 */
    
    if (gIsrLogIdx < LOG_SIZE)
    {
    gIsrLog[gIsrLogIdx].hw_capture_ticks = hw_capture;
    gIsrLog[gIsrLogIdx].timer_at_entry = timer_entry;
    gIsrLog[gIsrLogIdx].pmu_at_entry = pmu_entry;
    gIsrLog[gIsrLogIdx].pmu_at_gpio = CycleCounterP_getCount32(); /* T3 */
    gIsrLogIdx++;
    }
    
    GPIO_pinWriteLow(gpioDO1BaseAddr, CONFIG_DO1_PIN);
    }
    }

    After running, inspect gIsrLog[] in the debugger and calculate:

    Dispatch latency (timer ticks) = timer_at_entry − hw_capture_ticks
    ISR body latency (CPU cycles) = pmu_at_gpio − pmu_at_entry
    ISR body latency (microseconds) = (pmu_at_gpio − pmu_at_entry) ÷ R5F_clock_frequency_in_MHz

    Please share the values from the debugger and we can advise on the next steps based on which latency is dominant in your system.
    Looking forward to your response.

    Regards,

    Vaibhav

  • Hello,

        I have tested according to the method you provided, and the test results are as follows. Based on these test results, what should our next steps be?

        

  • Hi Wendy,

    Does the timer on your setup runs at default 25 MHz? I believe R5 is at 800 MHz?

    Regards,

    Vaibhav

  • Hello,

     I use 200Mhz for timer。

  • We also read the Timer 3 counter value inside the ISR and compare it with the hardware‑captured count value. The maximum difference we observed is over 2000 counts, which translates to about 10 µs

    For timer3 was the frequency set to 25 MHz?

  • Hello,

        No, the timers I am using are configured identically to the ones mentioned above, all at 200M.

  • Hi,

    The assigned expert is out of office today. Please expect delayed responses.

    Regards,

    Tushar

  • Hi Wendy,

    How is the delay observed to be 10 microseconds on your setup?

    Because the code I shared with you to do the profiling, you shared some data, and based on the data, these are the calculations:

    Given values from gIsrLog:
    - hw_capture_ticks = 4,229,503,398
    - timer_at_entry = 4,229,503,682
    - pmu_at_entry = 1,519,370,779
    - pmu_at_gpio = 1,519,371,647
    - Timer frequency: 200 MHz
    - R5F CPU frequency: 800 MHz

    Calculations:

    1. Dispatch Latency (hardware capture → ISR entry)
     = timer_at_entry − hw_capture_ticks
     = 4,229,503,682 − 4,229,503,398 = 284 timer ticks
     = 284 / 200 MHz = 1.42 microseconds
    2. ISR Body Latency (ISR entry → GPIO toggle)
     = pmu_at_gpio − pmu_at_entry
     = 1,519,371,647 − 1,519,370,779 = 868 CPU cycles
     = 868 / 800 MHz = 1.085 microseconds
    3. Total Measured Latency: ~2.5 microseconds

    This is much lower than the observed 10 microseconds . Was the 10 microseconds calculated at timer frequency 25 MHz?

    Regards,

    Vaibhav

  • Hello,

        "No, actually this 10 µs does not occur frequently, but it has indeed happened. I would like to know what causes the current dispatch latency, because in actual testing, this latency is not always at that value – it also jitters. Can it be controlled within 1 µs? Our use case is that when the second pulse (PPS) arrives, we capture it and enter the ISR, and we need to reset the timer immediately to achieve alignment with the second pulse. However, the current situation does not meet our requirements, and I hope to get your help on this.""In the figure, the last set of data shows a difference of about 5.7 µs."

  • Hi Wendy,

    Allow me sometime to check with another expert on this issue.

    Regards,

    Vaibhav

  • Hello Wendy,
    Can you please confirm whether the testing above was done in a debug build or a release build?
    If you tested in the debug build, the results may vary in the release build. Additionally, we are unsure about how your system creates the 10µs delay.
    This delay might occur due to context switching or critical section implementations inside the drivers and applications. Because of this, the interrupt triggers, but it must wait for interrupts to be enabled after the critical sections. Furthermore, if you are running this code on DDR memory, DDR access times could also add to this delay.
    Could you also please confirm where your code is running?
    Regards,
    Anil
  • Hello,

        Thank you for your reply. We are currently in debug mode, running from DDR. The issue at hand is that it is not fixed; if this latency were constant, we could compensate for it. Do you mean that in release mode, the deviation in this latency will be significantly smaller? What is the maximum possible deviation when running from DDR?

  • Hello Wendy,
    Yes, you need to run this example in release mode, as the release build is  used in production.
    This latency represents the correct number.
    As I mentioned above, latency is caused by many factors—such as DDR memory access, task context switching, and critical sections. Therefore, it is not possible to predict the maximum deviation value in Theoretical way. This requires evaluation across different test cases:
    Test Case 1: Run the application with the release build and share the results.

    Regards,
    Anil
  • Hello,

        When selecting the release build, we encounter a question about the optimization level. Under normal circumstances, what should this optimization level be determined by?

  • Hi,

    I was out last week for a couple of days, I am back today, please expect responses within a day or two!

    Regards,

    Vaibhav

  • Hello Wendy,
    By default, we use the -Os optimization level for all examples in the release build.
    You can verify these flag settings directly inside the project's Makefile.
    The -Os optimization level enables all optimizations available at -O2, plus additional optimizations designed specifically to reduce code size while mitigating negative impacts on performance.
    Please look at the link below for your reference.
    Regards,
    Anil.