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.

CC26xx GPT Edge-Time Mode

Other Parts Discussed in Thread: CC2640, SYSBIOS

Hello -

   I would like to measure timing on rising edges of an cc2640 input signal which may span more than one split-timer maximum measurement period (691ms w/prescaler extension). I've currently set up GPT0 Timer_A in edge-time mode, and it is triggering and capturing correctly.  However, I'm stuck on the best way to detect and handle the rollover of GPT0 Timer_A.  Once in edge-time mode, the periodic timeout and match interrupts don't fire. I'd think that I would prefer to have the timeout event (which doesn't seem to happen in edge-time mode) trigger GPT0 Timer_B in daisy-chain mode, with Timer_B in edge-count mode. This way Timer_B would simply count the rollover events for me.  The reference manual offers this small tidbit of advice:

  "If there is a possibility the edge could take longer than the count, another timer can be used to ensure detection of the missed edge."

But, does not give more information on the best way to do it. Perhaps I could synchronize Timer_B with Timer_A, and put Timer_B in periodic mode, but then I'm handling two interrupt calls with potential collisions of edge events on Timer_A and timeout events on Timer_B...

What's the best way to get this done?

Thanks!

  • Hi,

    Are you using TI-RTOS?

    Steve

  • Yes, forgot to mention that. I am using the current release of TI-RTOS. Thanks!
  • Hi Arthur, would you mind posting the code for timerA in edge time mode? I've been struggling getting it to work correctly.
    thanks!
  • Sure, but it is not a simple cut & paste though. It will take me a little time to hunt it down and extract it. I will try to work on it soon.
  • This should be most of it...

    // These are some additional includes for the timer routines:
    #include <inc/hw_ints.h>
    #include <ti/sysbios/family/arm/m3/Hwi.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    #include <driverlib/timer.h>
    #include <driverlib/aux_tdc.h>
    #include <driverlib/ioc.h>
    #include <driverlib/aon_ioc.h>



    // ----------------- I/O interrupt service routines --------------------------

    static void GPT0_A_Isr(UArg arg) {

    TimerIntClear(GPT0_BASE, TIMER_CAPA_EVENT);
    TimerIntClear(GPT0_BASE, TIMER_TIMA_TIMEOUT);

    // handle my interrupt event here
    Timer0Cnt++; // do some stuff

    } //--- end GPT0_A_isr

    static void GPT0_B_Isr(UArg arg) {

    TimerIntClear(GPT0_BASE, TIMER_CAPB_EVENT);
    TimerIntClear(GPT0_BASE, TIMER_TIMB_TIMEOUT);

    // handle my interrupt event here
    Timer0Cnt++; // do some stuff

    } //--- end GPT0_B_isr

    // ------------------------------ Timer init & close functions ----------------------------
    void initTimers(void)
    {
    // setup the input pins before calling this.
     
    Power_setDependency(PERIPH_GPT0); // Turn on PERIPH power domain and clock for GPT0
    Power_setConstraint(Power_SB_DISALLOW); // while the timer is running, we can't power down the perph domain.

    // Route Board_COUNTER_IN to IO event port 0 (0 = Timer0A, 1 = Timer0B, 2 = Timer1A.., I think)
    while (hAfePins == NULL){}; // wait here for pins to be assigned, it is being done by another task thread.
    PINCC26XX_setMux(hAfePins, PIN_ID(Board_COUNTER_IN), IOC_PORT_MCU_PORT_EVENT0);

    // Reset the timer registers - probably not needed for production, but seems to help with debug
    HWREG(GPT0_BASE + GPT_O_CTL) = 0;
    HWREG(GPT0_BASE + GPT_O_TAMR) = 0;
    HWREG(GPT0_BASE + GPT_O_TAPR) = 0;
    HWREG(GPT0_BASE + GPT_O_TBPR) = 0;

    TimerPrescaleSet(GPT0_BASE, TIMER_A, 255);
    TimerPrescaleSet(GPT0_BASE, TIMER_B, 255);

    TimerConfigure(GPT0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_B_PERIODIC_UP);

    TimerWaitOnTriggerControl(GPT0_BASE, TIMER_A, FALSE);
    TimerWaitOnTriggerControl(GPT0_BASE, TIMER_B, FALSE);

    TimerStallControl(GPT0_BASE, TIMER_BOTH, TRUE); // halt on debug.

    // Setup HWI handler
    //Hwi_Params_init(&hwiParams);

    if (Hwi_create(INT_TIMER0A, GPT0_A_Isr, NULL, NULL) == NULL) {
    System_abort("Can't create Hwi A"); }

    if (Hwi_create(INT_TIMER0B, GPT0_B_Isr, NULL, NULL) == NULL) {
    System_abort("Can't create Hwi B"); }

    TimerIntClear(GPT0_BASE, TIMER_TIMA_TIMEOUT);
    TimerIntClear(GPT0_BASE, TIMER_CAPA_EVENT);
    TimerIntClear(GPT0_BASE, TIMER_TIMB_TIMEOUT);

    TimerIntEnable(GPT0_BASE, TIMER_CAPA_EVENT | TIMER_TIMB_TIMEOUT);

    TimerEnable(GPT0_BASE, TIMER_BOTH); // Timer Enable
    } //--- end of initTimers

    void closeTimers(void)
    {
    TimerIntDisable(GPT0_BASE, TIMER_CAPA_EVENT | TIMER_TIMB_TIMEOUT);

    TimerDisable(GPT0_BASE, TIMER_A); // Timer disable
    TimerDisable(GPT0_BASE, TIMER_B); // Timer disable
    Power_releaseDependency(PERIPH_GPT0); // Turn on PERIPH power domain and clock for GPT0
    Power_releaseConstraint(Power_SB_DISALLOW); // while the timer is running, we can't power down the perph domain.
    } //--- closeTimers

  • Thanks so much Arthur!

  • edit:nevermind

  • Arthur, I see that you haven't received any further replies. Is this question still pending? If so, perhaps we should move this thread over to the device forum...
  • Arthur I do have one possible solution to the problem. Keep timer0A in edgetime mode and setup an additional 32bit timer1A . Configure the GPT timer0A's interrupts so that on edge capture event a DMA transfer is initiated from GPT Timer1a's TAR register to a memory location. I setup the DMA in single request, basic mode. This means that after each transfer, the DMA must be re-enabled. In order to do this, the dma done interrupt is returned to TIMER0A, thus we will enter timer0A's ISR after each DMA done transfer, at which point we can re-enable DMA for the next edge capture.

    Obviously, I've glossed over a lot of the fine details, so if you are having trouble getting this working I can put together some code as you did for me.
    I think this should be the smallest delay way to capture an edge without having to deal with the annoyance of the standard edge timer overflowing all the dang time!

    regards,
    CM