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.

CC2652PSIP: Timer Edge Capture for Counting

Part Number: CC2652PSIP
Other Parts Discussed in Thread: SYSBIOS

Tool/software:

Hi, 

I am attempting to use the a GPTIMER in GPT_MODE_EDGE_TIME.  Do you know what the max frequency acceptable is?  Currently, if I use an input signal of more than 100kHz and call Task_sleep in tirtos or vTaskDelay in FreeRTOS, the program wills stop executing.  Any example code would be great.

  • Hi Chris,

    The GP Timer source frequency is sourced on the main high-frequency clock frequency, or 48 MHz, so I would expect edge detection to be accurate at least up to 12 MHz (I'm leaving some room for error).  However you must make sure that the device is not entering low-power standby mode as this will disable the main clock and thus the GP Timer's edge detection ability.

    Regards,
    Ryan

  • Is there example code that does this?  

  • There is no direct example in the SimpleLink F2 SDK, however the GPTimerCC26XX.h File Reference does describe the necessary GPTimerCC26XX_setCaptureEdge and GPTimerCC26XX_getValue APIs.  You can also refer to the lower-level Timer.h driverlib documentation.

    Regtards,
    Ryan

  • Hi,

    I am still unable to get the performance out of the timer that I need.  

    This is my init code.  If I capture pulses at a frequency greater than 100kHz, the program will not execute past Task_sleep


    * ======== timerled.c ========
    */

    #include <stddef.h>

    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/Timer.h>

    /* Board Header file */
    #include "ti_drivers_config.h"

    /* TEST */
    #include <ioc.h>
    #include <ti/drivers/timer/GPTimerCC26XX.h>
    #include <ti/sysbios/knl/Task.h>
    void init_counter(void);
    /* Callback used for toggling the LED. */
    void timerCallback(Timer_Handle myHandle, int_fast16_t status);


    volatile uint32_t pulse_count = 0;
    volatile uint32_t wrong_interrupt = 0;
    GPTimerCC26XX_Handle hTimer;
    void timerCallback2(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
    // Critical section
    if (interruptMask & GPT_INT_CAPTURE){
    pulse_count++;
    } else {
    wrong_interrupt ++;
    }

    }
    /*
    * ======== mainThread ========
    */
    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) {}
    }
    init_counter();
    while(1){
    GPTimerCC26XX_enableInterrupt(hTimer, GPT_INT_CAPTURE);
    Task_sleep(10000);
    GPTimerCC26XX_disableInterrupt(hTimer, GPT_INT_CAPTURE);
    pulse_count = 0;
    Task_sleep(10000);

    }
    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)
    {
    GPIO_toggle(CONFIG_GPIO_LED_0);
    }

    GPTimerCC26XX_Handle hTimer;

    void init_counter(void) {
    // Route GPIO to the timer's capture event
    IOCPortConfigureSet(IOID_2,
    IOC_PORT_MCU_PORT_EVENT1,
    IOC_IOMODE_NORMAL | IOC_FALLING_EDGE | IOC_INPUT_ENABLE);

    // Set up timer parameters
    GPTimerCC26XX_Params params;
    GPTimerCC26XX_Params_init(&params);
    params.width = GPT_CONFIG_16BIT;
    params.mode = GPT_MODE_EDGE_TIME;
    params.direction = GPTimerCC26XX_DIRECTION_UP;
    params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;

    // Open timer
    hTimer = GPTimerCC26XX_open(COUNTER_GPTIMER, &params);
    if (hTimer == NULL) {
    while (1); // Error handling if timer cannot be opened
    }
    // Set capture edge to rising edge
    GPTimerCC26XX_setCaptureEdge(hTimer, GPTimerCC26XX_NEG_EDGE);

    // Register and enable interrupt
    GPTimerCC26XX_registerInterrupt(hTimer, timerCallback2, GPT_INT_CAPTURE);

    // Start the timer
    GPTimerCC26XX_start(hTimer);
    GPTimerCC26XX_enableInterrupt(hTimer, GPT_INT_CAPTURE);
    }

  • IOC_PORT_MCU_PORT_EVENT0 is used instead of IOC_PORT_MCU_PORT_EVENT1

  • Keep in mind:

    • Repetitive fast hardware interrupts may overlap if not serviced in time.  They are best not to have if they will be called within microseconds.
    • The timer edge capture mode is 16-bit, thus any values over 0xFFFF will overflow back to zero.  The timer value needs to be checked every couple of milliseconds if the incoming signal is exceptionally frequent.

    #include <stddef.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/Timer.h>
    
    /* Board Header file */
    #include "ti_drivers_config.h"
    
    /* TEST */
    #include <ti/devices/cc13x2_cc26x2/driverlib/ioc.h>
    #include <ti/drivers/timer/GPTimerCC26XX.h>
    #include <ti/sysbios/knl/Task.h>
    void init_counter(void);
    /* Callback used for toggling the LED. */
    void timerCallback(Timer_Handle myHandle, int_fast16_t status);
    
    volatile uint32_t pulse_count = 0;
    volatile uint32_t previous_count = 0;
    volatile uint32_t wrong_interrupt = 0;
    GPTimerCC26XX_Handle hTimer;
    //void timerCallback2(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
    //// Critical section
    //    if (interruptMask & GPT_INT_CAPTURE){
    //        pulse_count++;
    //    }
    //    else {
    //        wrong_interrupt ++;
    //    }
    //}
    
    /*
    * ======== mainThread ========
    */
    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_FREE_RUNNING;
    //    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) {}
        }
        init_counter();
        while(1){
    //        GPTimerCC26XX_enableInterrupt(hTimer, GPT_INT_CAPTURE);
            previous_count = GPTimerCC26XX_getValue(hTimer);
            Task_sleep(5000);
    //        GPTimerCC26XX_disableInterrupt(hTimer, GPT_INT_CAPTURE);
    //        pulse_count = 0;
            pulse_count = GPTimerCC26XX_getValue(hTimer);
            if(previous_count > pulse_count)
            {
                pulse_count += (uint16_t)(0xFFFFF - previous_count);
            }
            else
            {
                pulse_count -= previous_count;
            }
            GPIO_toggle(CONFIG_GPIO_LED_0);
    //        Task_sleep(10000);
    
        }
        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)
    {
        GPIO_toggle(CONFIG_GPIO_LED_0);
    }
    
    GPTimerCC26XX_Handle hTimer;
    
    void init_counter(void) {
        // Route GPIO to the timer's capture event
        IOCPortConfigureSet(26,
        IOC_PORT_MCU_PORT_EVENT0,
        IOC_IOMODE_NORMAL | IOC_FALLING_EDGE | IOC_INPUT_ENABLE);
    
        // Set up timer parameters
        GPTimerCC26XX_Params params;
        GPTimerCC26XX_Params_init(&params);
        params.width = GPT_CONFIG_16BIT;
        params.mode = GPT_MODE_EDGE_TIME;
        params.direction = GPTimerCC26XX_DIRECTION_UP;
        params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
    
        // Open timer
        hTimer = GPTimerCC26XX_open(COUNTER_GPTIMER, &params);
        if (hTimer == NULL) {
        while (1); // Error handling if timer cannot be opened
        }
        // Set capture edge to rising edge
        GPTimerCC26XX_setCaptureEdge(hTimer, GPTimerCC26XX_NEG_EDGE);
    
        // Register and enable interrupt
    //    GPTimerCC26XX_registerInterrupt(hTimer, timerCallback2, GPT_INT_CAPTURE);
    
        // Start the timer
        GPTimerCC26XX_start(hTimer);
    //    GPTimerCC26XX_enableInterrupt(hTimer, GPT_INT_CAPTURE);
    }
    

    I'm having improved results with the above code.

    Regards,
    Ryan