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.

using CC2650 GPT for high speed timer edge capture with RTOS

Other Parts Discussed in Thread: CC2640, CC2650

I need to precisely measure the time elapsed between falling edges on two gpio pins.  I'm not sure of the best way to do this.  I've been looking into using one of the four GPT in the M3 core to do this.

I'm familiar with the M3 and driverlib, but this is my first time using the RTOS.  Are there any references out there for something like this?  Is the GPT the best way to accomplish this?

I'm using the BLEPeripheral example on the CC2650 dev kit.  In the end application i plan to use the CC2640.

  • I found this thread which seems similar to what i need: e2e.ti.com/.../398961

    It's still unclear what I need to do to configure the timer to start on a GPIO falling edge then stop on a different GPIO falling edge.
  • Jeff,

    The kernel’s Timer module support (described in that other thread) for the four GPTs provides basic periodic and one-shot timing services, with the timer ticking off of a clock signal.  There is no direct support for setting up match and triggering for more specialized purposes.  You can still use a GPT for this, but you’ll need to manage this timer on your own, and write to the timer registers directly.  

    There is GPT timer support for these timers in driverlib (see timer.h).  (Sorry, I haven’t found any similar examples to point you to.)  If you want to use an interrupt to detect completion, you should use the kernel’s “Hwi” module to create an interrupt handler, to call your ISR function.  If you will be triggering another thread to run from the ISR (for example a task), then you’ll need to make this a “dispatched” interrupt (the default, most common type used), which provides scheduler protection, to hold off the new thread until the interrupt has unwound.  If you don’t need to post another thread to run from your ISR, you can use the Hwi_plug() API to create a simple, non-dispatched interrupt.

    Hope this helps …

    Regards,
    Scott

  • Thanks for the reply scott.
    Being new to the RTOS, i wasn't sure if i could make the driverlib calls directly. I read this in another thread:
    "Also, you may want to use the Timer module from TI-RTOS rather than the timer routines in driverlib. It will avoid possible collisions for usage of timer peripherals, and the timer Hwi will be created automatically for you."
    If the timer is dedicated to timing GPIO edges, does the possible collision scenario still apply to me?
  • Jeff,

    It is a very good concern, but yes, you can use the driverlib calls directly.  In this case you’ll need to, to get the functionality you want from the GPT.

    Yes it is possible that there might be collisions if your application is using a GPT for other purposes too.  On CC26xx the kernel’s Clock module uses the RTC underneath (which stays alive across power saving modes).  And if Timestamping is used in your app, the M3’s SYSTICK timer will be used for that.  So it would only be the case if your application is explicitly creating a kernel managed Timer for other purposes that there will be a collision.  And there is a way to manage this, because as kernel Timers are created (either statically in the application configuration, or dynamically at runtime), there is an “ID” parameter that can be used to select a specific timer peripheral.  The “ID” can be specified as “-1” and any available timer will be used, but if you specify the timer index 0-3 instead, the specific timer you specify will be used.  So if your application is using kernel Timers for GPTs, you just need to be sure when you create them to avoid the GPT you’re using for GPIO measurements.

    One other thing that you’ll probably need to consider is if you are using the provided power management framework in your application.  In the lowest possible sleep state (STANDBY) the GPT registers will lose context.  So, if you want to hold off a power transition during your measurement, you’ll need to declare a “constraint” while your measurement is in progress and you're waiting for an interrupt, to prohibit a transition to STANDBY until your measurement is complete, and you then release the constraint.  Also, if you want to repeat a measurement you’ll need to re-initialize the GPT registers after wakeup from STANDBY.  There are callback notification mechanisms in the power framework to notify drivers of these transitions, and allow them to cooperate with the framework.  There is some overview in “Power_Management_CC26xx.pdf” in the docs directory of the TI-RTOS installation.  I don’t know if this is a concern for your use case or not, but wanted to give you heads up…

    Regards,
    Scott

  • Thanks for the advice. So I'm able to get the timer interrupts. I started with just a periodic timer. Here's my code. I call TimerSetup from main before Bios_start().
    void Timer0Isr(){ TimerIntClear(GPT0_BASE, TIMER_TIMA_TIMEOUT);
    ulTimer0IntCnt++;}void TimerSetup(){ PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
    PRCMLoadSet();
    //PRCMPeripheralRunDisable(PRCM_PERIPH_TIMER0); // Disables a peripheral Timer
    //PRCMLoadSet();
    PRCMPeripheralRunEnable(PRCM_PERIPH_TIMER0); // Enables a peripheral Timer
    PRCMLoadSet(); TimerDisable(GPT0_BASE, TIMER_BOTH); // Timer disable
    // SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER2); // Timer Enable
    TimerConfigure(GPT0_BASE, TIMER_CFG_PERIODIC);
    //TimerPrescaleSet(GPT0_BASE, TIMER_BOTH, 47);
    TimerLoadSet(GPT0_BASE, TIMER_A, 48000000);/*
    hwi = Hwi_create(INT_TIMER0A, hwi0_isr, NULL, &Error); if (hwi == NULL) {
    System_abort("Can't create Hwi"); }*/
    //TimerIntRegister(GPT0_BASE, TIMER_A, Timer0Isr);
    TimerIntClear(GPT0_BASE, TIMER_TIMA_TIMEOUT);
    TimerIntEnable(GPT0_BASE, TIMER_TIMA_TIMEOUT); // Enables individual timer interrupt sources.
    //IntEnable(); // Timer Interrupt Enable ulTimer0IntCnt = 0;
    TimerEnable(GPT0_BASE, TIMER_A); // Timer Enable}
    here's the output from the cfg file:var m3Hwi0Params = new M3Hwi.Params();
    m3Hwi0Params.instance.name = "m3Hwi0";
    Program.global.m3Hwi0 = M3Hwi.create(31, "&Timer0Isr", m3Hwi0Params);
    I initialized the load value to a very large number (48000000). After the first interrupt i get repeated interrupts. It really seems like the isr flag is not getting cleared. Isn't that what TimerIntClear() should do?
    Do i have to do something else to clear the interrupt?
  • Jeff,

    Can you reformat and post the code again?  It got all smashed together.

    I've not used these particular driverlib API calls before, but I think that call to TimerIntClear() should do the trick.

    But it looks like you are creating the Hwi twice: first statically with ISR of "hwi0_isr", and then dynamically with ISR of "Timer0Isr"(?)  The Hwi should only be created once, and usually static creation is best.

    Which ISR is firing?

    If you set a breakpoint, and step thru the TImerIntClear() call, do GPT timer bits (in CCS register view) get cleared as expected?

    And with each step, do you see the timer count changing?  Does it change drastically, or in only small increments?  I'm wondering if maybe the timer is free running while you are halted in the debugger and actually triggering another interrupt. This happens on some devices, and i don't remember at the moment it this is the case with cc26xx.

    Thanks,
    Scott

  • Not sure what happened on that last post, but it was pretty crammed together.  Due to the formatting it was very hard to tell that the dynamic creation was commented out.  I started out that way then back tracked and used the GUI to config after your suggestion.

    It looks like you were correct about the timer continuing to run while the debugger was stopped.  In the ISR on my breakpoint I could refresh the register window and see the counter changing.  I set the "stall" bit for the time being so I don't get fooled again.

    Thanks so much for your help.