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.

CC2652R7: Internal Timer count doesn't reset in one shot mode

Part Number: CC2652R7

Hello, 

I was trying to run a one-shot timer multiple times. What I did was start the timer and stopped it mid way and then reran it. On the second run it doesn't complete the full period but starts off where it was stopped. I created a test below that shows this functionality. I am using a CC2652R7 board with the SDK : 7_10_01_24. I presume the internal timer count isn't being reset until the count reaches the period.

Regards,
Kenneth Thomas

sem_t timer_sem;

void timerCallback(Timer_Handle handle, int_fast16_t status)
{
sem_post(&timer_sem);
}

void testTimer()
{
sem_init(&timer_sem, 0, 0);

// Configure Timer parameters for one-shot callback after one second
Timer_Handle timer;
Timer_Params timer_params;
Timer_Params_init(&timer_params);
timer_params.periodUnits = Timer_PERIOD_US;
timer_params.period = 1000000;
timer_params.timerCallback = timerCallback;
timer_params.timerMode = Timer_ONESHOT_CALLBACK;

// Start/stop timer before it can finish
bool stop_early_and_restart = true;
if (stop_early_and_restart)
{
timer = Timer_open(CONFIG_TIMER_3, &timer_params);
Timer_start(timer);
usleep(500000);
Timer_stop(timer);
Timer_close(timer);
}

// Restart timer but let it finish
timer = Timer_open(CONFIG_TIMER_3, &timer_params);
uint32_t start_ticks = ClockP_getSystemTicks();
Timer_start(timer);
sem_wait(&timer_sem);
uint32_t stop_ticks = ClockP_getSystemTicks();
Timer_stop(timer);
Timer_close(timer);

printf("[TIMER] Elapsed time = %d msec", ((stop_ticks - start_ticks) * ClockP_getSystemTickPeriod()) / 1000);

sem_destroy(&timer_sem);
}

  • Hello Kenneth Thomas,

    When calling timer_close the time should be reset, as timer_close calls GPTimerCC26xx_resetHw(); you could if needed call this function, though it is not needed. You can also use the timer function to set the timer period (Timer_setPeriod) to see if that would help your project. A great resource that could help answer some other questions can be found on a similar topic discussed on this E2E thread (https://e2e.ti.com/f/1/t/1269670/), although note that this is for a different device. 

    Thanks,
    Alex F

  • Hey Alex, 

    Thanks for the E2E thread, it really helped. 

    This is the code I needed to call because there was a problem with the driver code.
    HWREG(gpt_handle->hwAttrs->baseAddr + GPT_O_TAV) = 0xFFFFFFFF;
    HWREG(gpt_handle->hwAttrs->baseAddr + GPT_O_TBV) = 0xFFFFFFFF;

    Sincerely, 
    Kenneth

  • Hey Alex, 

    Do you also mind checking this test code to see if I'm changing the values of the registers the "correct" way? 

    sem_t timer_sem;
    
    void timerCallback(Timer_Handle handle, int_fast16_t status)
    {
    sem_post(&timer_sem);
    }
    
    void testTimerDriver()
    {
    sem_init(&timer_sem, 0, 0);
    
    // Configure Timer parameters for one-shot callback after one second
    Timer_Handle timer;
    Timer_Params timer_params;
    Timer_Params_init(&timer_params);
    timer_params.periodUnits = Timer_PERIOD_US;
    timer_params.period = 1000000;
    timer_params.timerCallback = timerCallback;
    timer_params.timerMode = Timer_ONESHOT_CALLBACK;
    
    // Start/stop timer before it can finish
    bool stop_early_and_restart = true;
    if (stop_early_and_restart)
    {
    timer = Timer_open(CONFIG_TIMER_3, &timer_params);
    Timer_start(timer);
    usleep(500000);
    Timer_stop(timer);
    
    // Timer driver bug-fix/hack, implemented in our Timer class
    GPTimerCC26XX_Handle gpt_handle = ((TimerCC26XX_Object*)timer->object)->gptHandle;
    //CommandLine::log("TAV (0x%X) = %d", gpt_handle->hwAttrs->baseAddr + GPT_O_TAV, HWREG(gpt_handle->hwAttrs->baseAddr + GPT_O_TAV));
    //CommandLine::log("TBV (0x%X) = %d", gpt_handle->hwAttrs->baseAddr + GPT_O_TBV, HWREG(gpt_handle->hwAttrs->baseAddr + GPT_O_TBV));
    HWREG(gpt_handle->hwAttrs->baseAddr + GPT_O_TAV) = 0xFFFFFFFF;
    HWREG(gpt_handle->hwAttrs->baseAddr + GPT_O_TBV) = 0xFFFFFFFF; // TODO: Determine if this is invalid for 16-bit timers
    
    Timer_close(timer);
    }
    
    // Restart timer but let it finish
    timer = Timer_open(CONFIG_TIMER_3, &timer_params);
    uint32_t start_ticks = ClockP_getSystemTicks();
    Timer_start(timer);
    sem_wait(&timer_sem);
    uint32_t stop_ticks = ClockP_getSystemTicks();
    Timer_stop(timer);
    Timer_close(timer);
    
    CommandLine::log("[TIMER] Elapsed time = %d msec", ((stop_ticks - start_ticks) * ClockP_getSystemTickPeriod()) / 1000);
    
    sem_destroy(&timer_sem);
    }

    Thanks,
    Kenneth

  • Hello Kenneth, 

    I hope you are well. Taking a look at the provided code snippet above looks good at first glance, looking specifically at line 34/35 you are effectively trying to do HWREG(0x40010050) = 0xFFFFFFFF, and HWREG(0x40010054) = 0xFFFFFFFF right? If so then your process seems correct, as an extra step you can try and set a breakpoint before line 34/35 (lets say 31) and then see how the register updates during debug. 

    Thanks,
    Alex F