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.

AM625-Q1: MCU_TIMER3 Consistent Timer Discrepancy in FreeRTOS

Part Number: AM625-Q1
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello, 

We're experiencing a consistent ~24-tick discrepancy when reading MCU_TIMER3 on AM625-Q1 in FreeRTOS. We are using the timer in free-running mode (with overflow at approximately 171.8 seconds) as a replacement for the SysTick timer in an I2C driver.

We are reading the timer counter register (TCRR) directly and storing the value in a prevCount variable. On each iteration, we compare the current timer count with prevCount to detect overflows (when the current count is less than prevCount).

We are consistently observing a discrepancy where prevCount is greater than the current timer count by around 24 ticks before an actual timer overflow occurs. This discrepancy appears to be coming from the timer itself, as the inconsistent values are being read directly from the TCRR register.

Our questions

  1. How is it possible for an upward-counting timer to exhibit this behavior, where the previously read value is sometimes larger than the current value, but not due to a true overflow? We've ruled out typical software issues like non-atomic access or incorrect overflow handling.

  2. Are there any known limitations or errata related to MCU_TIMER3 on the AM625-Q1 that might cause this periodic 24-tick discrepancy? We've reviewed datasheet but haven't found anything that directly addresses this specific behavior. We are using CONFIG_TIMER3_CLOCK_SRC_MCU_HFOSC0 as the clock source.

  3. Could there be interactions with the I2C peripheral or its driver that might interfere with the timer's operation?

    We have also attached the relevant code snippets and our SysConfig timer settings.

 

-------------------------API to setup timer as free-running--------------

void TimerP_setup(uint32_t baseAddr, TimerP_Params *params)
{
    volatile uint32_t *addr;
    uint32_t ctrlVal = 0u;

    DebugP_assert( baseAddr!=0U);
    (void)params;
    /* stop timer and clear pending interrupts */
    TimerP_stop(baseAddr);

    /* autoreload timer */
    ctrlVal |= (0x1U << 1);
    /* Compare enable*/
    ctrlVal |= (0x1U << 6);

    
    /* set timer control value */
    addr = (volatile uint32_t *)(baseAddr + TIMER_TCLR);
    *addr = ctrlVal;
    
    /* set timer count value */
    addr = (volatile uint32_t *)(baseAddr + TIMER_TCRR);
    *addr = 0u;
    
    /* set reload value */
    addr = (volatile uint32_t *)(baseAddr + TIMER_TLDR);
    *addr = 0u;
}

---------------------------API to get Count---------------------------------------

uint32_t TimerP_getCount(uint32_t baseAddr)
{
    volatile uint32_t *addr = (volatile uint32_t *)(baseAddr + TIMER_TCRR);
    uint32_t count;
    uintptr_t key;

    key = HwiP_disable();    // Disable interrupts/enter critical section

    count = *addr;       // First read (dummy read)
    count = *addr;       // Second read (actual value)

    HwiP_restore(key);   // Re-enable interrupts/exit critical section

    if (prevCount > count && prevCount != 0) 
    {
         // Check and log only if it's not the initial state
         DebugP_log("Timer Discrepancy: prevCount=%u, count=%u\r\n", prevCount, count);
    }

    prevCount = count;  // Update prevCount *after* the check

    return count;
}
-------------------------------------------------------------------------