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.

AM4376: TimerP_getTimeInUsecs function issue

Part Number: AM4376

We are using the TimerP_ getTimeInUsecs function several times in our interrupt which is called every 1ms. The interrupt calls TimerP_ getTimeInUsecs, performs a few operations, calls TimerP_ getTimeInUsecs again, then starts the timer again by calling TimerP_start(). We are currently running a test where we measure the number of microseconds before and after 64 calls to this interrupt. When running this test for an hour we see that the number of microseconds it takes for the interrupt to run 64 times continues to increase over time. We have found that by commenting out the calls to the TimerP_getTimeInUsecs function, that the time it takes for 64 interrupts no longer continuously increases. This seems to indicate that the TimerP_getTimeInUsecs function, or functions called by it, take longer to run over time. I realize that by performing operations before the call to TimerP_start() we will not have a consistent/accurate time, however that would not explain a continuously increasing time to complete 64 interrupts, especially when considering that removing calls to TimerP_getTimeInUsecs() resolves the issue.

  • Hi Ryan,

    Can you please clarify a bit?

    >> interrupt which is called every 1ms
    this interrupt is fired by hardware besides the Timer you're using for benchmarking?

    >> TimerP_ getTimeInUsecs function several times
    you call this function multiple times in the ISR to benchmark portions of the ISR?

    >> then starts the timer again by calling TimerP_start()
    Why does the Timer need to be started, and why isn't it running continuously? When is the Timer stopped?

    >> We are currently running a test where we measure the number of microseconds before and after 64 calls to this interrupt
    Where do these measurements take place? In a main thread? Are you using calls to TimerP_ getTimeInUsecs() in this main thread?

     >> We have found that by commenting out the calls to the TimerP_getTimeInUsecs function, that the time it takes for 64 interrupts no longer continuously increases
    Commenting out the calls where? In the ISR?

    >> I realize that by performing operations before the call to TimerP_start() we will not have a consistent/accurate time
    Again, when is the Timer stopped such that it needs to be re-started?

    Perhaps there's a bug in OSAL TimerP. Would it be possible for you to share a simple example code which demonstrates this issue?

    Regards,
    Frank

  • Hi Ryan,

    A couple of more questions:

    Is this an RTOS or bare-metal application?

    What version of PRSDK are you using?

    Thanks,
    Frank

  • Frank,

    See clarifications below:

    >> interrupt which is called every 1ms
    >> this interrupt is fired by hardware besides the Timer you're using for benchmarking?

    The interrupt is fired by timer 4, the TimerP_getTimeInUsecs is configured in osalArch_TimestampInit to use timer 5. Both timers are configured using the TimerP_Params_init and TimerP_create functions.

    >> TimerP_ getTimeInUsecs function several times
    >> you call this function multiple times in the ISR to benchmark portions of the ISR?

    This function is called multiple times in the ISR.

    >> then starts the timer again by calling TimerP_start()
    >> Why does the Timer need to be started, and why isn't it running continuously? When is the Timer stopped?

    The TimerP for the interrupt is configured as:
    .startMode = TimerP_StartMode_USER;
    .runMode = TimerP_RunMode_ONESHOT;

    >> We are currently running a test where we measure the number of microseconds before and after 64 calls to this interrupt
    >> Where do these measurements take place? In a main thread? Are you using calls to TimerP_ getTimeInUsecs() in this main thread?

    Yes, the measurements are done in a main thread, and we are using TimerP_getTimeInUsecs in that thread.

    >> We have found that by commenting out the calls to the TimerP_getTimeInUsecs function, that the time it takes for 64 interrupts no longer continuously increases
    >> Commenting out the calls where? In the ISR?

    Commenting out the calls to TimerP_getTimeInUsecs inside the ISR.

    >> I realize that by performing operations before the call to TimerP_start() we will not have a consistent/accurate time
    >> Again, when is the Timer stopped such that it needs to be re-started?

    See above answer for timer configuration.

    >> Perhaps there's a bug in OSAL TimerP. Would it be possible for you to share a simple example code which demonstrates this issue?

    Our PRSDK is pdk_am437x_1_0_15
    I can share some pseudo code, but it is not possible to share a working example at this time.

    void measure_thread( )
    {
        schedule a sem post every 64 calls to interrupt

        while(1)
        {
            pend on semaphore;

            current_time = TimerP_getTimeInUsecs;

            print current_time - previous_time;

            current_time = previous_time;
        }
    }

    void timer_interrupt( )
    {
        start_time = TimerP_getTimeInUsecs; //removing this line resolves the problem

        Do some things

        end_time = TimerP_getTimeInUsecs; //removing this line resolves the problem

        TimerP_start();
    }

    Please see below charts plotting the time in microseconds it takes between measurements from the main thread (64 interrupts). The top chart is with calls to TimerP_getTimeInUsecs in the interrupt, the bottom chart is without. Notice that the top chart the total time continues to increase, while the bottom time value remains relatively the same.

  • Hi Ryan,

    Thanks for the feedback.

    Just to confirm / summarize:

    • OSAL Timer 4: one shot configuration, started repeatedly (in main thread?)
    • OSAL Timer 5: benchmark timer
    • Calls to TimerP_getTimeInUsecs() (Timer 5) in Timer 4 ISR to benchmark portions of ISR.
    • Calls to TimerP_getTimeInUsecs() (Timer 5) before / after 64 Timer 4 one-shot starts.
    • Calls to TimerP_getTimeInUsecs() in ISR: time for 64 Timer 4 ISRs increases.
    • Calls to TimerP_getTimeInUsecs() not in ISR: time for 64 Timer 4 ISRs remains the same (some variance, but no clear upward trend). 

    I gather this is a SYS/BIOS application since you mention a semaphore in your pseudo code?

    Have you tried bypassing OSAL and directly using the CSL DM Timer API? Please see: 

    • API header: <PDK>\packages\ti\starterware\include\dmtimer.h
    • Example code: <PDK>\packages\ti\starterware\examples\dmtimer

    Regards,
    Frank

  • Frank,

    • OSAL Timer 4: one shot configuration, started repeatedly (in main thread?)
      • This is started repeatedly in the ISR.
    • OSAL Timer 5: benchmark timer
      • Correct
    • Calls to TimerP_getTimeInUsecs() (Timer 5) in Timer 4 ISR to benchmark portions of ISR.
      • Correct
    • Calls to TimerP_getTimeInUsecs() (Timer 5) before / after 64 Timer 4 one-shot starts.
      • Correct, from main thread
    • Calls to TimerP_getTimeInUsecs() in ISR: time for 64 Timer 4 ISRs increases.
    • Calls to TimerP_getTimeInUsecs() not in ISR: time for 64 Timer 4 ISRs remains the same (some variance, but no clear upward trend). 
      • Correct, with calls to TimerP_getTimeInUsecs() present in the ISR, the total time for 64 Timer 4 ISRs increases.

    >> Have you tried bypassing OSAL and directly using the CSL DM Timer API?

    I have not tried this yet, I will test it out over the weekend and let you know Monday.

    Thanks,

    Ryan

  • I'm not sure that the dmtimer is what we are looking for, that seems to be only a countdown timer. I realize I have made a mistake in my description earlier, it appears that Timer 5 is only set up to call osalArch_TimestampCcntAutoRefresh to handle timer overflows. The TimerP_getTimeInUsecs() function calls down to osalArch_TimestampGet64() which calls osal_TimestampProvider_readCntr() and osal_TimestampProvider_getOverflowCCNT(). It is reading the PMCCNTR cycle count register.

  • Hi Ryan,

    Thanks for the follow up and clarification.

    Can you please put together a simple example demonstrating the problem?

    Regards,
    Frank