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.

TDA4VE-Q1: Clock accuracy issue

Part Number: TDA4VE-Q1

Tool/software:

Hi TI experts,

SDK:9.2

Linux:9.2

HW:our own board

We use timer16(0x2500000UL) now,the current external crystal oscillator is 19.2m, so the time for one tick is calculated as 1/19200000.We achieve different timer clock accuracies by setting the value of the TIMER_TMAR register, but the actual outcome is not as expected
1. The first version of the software set this count value to 19200, * 1/19200000=1000us=1ms, and the software set the fsync cycle to 33 * 1ms. In this case, the fsync pulse cycle is around 33.1ms or 33.2ms, with an accuracy of 1ms;
2. The second version of the software sets this count value to 1920, * 1/19200000=100us, and the software sets the fsync period to 333 * 100us. In this case, the fsync pulse period is 33.2ms-33.4ms, and the accuracy is inaccurate at 100us;
3. The third version sets this count to 192, * 1/19200000=10us, and the software sets the fsync cycle to 3333 * 10us. In this case, the fsync pulse cycle is a few milliseconds, with an error of milliseconds and an accuracy of 10us that is inaccurate;
4. The final version is the version currently on the server, and the accuracy cannot be adjusted downwards. We have changed our approach and adjusted the accuracy upwards. Based on the original 1ms count value, we calculated it as 1.11, which is equivalent to 19200 * 1.11=21312. The software has set the pulse period to 30 * 1.11ms=33.3ms. Currently, the accuracy has been tested and meets the requirements of their application;

The current issue is:
1. Why does setting the TIMER_TMAR value to 1920 and 21312 result in different results when the clock accuracy is adjusted to 33.3ms?
2. Can the minimum clock accuracy of a timer be 1ms? Is there a way to improve clock accuracy?
3. In addition, we found that even if the TIMER_TMAR register value is set to 21312, a normal 33.3ms pulse period can be achieved. However, in some scenarios with high resource loads, this 33.3ms period may fluctuate and sometimes reach 35ms. Is there any way to stabilize the pulse period at 33.3ms?

BR.

  • Hi,

    Due to a US holiday, the engineer responsible is currently out of office. Apologies for the delay, and thank you for your patience.

    Warm regards,

    Christina

  • Hi,

    May I ask if there are any new updates?

    BR.

  • Hello,

    -0-

    Can you describe how you are measuring the period?   Is the measurement from some direct PWM output signal or is some complex SW in place which is counting and reacting to interrupts?

    Scanning the description, I interpret you are setting up an event period of {1mS, 100uS, 10uS} using TMAR and then using some kind of counting software in software to target a 33.xmS period (by counting x33, x333, x3333).   What you report for accuracy seem to indicate the counting SW is off by 1 unit of the counting interval as set by the TMAR in each case.  This would imply whatever SW is doing the counting may be off by 1 (maybe wrong start or stop logic assumption > vs >=).

    In your solution you seem to have adjusted the interval to account for the off by one error and thus got to the desired target rate.

    If this SW is provided by TI, which one is it?  Perhaps it has a bug (SW description or internal logic), or maybe the API is not being used properly.

    -1-

    If I make some simple test of the base counter, I see a cleanly incrementing base, at the input clock rate.  I don't see any discontinuities when sampling + plotting directly from a dedicated bare metal debug task.

    Can you provide a dump of all the TIMER16 registers and a better description of how you are measuring.  Perhpas adding the code will allow for reproducing or finding the off by 1 issue. 

    Regards,
    Richard W.
  • Hi Richard W,

    Can you describe how you are measuring the period?   Is the measurement from some direct PWM output signal or is some complex SW in place which is counting and reacting to interrupts?

    The purpose of using a timer is to achieve PWM function while recording the start time of each pulse. We used two methods to measure the pulse period:

    1.The time recorded in the interrupt function of Timer 16 will be periodically printed on the application to determine whether the pulse period is accurate.

    2.Use an oscilloscope to measure.

    If this SW is provided by TI, which one is it?  Perhaps it has a bug (SW description or internal logic), or maybe the API is not being used properly.

    The software implementation method does not come from TI. I have provided the implementation of the interrupt function in the following code.

    Can you provide a dump of all the TIMER16 registers and a better description of how you are measuring. 

    The software implementation method does not come from TI. I have provided the implementation of the interrupt function in the following text.

    static void OsSysTimer_ISR(uintptr_t arg)
    {
        uint32_t tempTCRR, reloadValue;
        //static uint32_t cnt = 5;
    
        /* Disable the Timer interrupts */
        OS_WR_REG32(OS_SYS_TIMER_BASE + OS_TIMER_IRQENABLE_CLR, OS_TIMER_IRQENABLE_SET_MAT_EN_FLAG_MASK); 
    	
        //tempTMAR = OS_RD_REG32(OS_SYS_TIMER_BASE + OS_TIMER_TMAR); 
        tempTCRR = OS_RD_REG32(OS_SYS_TIMER_BASE + OS_TIMER_TCRR); 
        reloadValue = tempTCRR + OS_PL_SYSTIMER_RELOAD_VAL;
    
        /* acknowledge the interrupt */
        OS_WR_REG32(OS_SYS_TIMER_BASE + OS_TIMER_IRQSTATUS, OS_TIMER_IRQSTATUS_MAT_IT_FLAG_MASK);
    
        /* Load the register with the match value */
        OS_WR_REG32(OS_SYS_TIMER_BASE + OS_TIMER_TMAR, reloadValue);
    
        //OsCnt_InternalIncreaseCounter(CoreID, Os_CoreCfg[CoreID].startCntId);
        /* Enable the Timer interrupts */
        OS_WR_REG32(OS_SYS_TIMER_BASE + OS_TIMER_IRQENABLE_SET, OS_TIMER_IRQENABLE_SET_MAT_EN_FLAG_MASK); 
        /* Operation on the system clock interrupt register. */
    
        isr_cnt = isr_cnt + 1;
        if(isr_cnt == 1)
        {
            // how to calculate timeStamp ? you can refer to appLogGetGlobalTimeInUsec function
            if (runFreq != 0) {
                timeStamp = (*(volatile uint64_t *)(GTC_TIMER_MAPPED_BASE + 0x8)) / runFreq;
            } else {
                timeStamp = (*(volatile uint64_t *)(GTC_TIMER_MAPPED_BASE + 0x8)) / 200;
       }
    
            (*(volatile unsigned int *) (0x42110000U + 0x18U))  = 0x00008000; /* Set HIGH */
            
        }else if(isr_cnt == 8)
        {
            (*(volatile unsigned int *) (0x42110000U + 0x1CU))  = 0x00008000; /* Set LOW */
        }else if(isr_cnt == 30)
        {
            isr_cnt = 0;
        }
    
    }
    

    BR.

  • Hello,

    Please provide the JTAG dump of all the registers.  There are access rules if the posted feature is set which can result in unexpected results if not followed.  Other registers can also have side effects.  Direct jtag register inspection is very much like looking at using the oscilloscope vs. a software print in that it can show effects from a different and less biased perspective.

    Regards,
    Richard W.