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.

RTOS/CC2640: Hardware Interrupts timestamping

Part Number: CC2640
Other Parts Discussed in Thread: CC2650STK

Tool/software: TI-RTOS

Background - trying to gather hardware interrupts pulses from IR sensor. I am receiving the correct number of pulses based on the IR host protocol, but the timings are off.

The data is based on pulse duration, something like: base pulse length + 90 Us * n where N is a number between 0-F (a nibble), so min accuracy I need is less then 90 Us.

Problem - The timestamps I seem to be getting are not accurate enough. I am collecting the timings by storing previous ticks - "Clock_getTicks",  then once i have collected enough pulses, i disable IR handler and notify main task to process, which when done processing, it will just re-enable the interrupt that particular data pin.

IR Handler sample:

void IR_Interrupt_Handler(void)
{

    uint32 tick_now = Clock_getTicks();

//store pulse:  tick_now - IR_data.last_activity_ticks ( I later mutiple these values by "Clock_tickPeriod" to make them in Us (microseconds).

if  (received required number of pulses)

{

//1. disable interrupt

//2. notify main task to process the data (which, when done, resets receive buffer and enables interrupts to kick the receiving of more IR data

}
    IR_data.last_activity_ticks = tick_now;  
}

Note: I tried disabling interrupt on this datapin inside the IR handler and then, re-enabling it at the end of it, which does not change my result, however when i do this it seems to lock up after some iterations, about 200-300 cycles pulses

