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.

TMS320F2810: Incorrect hardware timer counter value

Part Number: TMS320F2810
Other Parts Discussed in Thread: CC3200

Hello there,

                  We are using the hardware timer for unix timestamp increment in second. But the hardware timer always interrupt in milliseconds. Below is the code we have used. The problem we have found is that every 4 hours before we update the timestamp after getting the actual timestamp from server to the MCU, the MCU timestamp is 2 seconds faster than the actual update server timestamp. If we do not update the timestamp, after may be 4 or 5 days, the timestamp will go around 15 seconds faster than the actual current timestamp.

static interrupt void SystickInterruptHandler()
{
    ui64SysTickCounter++;

    /* Need to call the extern variable for increasing the UNIX timestamp*/
    if ( g_UnixTimestamp != 0 )
    {
        if ( (ui64SysTickCounter % 1000 ) == 0 )
        {
            g_UnixTimestamp++;
        }
    }

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

static void Timer0Initialise(float freq, float period)
{
    uint32_t tick;
    tick = (uint32_t)(freq * period);
    CpuTimer0Regs.PRD.all = tick;
    CpuTimer0Regs.TPR.all = 0;
    CpuTimer0Regs.TPRH.all = 0;

    CpuTimer0Regs.TCR.bit.TSS = 1;      // 1 = Stop timer, 0 = Start/Restart Timer
    CpuTimer0Regs.TCR.bit.TRB = 1;      // 1 = reload timer
    CpuTimer0Regs.TCR.bit.SOFT = 1;
    CpuTimer0Regs.TCR.bit.FREE = 1;     // Timer Free Run
    CpuTimer0Regs.TCR.bit.TIE = 1;      // 0 = Disable/ 1 = Enable Timer Interrupt

    ui64SysTickCounter = 0;

    EALLOW;
    PieVectTable.TINT0 = &SystickInterruptHandler;
    EDIS;

    CpuTimer0Regs.TCR.bit.TSS = 0;

    IER |= 0x0001;

    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
}

void Hwtimer_Initialise(void)
{
    Timer0Initialise(150000000, 0.001); // 150KHz and 1ms timer.
}

So what could go wrong in the code and what other things that we need to implement in the code.

g_UnixTimestamp is the timestamp that always showing faster by 2 seconds than the actual current time.

Thanks

  • HI Ganesh,

    Have you referred to the Example_281xCpuTimer.c file within this download ?

    C:\tidcs\c28\DSP281x\v120\DSP281x_examples\cpu_timer.

    The respective functions for the timer initialization and configuration can be found in the following files:

    C:\tidcs\c28\DSP281x\v120\DSP281x_common\source\DSP281x_CpuTimers.c

    C:\tidcs\c28\DSP281x\v120\DSP281x_headers\include\DSP281x_CpuTimers.h

     

    Ganesh Gurung58 said:
    The problem we have found is that every 4 hours before we update the timestamp after getting the actual timestamp from server to the MCU, the MCU timestamp is 2 seconds faster than the actual update server timestamp.

    At which point does the server timestamp start?

    Best Regards,

    Marlyn

  • Hi Marlyn,

                      Thanks, i will look into it. We get the timestamp when power up device and as soon as CC3200 connect to WIFI, it will get the timestamp. I would say after 1 minute of wifi connection.

  • Hi there,

                  I read the example code. Hmm looks different than what we have done. I have a question though.

    In your example for 1 second timer interrupt you set as below

    ConfigCpuTimer(&CpuTimer0, 100, 1000000);


    If i need to do 1ms timer interrupt what setting should i have to do.

    is it ConfigCpuTimer(&CpuTimer0, 100, 1000000000); ?

    or 

    is it ConfigCpuTimer(&CpuTimer0, 100, 1000); ?

    By the way how do we know our CPU frequency in the chip?

    Thanks

  • Hi there,

    i think i understand how the cpu clock is set. The external clock is 30MHz and  SysCtrlRegs.PLLCR.bit.DIV = 0xA; //set to 150MHz . PLL at ((30*10)/2). So the CPU clock should be 150 MHZ.

    As from the above code i mentioned is the Timer0Initialise(150000000, 0.001); which is basically doing 1ms timer interrupt. It seems our code is right.

    So what else could be the problem?

    Thanks

  • Hi Ganesh,

    For your first question if you were to use the example functions then a 1ms timer would be:  ConfigCpuTimer(&CpuTimer0, 100, 1000); 

    Ganesh Gurung58 said:
    So the CPU clock should be 150 MHZ.

     

    Yes, this should be correct. The code you have should generate a 1ms timer interrupt. An alternative way to write it would be Timer0Initialise(150, 1000);

    After writing to the PLLCR register DIV field do you wait the 131072 OSCCLK cycles for PLL to become stable?

    Here is an excerpt from page 51 in TMS320x281x DSP System Control and Interrupts Reference Guide

    The PLLCR register DIV field (bits 3−0) is used to change the PLL multiplier of the device. When the CPU writes to the DIV bits, the PLL logic switches the CPU clock (CLKIN) to OSCCLK/2. Once the PLL is stable and has locked at the new specified frequency, the PLL switches CLKIN to the new frequency as shown in Figure 3−6. The time it takes for the PLL to switch from OSCCLK/2 to the new frequency is 131072 OSCCLK cycles. For time-critical software, you should insert a software delay of the required locking period after writing to the PLLCR register in order for the PLL to complete the locking sequence

    An example of this is shown in the InitPll function within C:\tidcs\c28\DSP281x\v120\DSP281x_common\source\DSP281x_SysCtrl.c

    Best Regards,

    Marlyn

  • Hi Marlyn,

    Yes we wait the 131072 OSCCLK.

    void InitSysCtrl()
    {
        volatile uint32_t ui32LockCounter;
        EALLOW;
        SysCtrlRegs.WDCR = 0x0068;
        SysCtrlRegs.PLLCR.bit.DIV = 0xA; //set to 150MHz . PLL at ((30*10)/2)
        //Wait for the PLL to lock
        for(ui32LockCounter = 0; ui32LockCounter < ((131072u / 2u) / 12u); ui32LockCounter++)
        {
            //Just loop
        }
        //SetUp the peripheral clock's
        SysCtrlRegs.HISPCP.bit.HSPCLK = 3; //Clock set to 25MHz
        SysCtrlRegs.LOSPCP.bit.LSPCLK = 2; //Clock set to 37.5MHz
    }

    Is 150MHz very stable in this MCU?

    Thanks

  • Hi Ganesh,

    Interesting experiment.

    How accurate is the 30MHz clock input?

    Oscillator output can drift and also may have small deviation from the center frequency.  Say a tolerance spec of 50 PPM, it will add up in few hours. 

    50(PPM) * 30 (MHz) * 5 (xPLL) * 3600 (seconds) * 4 hours = 0.7 seconds worth of extra pulses; your oscillator may be a off a little more. 

    Clocks drift, so like you did they need to be sync'd periodically to reference same time. Increase your millisecond timer period by 20 counts to 150020 to reduce the time drift. Also how are you syncing the time? are you clearing millisecond counter also? why 64bits?

    Thanks,

    Joe

  • Hi Joe,

               Possibilities that the oscillator output can be drift and small deviation can change the frequency change as you mentioned before message.

    Good question that we have not clear the millisecond counter value when update the timestamp but that will give only 1 second difference. We update the g_UnixTimestamp when received the timestamp from the server. 

    Another good question is why we are using 64 bits for milliseconds. Hmm actually 32 bit should be enough. Does it make any difference if we use 64 bits for milliseconds counter?

    We will let you know once we increase the millisecond timer period by 20. Let see how it goes.

    Thanks