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.

CCS: TDA4VM:mcu timer period Imprecision

Other Parts Discussed in Thread: SYSBIOS

Tool/software: Code Composer Studio

 I use mcu_timer0 with period 1.333ms and mcu_timer 1,2 with period 0.5ms.

 The interrupt frequency of mcu_timer0 is 600Hz which is precise.however, The interrupt frequency of mcu_timer1&2  is about  1530Hz(should be 2000HZ) .

I used the api: timerP_create, sdk version 6.02

  • Hi Ronaldo,

    Can you please share the code snippets where you are configuring the timer tasks, also please share the Timer ISR functions. It could very well be possible that the Timer ISR itself takes more than 0.5ms and hence what will happen is that the ISRs will start queuing and this could mess up the expected recurrence time.

    Also, do you mean mcu_timer0 with a period of 1.666ms? That would lead to a interrupt frequency of 600Hz.

    Regards,
    Karan

  • Hi Karan,

    It is impossible that the ISR handler takes more than 0.5ms. Even I setup the timer expectation duration as 1s, the actual duration is 1.3s. The code is as below:

    static uint32_t expt_ns = 1000000000UL;

    static void timer_handler(unitptr_t arg)

    {

        DEBUG_PRINTF("expt_ns:%u\r\n", expt_ns);

    }

    static void __timer_setup(void)

    {

        TimerP_Params timerParams;

        TimeP_Handle timerHandle;

        TimeP_Params_init(&timerParams);

        timerParams.startMode = TimerP_StartMode_USER;

        timerParams.PeriodType = TimerP_PeriodType_MICROSECS;

        timerParams.Period  = expt_ns / 1000;

        timerParams.arg = NULL;

        timerParams.runMode = TimerP_RunMode_CONTINUOUS;

        timerHandle = TimeP_create(2, (TimerP_Fxn)timer_handler, &timerParams);

        if (timerHandle != NULL_PTR)

        {

            TimerP_start(timerHandle);

        }

    }

    The result is as below:

    <510.321>exp_ns:1000000000

    <511.621>exp_ns:1000000000

    <512.921>exp_ns:1000000000

    <514.223>exp_ns:1000000000

    <515.525>exp_ns:1000000000

    <516.825>exp_ns:1000000000

    the number in <> is the uptime calculated by timer0, which is accurate(has tested with the standard clock)

    Regards,
    Ronaldo

  • Hi Ronaldo,

    I'm trying to replicate the issue locally, can you please let me know are you using a baremetal or a bios application? Also, is this your code or you are trying to modify an existing application?

    Regards,

    Karan

  • Hi Karan,

    I'm running a baremeta application,  and it is my own application code, not based on demo application

    Regards,

    Ronaldo

  • Hi Ronaldo,

    I verified on a SYSBIOS application and all timers (except the one used by BIOS itself show the same behaviour).

    So will it be possible to share the source code of your baremetal application, so that we can reproduce the problem?

    As a quick check can you replace all the timerIDs (0,1 and 2) by TimerP_ANY, this will make sure that you get the timer from the free pool of timers available. Let me know if this too result in the similar kind of behavior.

    Also, please provide more details on how and in what context are you running the baremetal app, is it using SBL, CCS+GELs or via uboot?

    Regards,

    Karan

  • Hi Karan,

    What do you mean "all timers (except the one used by BIOS itself show the same behaviour).".all the timer can run in the right frequency? have you checked if the frequency is right? besides, i can not give you my application source code. but the related source codes are shown in my reply. its api TimeP_create TimeP_start are in TimeP_nonos.c, what else do you need? 

    Regards,

    Ronaldo

  • Hi Ronaldo,

    I think I found the issue, can you please try to use the following piece of code in your application -

        /* The below goes to your main() where you are creating the timers */    
    
        config_pmu(); // for taking timestamp, you can use your own instrumentation
        TimerP_Params timerParams;
        TimerP_Handle timerHandle, timerHandle1, timerHandle2;
        TimerP_Params_init(&timerParams);
        timerParams.startMode = TimerP_StartMode_USER;
        timerParams.periodType = TimerP_PeriodType_MICROSECS;
    
        /* This should be more than the execution time of the ISR */
        timerParams.period  = 60000; //60ms
        timerParams.arg = NULL;
    
        /* This is the additional thing added */
        timerParams.intfreqLo = 19200000;
        timerParams.intfreqHi = 0;
    
        timerParams.runMode = TimerP_RunMode_CONTINUOUS;
    
        /* Use TimerP_ANY in all the TimerP_create() */
        timerHandle = TimerP_create(TimerP_ANY, (TimerP_Fxn)timer_handler, &timerParams);
        timerHandle1 = TimerP_create(TimerP_ANY, (TimerP_Fxn)timer_handler1, &timerParams);
        timerHandle2 = TimerP_create(TimerP_ANY, (TimerP_Fxn)timer_handler2, &timerParams);
    
        if (timerHandle != NULL_PTR)
        {
            TimerP_start(timerHandle);
        }
        else
        {
            AppUtils_Printf(MSG_NORMAL, 
            "Not able to create timer !!!\n");
        }
        if (timerHandle1 != NULL_PTR)
        {
            TimerP_start(timerHandle1);
        }
        else
        {
            AppUtils_Printf(MSG_NORMAL, 
            "Not able to create timer1 !!!\n");
        }
        if (timerHandle2 != NULL_PTR)
        {
            TimerP_start(timerHandle2);
        }
        else
        {
            AppUtils_Printf(MSG_NORMAL, 
            "Not able to create timer2 !!!\n");
        }
    
    /* You can add you custom ISRs now, I would suggest the use of PMU to get the cycle count */

    So the reason for the issue is that by default the timerParams have a field for the freq of the clock driving the timer and that by default is 25MHz and the actual clock however is 19.2MHz (I need to check if this is a bug and we need to change the default values)

    So when you were configuring the timer for 1sec it was taking 1.3secs (as 25/19.2 = 1.3). So now when you override the default value by actual (19.2MHz) the behavior is consistent. I've used T = 60ms in the code. Also I use PMU counter to take time stamp, you can use your own method or use my reference code as below -

    /* File needs to be included */
    #include <ti/csl/arch/r5/csl_arm_r5_pmu.h>
    
    #define PMU_EVENT_COUNTER_1 (CSL_ARM_R5_PMU_EVENT_TYPE_CYCLE_CNT)
    #define PMU_EVENT_COUNTER_2 (CSL_ARM_R5_PMU_EVENT_TYPE_ICACHE_STALL)
    #define PMU_EVENT_COUNTER_3 (CSL_ARM_R5_PMU_EVENT_TYPE_DCACHE_MISS)
    
    /* To use PMU instrumentation, call the config_pmu() once during init time.
     *
     * Reset the counters using CSL_armR5PmuResetCntrs() API.
     * Then use CSL_armR5PmuReadCntr() with argument 0, 1 or 2 to capture value
     * of 1st, 2nd or 3rd PMU counter. 
     */
    
    uint32_t config_pmu(void)
    {
    
        CSL_armR5PmuCfg(0, 0 ,1);
        CSL_armR5PmuEnableAllCntrs(1);
        int32_t num_cnt = CSL_armR5PmuGetNumCntrs();
    
        CSL_armR5PmuCfgCntr(0, PMU_EVENT_COUNTER_1);
        CSL_armR5PmuCfgCntr(1, PMU_EVENT_COUNTER_2);
        CSL_armR5PmuCfgCntr(2, PMU_EVENT_COUNTER_3);
    
        CSL_armR5PmuEnableCntrOverflowIntr(0, 0);
        CSL_armR5PmuEnableCntrOverflowIntr(1, 0);
        CSL_armR5PmuEnableCntrOverflowIntr(2, 0);
        CSL_armR5PmuResetCntrs();
        CSL_armR5PmuEnableCntr(0, 1);
        CSL_armR5PmuEnableCntr(1, 1);
        CSL_armR5PmuEnableCntr(2, 1);
        return 0;
    }
    
    static uint32_t expt_ns = 1000000000UL;
    static uint64_t timerTaskTS;
    static uint64_t timerTaskTS1;
    static uint64_t timerTaskTS2;
    
    static void timer_handler(void)
    {
        timerTaskTS = CSL_armR5PmuReadCntr(0);
        AppUtils_Printf(MSG_NORMAL,
                        " timerTaskTS: %u\r\n", timerTaskTS);
    }
    
    static void timer_handler1(void)
    {
        timerTaskTS1 = LOCAL_getCycleCnt();
        AppUtils_Printf(MSG_NORMAL,
                        " timerTaskTS1: %u\r\n", timerTaskTS1);
    }
    
    static void timer_handler2(void)
    {
        timerTaskTS2 = LOCAL_getCycleCnt();
        AppUtils_Printf(MSG_NORMAL,
                        " timerTaskTS2: %u\r\n", timerTaskTS2);
    }

    Output comes out like the following, showing 60ms between ISR hits for all 3 timers.

    Timer period = 60ms
    ISR INTERVAL (ns) TS Delta (ns) TS1 Delta (ns) TS2 Delta (ns)
    timerTaskTS 1334522052 60000000    
    timerTaskTS1 1484281610   60000000  
    timerTaskTS2 1495925627     60000000
    timerTaskTS 1394522052 60000000    
    timerTaskTS1 1544281610   60000000  
    timerTaskTS2 1555925627     60000000
    timerTaskTS 1454522052 60000000    
    timerTaskTS1 1604281610   60000000  
    timerTaskTS2 1615925627     60000000
    timerTaskTS 1514522052 60000000    
    timerTaskTS1 1664281610   60000006  
    timerTaskTS2 1675925627     60000000
    timerTaskTS 1574522052 60000000    
    timerTaskTS1 1724281616   60000000  
    timerTaskTS2 1735925627     60000000
    timerTaskTS 1634522052 60000000    
    timerTaskTS1 1784281616   60000000  
    timerTaskTS2 1795925627     60000000
    timerTaskTS 1694522052      
    timerTaskTS1 1844281616      
    timerTaskTS2 1855925627      

    There is still one question however, how were you able to still get the correct timing initially with timerID = 0. But first we can try the above and get you unblocked.

    Regards,

    Karan

  • Hi Karan,

    your last reply solved my problem, thanks a lot.

    Regards,

    Ronaldo