is there a better way to timestamp hardware interrupts?

  • Hello,

    Have you considered using the GPTimer module to get a higher precision timestamp?

    Best wishes
  • Hi,

    Yes, thank you for suggestion. I had found some examples and started looking into GTP Timer. this is very useful example:

    e2e.ti.com/.../436309 

    I can get the interrupts to come in, but when i measure the timer ticks, i am getting very high numbers, not nearly close to what they are supposed to be.

    I am reading the ticks as such:

    tick_now = TimerValueGet(GPT0_BASE,TIMER_A);

    when I try:

    tick_now = HWREG(GPT0_BASE + GPT_O_TAPR); - i get zero everytime,

    Thanks for your help in advance!

  • Hi,

    I would appreciate some more input to ensure I am on the right path in resolving this.

    I have gone ahead and implemented edge detection using GPT 0, using other forum threads and a lot of research.
    I am receiving the interrupts and the handler is getting called, but the issue is that the time stamps are still not accurate enough. It has been way too long than anticipated trying to achieve something very simple with TI CX2640 BLE chip. BTW, I am using BLE stack 2.2.1.
    Can someone confirm or advise how to proceed to make sure we are getting accurate timestamps with GPT0.
    Theoretically, GPT0 is a 48MHz timer, so its ticks should be 1/48 of microsecond – this logic is the base if my calculations.
    Something else to double check, I am using a prescale of 255 which in this mode (edge capture) just extends the timer range by more 8 bits (16-23), making it a 24 bit timer – this is why I am reading the value such:
    (uint32_t) ( (HWREG(GPT0_BASE + GPT_O_TAPR) & 0x000000FF) << 16) + HWREG(GPT0_BASE + GPT_O_TAR);
    Without prescale the timer resets away too frequently and makes it harder to keep track of the duration between interrupts.
    Here is the code:
    Timer setup:
    //----------------------------------------------------------------------------
    //----------------------------------------------------------------------------

    hIrDataPin = PIN_open(&pinIrDataState, IrPinTable);

    //turn on power to periphs
    PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
    Power_setDependency(PowerCC26XX_PERIPH_GPT0);
    PRCMLoadSet();
    PRCMPeripheralRunEnable(PRCM_PERIPH_TIMER0);
    PRCMLoadSet();

    PINCC26XX_setMux(hIrDataPin,XPERT_PIN_IR_DATA,IOC_PORT_MCU_PORT_EVENT0);

    //clear timer regs
    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;
    HWREG(GPT0_BASE + GPT_O_TBMR) = 0;
    HWREG(GPT0_BASE + GPT_O_CFG) = 0x00000004; //timers in 16bit mode

    TimerConfigure(GPT0_BASE,TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP);
    TimerPrescaleSet(GPT0_BASE, TIMER_A, 255);
    TimerEventControl(GPT0_BASE,TIMER_A,TIMER_EVENT_POS_EDGE | TIMER_EVENT_NEG_EDGE);
    TimerIntClear(GPT0_BASE,TIMER_CAPA_EVENT);
    TimerIntEnable(GPT0_BASE,TIMER_CAPA_EVENT);
    TimerIntRegister(GPT0_BASE, TIMER_A, GPT0_A_Isr);
    TimerEnable(GPT0_BASE,TIMER_A);
    //----------------------------------------------------------------------------
    //----------------------------------------------------------------------------

    Interrupt Handler:
    void GPT0_A_Isr(UArg x)
    {
    TimerIntClear(GPT0_BASE,TIMER_CAPA_EVENT);
    uint32_t tick_now = (uint32_t) ( (HWREG(GPT0_BASE + GPT_O_TAPR) & 0x000000FF) << 16) + HWREG(GPT0_BASE + GPT_O_TAR);
    uint32_t pulse_duration;

    if (tick_now < last_activity_ticks)
    {
    //this does not seem to work as I get unexpected long pulses which I am suspecting is when the timer resets, but I have not been able to confirm.
    pulse_duration = (0x00FFFFFF - last_activity_ticks) + tick_now;
    }
    else
    {
    //and-ing with 0x00FFFFFF to make sure we don’t put anything mistakenly in the higher two nibbles
    pulse_duration = (tick_now - last_activity_ticks) & 0x00FFFFFF;
    }

    //store pulse = pulse_duration / 48
    //after X number of pulses are collected
    //disable interrupts
    //process pulses
    //reset pulses
    //enable interrupt

    //store last ticks
    last_activity_ticks = tick_now;
    }

    for reference, here is snapshot of what pulses are expected and what I am getting (expected/received)
    720/529
    885/561
    2070/537
    885/906
    1440/1446
    885/906
    1350/1354
    885/906
    810/737
    885/357
    900/709
    885/382
    1260/1079
    885/834
    1080/943

    I am expecting some degree of error, and there is clearly a resemblance in the pulse pattern, but the error margin I am seeing is not acceptable.

    Can anyone suggest what else can I try?
    At this point, I am not sure if there is an issue with the code or the maybe my hardware setup.
    I did tried two different IR sensors and the pulses I am receiving are very similar.

    Thanks,
    SS
  • UPDATE:

    after a lot of trial and error, i followed timer concept from sensortag_cc2650stk example, and now I am able to get accurate timestamps.
    for reference:

    Enable Timer:
    hIrDataPin = PIN_open(&pinIrDataState, IrPinTable);

    Power_setDependency(PowerCC26XX_PERIPH_GPT0);
    Power_setConstraint(PowerCC26XX_SB_DISALLOW);

    TimerConfigure(GPT0_BASE,TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP);

    PINCC26XX_setMux(hIrDataPin,XPERT_PIN_IR_DATA,IOC_PORT_MCU_PORT_EVENT0);

    TimerLoadSet(GPT0_BASE, TIMER_A, 0);
    TimerPrescaleSet(GPT0_BASE, TIMER_A, 0x000000FF);//255
    TimerEventControl(GPT0_BASE,TIMER_A,XPERT_GPT0_INTERRUPT_EDGE);
    TimerIntClear(GPT0_BASE,TIMER_CAPA_EVENT);
    TimerIntEnable(GPT0_BASE,TIMER_CAPA_EVENT);
    TimerIntRegister(GPT0_BASE, TIMER_A, IR_TimerInterrupt_Handler);
    TimerEnable(GPT0_BASE,TIMER_A);

    ISR HAndler:
    TimerIntClear(GPT0_BASE,TIMER_CAPA_EVENT);
    uint32_t tick_now = (uint32_t) ( (HWREG(GPT0_BASE + GPT_O_TAPR) & 0x000000FF) << 16) + HWREG(GPT0_BASE + GPT_O_TAR);

    Disable Timer when done:
    TimerDisable(GPT0_BASE,TIMER_A);

    if (hIrDataPin != NULL)
    {
    PINCC26XX_setMux(hIrDataPin, XPERT_PIN_IR_DATA, IOC_PORT_GPIO);

    PIN_close(hIrDataPin);
    hIrDataPin = NULL;
    }

    Power_releaseDependency(PowerCC26XX_PERIPH_GPT0);
    Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);

    I wish this was better documented, hope above is going to help others