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.

RTC Interrupt Miss for CC2650

Other Parts Discussed in Thread: SYSBIOS, CC2650

Hi All,

I am utilizing the channel 1 of RTC in my software besides the channel 0 which is used by SYSBIOS. Basically my software will set up RTC channel 1 comparison register, and the ISR function will post a semaphore when RTC interrupt happens. I have a task that is pending for that semaphore to run. 

After running for a few weeks or a month, I would notice a RTC interrupt miss which caused my task to stop running. I also set up a semaphore pend timeout value which is equal to 1ms + (RTC Channel 1 Future Interrupt Time - RTC Current Time). I was hopping the semaphore pend timeout would give a notice to the task that a RTC interrupt lost happened. Unfortunately the semaphore pend did not timeout either after RTC channel 1 interrupt was lost. When I attached to the CC2650, I can see RTC was running regularly and past the previous set RTC channel 1 compare value. 

In the software, UART is the only other HWI that is always enable. I am suspecting somehow UART operation causes RTC interrupt lost and semaphore pend timeout failed.

Any suggestion to debug this RTC interrupt miss problem?

Thanks,

Jianwei

 

  • I am reading the RTC section of CC26XX TRM. 

    "An event will be scheduled to occur as soon as possible when writing to CH1CMP provided that the channel is enabled, in compare mode and the new value matches any time between next RTC value and 1 second in the past."

    I am suspecting something is blocking the system for more than 1 second. That's why even the semaphore_pend does not return either 1ms after the RTC Channel 1 compare value. 

  • Jianwei,

    I'm looking into this and going to try to ask around to see if someone can think of a way you can debug this.

    Judah
  • The expert on this area has not yet responded to me but just thinking about your problem.

    Even if something prevent the ISR from executing right away, that does seem like it would cause a missed interrupt.
    Would it be a problem if two clock timeouts are triggered before the ISR is executed?

    I thinking we might need to know more about what is going on in your system. Is the ISR never getting triggered again?

    Judah
  • In our system, the pending task will set the timeout for the next RTC interrupt time after it return from the pend. So if it miss one interrupt or fail to return from the semaphore pend, the ISR will never be trigger again.  The other possible cause of this problem is the ISR is triggered and post the semaphore, but the semaphore pend failed to  response. I am suspecting this because the semaphore pend failed to time out when this problem occurred. Something in the semaphore might be corrupted. I will try to add some debug count for the semaphore value and the number of times semaphore post  andpend to verify my guess, but it just takes long time for this problem to occur. 

  • some ideas to debug,:

    - When this happens, check the app state in ROV to make sure there hasn’t been a stack overflow, corruption of some module state, etc.

    - And check the RTC registers in the debugger to see if there is a pending interrupt event that has not been serviced yet. For example, maybe interrupts are indefinitely disabled, that is why the RTC ISR is not firing?

    - When this happens, post a snapshot of the RTC register contents that can be viewed in the debugger.

    - Try to see if there is a specific time that this occurs. It might be at some time corresponding to a hardware or software counter rolling over somewhere.

    - If you don’t have it, add a check when setting the channel 1 compare threshold to make sure the time for next interrupt is not too soon. If it is, bump the count by 4 (corresponding to 61 microseconds), as is done in the timer module.

    - post the code you using to set the CH1 threshold. And show how you are setting the semaphore timeout on CH0 to correspond to the expected CH1 timeout, plus 1 msec.

    Judah
  • Judah,

    Below is the code to set RTC Channel 1 and related semaphore post/pend

    void  timeslot_cb(struct rtimer* rt_ptr, void* ptr)

    {

      Semaphore_post(timeslot_sem, NULL);

    }

    void timeslot_task(void)

    {

         ........

    while (1)

     {

       pend_status = Semaphore_pend(timeslot_sem,timeslot_timeout_cticks);

       ......

       /*slot_start is the future wakeup time, RTIMER_NOW() returns current RTC time

          #define RTIMER_SECOND 65536

         #define CLOCK_SECOND 100000   // 10 us clock tick */

        // Convert to ms first to avoid possible overflow 

        timeslot_timeout_ms = (uint32_t)((uint64_t)(slot_start - RTIMER_NOW())*1000)/RTIMER_SECOND;

       timeslot_timeout_cticks = (uint32_t)((uint64_t)(timeslot_timeout_ms*CLOCK_SECOND)/1000);

       // Add 1ms delay to timeout

       timeslot_timeout_cticks += CLOCK_SECOND/1000;

        /* This sets RTC channel 1 compare register and registers timeslot_cb as callback function. Eventually this will call  rtimer_arch_schedule() below */

        rtimer_set(&acm_rt, slot_start, 1, (void (*)(struct rtimer *, void *)) timeslot_cb, NULL);

    }

    void rtimer_arch_schedule(rtimer_clock_t t)

    {

       uint32_t key;

       key = Hwi_disable();

       HWREG(AON_RTC_BASE + AON_RTC_O_EVFLAGS) = AON_RTC_EVFLAGS_CH1;

       AONRTCChannelDisable( AON_RTC_CH1 );

       AONRTCCompareValueSet(AON_RTC_CH1, (rtimer_clock_t)(t));

       AONEventMcuWakeUpSet( AON_EVENT_MCU_WU1, AON_EVENT_RTC_CH1 );

       AONRTCChannelEnable( AON_RTC_CH1);

       //Combined event with RTC CH0.

       AONRTCCombinedEventConfig(AON_RTC_CH1|AON_RTC_CH0);

       AONRTCDelayConfig( AON_RTC_CONFIG_DELAY_NODELAY );

       AONRTCEnable();

       Hwi_restore(key);

    }

    This is normally the semaphore values from RTOS plugin (I am using IAR not CCS)

    Address       event  eventId  mode  count   pendedTask

    0x200009c8 none  n/a       counting 0         Label: timeslot_task_handle, priority: 4, pendState: Waiting for 63839 more ticks

    However, I found out the semaphore timeout value becomes a very large negative values (always)  after running for a few days. This might explain why the semaphore pend does not timeout when no semaphore is post. I checked the timeslot_timeout_cticks value above and seemed normal and no overflow.  At this point the system is still running fine because the RTC channel 1 interrupt is still fire as expected. 

    Address       event  eventId  mode  count   pendedTask

    0x200009c8 none  n/a       counting 0         Label: timeslot_task_handle, priority: 4, pendState: Waiting for -21474322328 more ticks

    I am wondering where the remaining ticks for semaphore pend is stored in the OS. I would like to check why it becomes negative value even though positive timeout value is passed to sempahore_pend as argument. 

  • I have one other task which is pending on UART interrupt

    Address        Label                Priority  Mode      fxn                    arg0             arg1              stackPeak   stackSize   stackBase    curCordId affinity   blockedOn

    0x200005dc HCT_TX_task  3            Blocked HCT_TX_task 0x00000000 0x00000000 656               756              0x20003308  n/a             n/a

    Task_sleep(-25769246446)

     

    Since the Task_sleep  value is a negative value again, it looks very similar to the semaphore pend issue I posted. Below is the related code

     

    void HCT_TX_task(UArg arg0, UArg arg1)

    {

    ......

    while (1)

    {

    //wait until a byte came

    while(1!=UART_read(HCT_Hnd->uart_hnd,(uint8_t*)msghdr,1));

    /* UART message processing*/

    .....

    }

    }

    Here is the UART setting. The UART is in blocking mode with a timeout of 1ms. Should I use a semaphore pend for the task and use callback for UART interrupt instead of blocking mode?

    Here is the UART setting

    UART_Params params;
    UART_Params_init(&params);
    params.baudRate = 115200;
    params.writeMode = UART_MODE_BLOCKING;
    params.readMode = UART_MODE_BLOCKING;
    params.writeDataMode = UART_DATA_BINARY;
    params.readDataMode = UART_DATA_BINARY;
    params.readEcho = UART_ECHO_OFF;
    params.readTimeout = 100000;//1s

    uartHandle = UART_open(0, &params);
    if (!uartHandle)
    {
    Task_exit();
    }

  • I would hold off on changing the UART blocking mode.

    I think you ought to try to understand the negative Semphore_pend waiting and Task_sleep first.

    1. Do you need an Hwi_disable/restore around the "rtimer_set()" call in timeslot_task()?

    2. Your comment in code says "add 1 ms delay to timeout" but you do CLOCK_SECOND/1000 (How is this a milisecond?)

    3. Are you stacks okay when you hit the error condition. I notice your stack peak is 656 and stacksize is 756 which is close. Can you try increase your stacksize?

    The waiting for ### more ticks is a calculated value. Its taking the clocks current timeout - the clocks current tick and also supposed to compensate for any wrap condition.

    Judah