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.

LP-CC1352P7: reset timer count

Part Number: LP-CC1352P7
Other Parts Discussed in Thread: SYSCONFIG

Hi,

I am using two timers as shown in the snapshot.

The Timer_close() API doesnt seem to reset the timer count properly. Hence, calling Timer_start() with a new period value doesn't seem to take effect(callback function isn't called).

For example, here is the code to initialize timer 1:

void timer_1_init(uint32_t period_us)
{
    int32_t status = 0;

    timer_1_flag = 0;

    Timer_Params_init(&timer_1_params);
    timer_1_params.periodUnits = Timer_PERIOD_US;
    timer_1_params.period = period_us;
    timer_1_params.timerMode  = Timer_ONESHOT_CALLBACK;
    timer_1_params.timerCallback = timer_1_callbackfunction;

    Timer_init();

    timer_1_handle = Timer_open(CONFIG_TIMER_1, &timer_1_params);

    if (timer_1_handle == NULL) {
        // Timer_open() failed
        while (1);
    }

}

Here is the code snippet to close and re-start the timer(within a state machine) with a new period value:

timer_1_flag = 0;
Timer_close(timer_1_handle);
timer_1_init(TIMESTAMP_START_TX);
Timer_start(timer_1_handle);

(1) Kindly review the code snippet and let me know if there is any issue with it.

(2) How do I access timer 1 through hardware register address to reset the counter?

Thanks

Karthik

  • Hello Karthik,

    with your configuration of  timer_1_params.timerMode  = Timer_ONESHOT_CALLBACK; a callback will not be invoked if timer_stop() or timer_close() is called before the timer interrupt is triggered. This seems to be the issue here, as the setup looks alright.

    Kindly review the definitions of the Timer modes under: https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_7_10_01_24/docs/drivers/doxygen/html/_timer_8h.html#ab0e86a066b5c68c55183cd680090a9b7

    The timer is always reset when calling Timer_close(). You can however manually reset the timer through the GPTimerCC26xx_resetHw() function call, however this is not necessary as this is called already by Timer_close().

    Regards
    Manuel

     

  • Hi Manuel,

    Very clear explanation!

    Will review my code accordingly.

    What is the effect of using timer_stop? Does it mean, we can immediately call timer_start and the counter continues to count from where it stopped earlier?

    Also, what happens if timer_1_init() is called "again" before the timer interrupt(callback) is triggered?

    Thanks

    Karthik

  • Hi Karthik,

    yes timer_stop() will stop the timer in its current counting and not reset the register. Therefore calling timer_start() counts on from the last value.

    When calling timer_1_init() while the timer is running and before the interrupt, you would need to run timer_start() again for the timer to restart.
    However I think it would be more useful to use Timer_setPeriod() to change the period of your timer. This can be called even during the timer is running. but the value will be updated asychronously.
    Please refer to this for more information: 
    https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_7_10_01_24/docs/drivers/doxygen/html/_timer_8h.html#aee385432bc15af4d7ae919e941341a4c

    Regards
    Manuel

  • Hi Manuel,

    I have initialized the timer using timer_1_init() within which Timer_open is called.

    I expected the timer_1 to generate an interrupt after 3 ms(defined in TIMESTAMP_START_TX macro) but that doesn't happen.

    The following snippet was used to verify if the timer count is properly set. Not able to understand it based on values printed: t1[0],t1[1] and t1[2].

    Kindly review and let me know if I am missing something.

    One more thing that is puzzling me is that the pre-condition for timer_setperiod recommends to use timer_stop before calling the setperiod API. This seems to be contradictory to what is described under "Timer_ONESHOT_CALLBACK " that calling timer_stop before the timer interrupt will prevent the specified callback from ever being invoked. Let me know if I misunderstood it.

    #define TIMESTAMP_START_TX 3000
    
    timer_1_count[0] = Timer_getCount(timer_1_handle);
    uart_printf("t1[0] %d\r\n",timer_1_count[0]);
    Timer_stop(timer_1_handle); // Karts[13-09-2023]: use this when timer setperiod is used
    timer_1_count[1] = Timer_getCount(timer_1_handle);
    uart_printf("t1[1] %d\r\n",timer_1_count[1]);
    timer_1_status = Timer_setPeriod(timer_1_handle,Timer_PERIOD_US,TIMESTAMP_START_TX);
    if(timer_1_status == 0)
    {
        Timer_start(timer_1_handle);
        timer_1_count[2] = Timer_getCount(timer_1_handle);
        uart_printf("t1[2] %d\r\n",timer_1_count[2]);
        while(1);
    }
                
                
    Result:
    t1[0] 4935
    t1[1] 58317
    t1[2] 58461

    Thanks

    Karthik

  • Hello Karthik,

    can you please share the initial period that you initialize the timer before line 3? 
    This will help me understand the output that you are getting.

    The timer either needs to reach its end and trigger the callback or be stopped before that in order for the period to be reset.

    Can you try to test the following example code and see if this works:

    Timer_Params_init(&params);
        params.period        = 1000000;
        params.periodUnits   = Timer_PERIOD_US;
        params.timerMode     = Timer_ONESHOT_CALLBACK;
        params.timerCallback = timerCallback;
    
        timer0 = Timer_open(CONFIG_TIMER_0, &params);
    
        if (timer0 == NULL)
        {
            /* Failed to initialized timer */
            while (1) {}
        }
    
        if (Timer_start(timer0) == Timer_STATUS_ERROR)
        {
            /* Failed to start timer */
            while (1) {}
        }
    
        while(gwaitForCallback == 0)
        {
            // do nothing
        }
    
        Timer_setPeriod(timer0, Timer_PERIOD_US, 2000000);
    
        if (Timer_start(timer0) == Timer_STATUS_ERROR)
        {
          /* Failed to start timer */
          while (1) {}
        }
    
        Timer_stop(timer0); //cancelling after starting
    
        //CHECK THAT CALLBACK HAS NOT BEEN CALLED
        //If you comment out the timer stop, the callback will be called twice
    
    
        return (NULL);
    }
    
    void timerCallback(Timer_Handle myHandle, int_fast16_t status)
    {
        if (status == Timer_STATUS_SUCCESS)
        {
            GPIO_toggle(CONFIG_GPIO_LED_0); //optional GPIO toggle
            gwaitForCallback++;
        }
    
    }

    Best regards
    Manuel

  • Hi Manual, the initial period is 65534 microseconds for which interrupt may not have been generated yet.

     In the snippet I shared, I did stop the timer before setting it with a new period value(3000 microseconds which is less than that of initial value).

    Just to update you, I also tried in Timer_CONTINUOUS_CALLBACK mode . Didn't work.

    Tried the code.The code is stuck at "failed to initialize timer".

    Thanks

    Karthik

  • Hello Karthik,

    do you still have the timer configured as 16-bit? Can you try to run the program again with the respective timer configured as the standard 32-bit mode.

    Did you already try the "timerled" example included in the SDK? This is also using the Timer_CONTINUOUS_CALLBACK mode and should work out of the box.

    Regards
    Manuel

  • Hi Manuel,

    Timer type is 16 bits.

    Tried the example. It seem to work.First the LED toggles every 1 second. Then it switches to toggling every 5 seconds.

    Here is the code:

    void *mainThread(void *arg0)
    {
        Timer_Handle timer0;
        Timer_Params params;

        /* Call driver init functions */
        GPIO_init();
        Timer_init();

        /* Configure the LED pin */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

        /* Turn off user LED */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_OFF);

        /*
         * Setting up the timer in continuous callback mode that calls the callback
         * function every 1,000,000 microseconds, or 1 second.
         */
        Timer_Params_init(&params);
        params.period        = 1000000;
        params.periodUnits   = Timer_PERIOD_US;
        params.timerMode     = Timer_CONTINUOUS_CALLBACK;
        params.timerCallback = timerCallback;

        timer0 = Timer_open(CONFIG_TIMER_0, &params);

        if (timer0 == NULL)
        {
            /* Failed to initialized timer */
            while (1) {}
        }

        if (Timer_start(timer0) == Timer_STATUS_ERROR)
        {
            /* Failed to start timer */
            while (1) {}
        }

        while(1)
        {
            if(timer_0_flag == 1)
            {
                timer_0_flag = 0;
                timer_0_count++;
            }

            if(timer_0_count == 10)
            {
                Timer_stop(timer0);
                timer_0_count = 0;
                timer_0_flag = 0;
                Timer_setPeriod(timer0,Timer_PERIOD_US,5000000);
                if (Timer_start(timer0) == Timer_STATUS_ERROR)
                {
                    /* Failed to start timer */
                    while (1) {}
                }
            }
        }

        return (NULL);
    }

    /*
     * This callback is called every 1,000,000 microseconds, or 1 second. Because
     * the LED is toggled each time this function is called, the LED will blink at
     * a rate of once every 2 seconds.
     */
    void timerCallback(Timer_Handle myHandle, int_fast16_t status)
    {
        timer_0_flag = 1;
        GPIO_toggle(CONFIG_GPIO_LED_0);
    }

    The context to my issues is that I am using two timer instances. Will have to try that scenario over this example.Could you please confirm if Timer_init() should be called only once even when using multiple timer instances? Because, I had that function called in two sub routines while initializing timer0 and timer1.

    For reference, I had copied the timer_1_init() routine in this thread above. Similarily, timer_0_init routine also was written.

    On a side note, whenever I pause the debug session, the control goes to an unknown state(snapshot below). Is this expected? How do I know if the control stopped in a valid location?

  • Hello Karthik,

    Timer_init() only has to be called once before any timer is opened.
    But Timer_open() has to be called for both timer instances with the desired parameters.

    The debug issue you are seeing here is probably due to the being in sleep mode during the 1 or 5s long counting periods (see the PowerCC26xx_standbyPolicy()). Therefore stopping the debug during sleep will result in this state.

    Regards
    Manuel

  • Hi Manuel,

    I think I managed to replicate the issue.

    Please see the snapshot. The timer 1 counter is stuck at 1. Ideally, it should have given a number higher than that of timer 0 count.

    Also attached the source code ( timer 0 in one shot mode and timer 1 in continuous mode).

    Initially, timer 1 is configured to 65 ms and timer 0 to 10 ms.Subsequently, timer 1 is configured to 3ms.

    It is expected that timer 1 counter increments three times than that of timer 0. But, the count is stuck at 1.

    Kindly review and let me know if I am missing anything.

    timerled.zip

    Thanks

    Karthik

  • Hello Karthik,

    I have tested your code and encountered the same issues.
    There seems to be a bug in the drivers and the count register is not reset when a new load value is set. This is why when restarting the timer, it will overflow eventually and restart. 

    For now you will have to reset the counter value registers manually on a register level.
    Please use the following commands for that:

    Timer_stop();
    Timer_setPeriod();
    
    HWREG(0xTAV_Address) = 0xFFFFFFFF;
    HWREG(0xTBV_Address) = 0xFFFFFFFF;
    
    Timer_start();

    For "TAV_Address" and "TBV_Address" please look at the register view in CCS and look for your respective timer used (GPTx) and find the address of the TAV/TBV register for this GPTx.

    Hope this will solve the issue on your side.

    Regards
    Manuel

  • Hi Manuel,

    Tried but doesn't seem to work. The timer 1 counter doesn't increment.

    Could you review and confirm if the HW addresses(timer 1 which corresponds to GPT1) are correct?

    Update:

    I did code execution pause and run multiple times and then left the execution to pause.

    After some time, resumed execution. Interestingly, the timer 1 counter incremented.

    I did not understand this behavior. What should I do next?

    Thanks

    Karthik

  • Hello Karthik,

    the timer incrementing after the pause probably has something to do with the timer overflowing and then restarting. I have observed similar behaviour.

    I need to understand better what you are trying to do.
    As far as I see you want both timers to run independently but start timer 1 with an interval of 65ms which is never completed but is reconfigured to 3ms after counter 0 counts to 0 for the first time.
    Is that correct?

    If you want both timers to run continuously, then you should configure them as CONTINOUS_CALLBACK and add:

    while(timer_0_flag == 0)
                {
    
                }

    before the reconfiguring of timer 1. That way it is only done once timer 0 has reach 0 one time.
    You will need to remove the while loop around the reconfiguring part.

    Can you tell me if this is what you intend to do and if the solution works?

    Regards
    Manuel

  • Hi Manuel,

    I wanted timer 0 to run for 10ms duration in one shot mode. Leave it aside.

    I want timer 1 to be configured and re-configured throughout the application.

    For example(and in the sample that I sent), I had initialized timer 1 to 65 ms and the before this time is elapsed there is a need for me to reconfigure it to 3ms and timeout.

    As suggested HW address was written to reset the counter(assigned 0xFFFFFFFF). Yet, the timer doesn't seem to start immediately. Why should it overflow and then start? What the point in writing TAV and TBV registers then? There could be another bug in the driver?

    I am open to connect directly with you if it is ok with you to quickly sort this out.

    I am already delayed with this and I would appreciate a quick response to close this thread.

    Thanks

    Karthik

  • Hello Karthik, 

    I have now adapted my code exactly like you.
    Timer 0 as ONESHOT_CALLBACK, Timer 1 as CONTINOUS_CALLBACK with GPT1 as the Timer peripheral.

    When I run the following code (which is just adapted from the code that you sent), everything works as desired:

    /*
     * Copyright (c) 2016-2020, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== timerled.c ========
     */
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(inc/hw_gpt.h)
    #include DeviceFamily_constructPath(driverlib/timer.h)
    
    #include <stddef.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/Timer.h>
    
    /* Board Header file */
    #include "ti_drivers_config.h"
    
    /* Callback used for toggling the LED. */
    void timerCallback(Timer_Handle myHandle, int_fast16_t status);
    void timer1Callback(Timer_Handle myHandle, int_fast16_t status);
    
    volatile uint8_t timer_0_flag = 0;
    uint32_t timer_0_count = 0;
    
    volatile uint8_t timer_1_flag = 0;
    uint32_t timer_1_count = 0;
    int32_t timer1_status = 0;
    int32_t timer0_status = 0;
    
    Timer_Handle timer0,timer1;
    Timer_Params params,params1;
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        uint32_t i =0;
    
        /* Call driver init functions */
        GPIO_init();
        Timer_init();
    
        /* Configure the LED pin */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        //GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        /* Turn off user LED */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_OFF);
        //GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_OFF);
    
    
        /*
         * Setting up the timer in continuous callback mode that calls the callback
         * function every 1,000,000 microseconds, or 1 second.
         */
        Timer_Params_init(&params);
        params.period        = 10000;
        params.periodUnits   = Timer_PERIOD_US;
        params.timerMode     = Timer_ONESHOT_CALLBACK; //Timer_CONTINUOUS_CALLBACK;
        params.timerCallback = timerCallback;
    
        Timer_Params_init(&params1);
        params1.period        = 65000;
        params1.periodUnits   = Timer_PERIOD_US;
        params1.timerMode     = Timer_CONTINUOUS_CALLBACK;
        params1.timerCallback = timer1Callback;
    
        timer0 = Timer_open(CONFIG_TIMER_0, &params);
    
    
        if (timer0 == NULL)
        {
            /* Failed to initialized timer */
            while (1) {}
        }
    
        timer1 = Timer_open(CONFIG_TIMER_1, &params1);
    
        if (timer1 == NULL)
        {
            /* Failed to initialized timer */
            while (1) {}
        }
    
    
        if (Timer_start(timer1) == Timer_STATUS_ERROR)
        {
            /* Failed to start timer */
            while (1) {}
        }
    
        if (Timer_start(timer0) == Timer_STATUS_ERROR)
        {
            /* Failed to start timer */
            while (1) {}
        }
    
    
    #if 0
        Timer_stop(timer1);
        timer_1_count = 0;
        timer_1_flag = 0;
        Timer_setPeriod(timer1,Timer_PERIOD_US,3000);
        if (Timer_start(timer1) == Timer_STATUS_ERROR)
        {
            /* Failed to start timer */
            while (1) {}
        }
    
    
        while(1)
        {
    
            if(timer_0_flag == 1)
            {
                Timer_stop(timer0);
                Timer_stop(timer1);
                while(1);
            }
        }
    #endif
    
    
    #if 1
                while(timer_0_flag == 0)
                {
    
                }
    
                Timer_stop(timer1);
                Timer_setPeriod(timer1,Timer_PERIOD_US,3000);
                HWREG(0x40011050) = 0xFFFFFFFF;
                HWREG(0x40011054) = 0xFFFFFFFF;
                timer1_status = Timer_start(timer1);
                if (timer1_status == Timer_STATUS_ERROR) {
                    //Timer_start() failed
                    //Display_printf("timer1 start error!\r\n");
                    while (1);
                }
    
    #if 1
            if(timer_1_flag ==1)
            {
                timer_1_flag = 0;
                //Timer_stop(timer_1_handle);
                //while(1);
            }
    #endif
    
    #endif
    
        while (1);
    
        return (NULL);
    }
    
    /*
     * This callback is called every 1,000,000 microseconds, or 1 second. Because
     * the LED is toggled each time this function is called, the LED will blink at
     * a rate of once every 2 seconds.
     */
    void timerCallback(Timer_Handle myHandle, int_fast16_t status)
    {
        timer_0_flag = 1;
        timer_0_count++;
        GPIO_toggle(CONFIG_GPIO_LED_0);
    
    }
    
    void timer1Callback(Timer_Handle myHandle, int_fast16_t status)
    {
        timer_1_flag = 1;
        timer_1_count++;
        //GPIO_toggle(CONFIG_GPIO_LED_1);
    }
    

    Can you please check on your side?

    Regards
    Manuel

  • Hi Manuel,

    I think you have assumed that timer 0 in one shot mode is used only once in the application. If so then it is not.

    I start the timer 0 again whenever its interrupt flag is set to execute some other event. While this is happening, I need to initiate some other action using timer1.

    I want to understand why should we wait for timer_0_flag to be set before re-configuring timer 1? The timers are independent objects(firmware point of view) with independent registers.

    I tried the logic you shared. It did not work.

    Please see the snapshot. The timer 0 flag is set. Yet, the timer_1_count remains 0.

    It only works after long pause and execution. Now see where the control is when I paused the code execution.

    What else is missing here?

    Thanks

    Karthik

  • Hello Karthik,

    the while loop to wait for the timer_0_flag was only used in this case to provide an example in which timer 1 is actually reconfigured when timer 0 reached the callback. Just like in the code snippet that you have sent me earlier this week.
    For your final application I would recommend using a semaphore instead of the while loop.

    timerled_example.zip

    I have now attached the whole project that I used, to make sure that the SysConfig settings are consistent.

    I am using Code Composer Studio 12.4.0.0007 with the SimpleLink_CC13xx_C26xx_SDK_7_10_01_24.
    Launchpad is a LP-CC1352P7-1.

    Please verify you are using the same versions, software and hardware as I do. 

    This is the exact code that I have tested and it works on my side as follows:

    Both timers are configured. I have checked with the register values that the correct interval is loaded in the reload register.
    Timer 0 call back and sets timer_0_flag to 1. This leads to the timer 1 reload value to be reconfigured, which can also be verified by the value in the GPT1_TAILR register.
    Then timer 1 counts in the desired interval of 3ms.

    Please assure this code works on your side as well.

  • Hi Manuel,

    Your project worked for me.

    SDK used: C:/ti/simplelink_cc13xx_cc26xx_sdk_7_10_00_98/source

    CCS version: 12.4.0.00007 

    It also worked in the example project. Difference being, timer 1 in example project was trying to use any GPTM0 instead of GPTM1( which was conflicting).

    Will go back to my actual application and try.

    Thanks

    Karthik