Tick overflow and sending to queue from timer callback

Please consider following path:

(all lines number are for commit c4f9e27c28c018c85b9d23e5ac7470ada508bdb8)

  • timers task gets active and process timers (timers.c#L596)
  • scheduler is set to suspended state (timers.c#L610)
  • prvSampleTimeNow is called (timers.c#L617)
  • due to MCU running without interrupts enabled for few ticks (for example ISR was disabled to write flash memory, in some architectures during writes one can execute code only from RAM)
  • TickType_t overflowed when MCU had interrupts disabled and code goes into prvSwitchTimerLists
    (timers.c#L702)
  • there was at least one pending timer which expired and callback function is called (timers.c#L564)
  • callback function calls xQueueGenericSend
    In that function there’s assert that scheduler must be running, but due to point 2 scheduler is in suspended state. The assert is triggered.

Is my analysis correct and it is real problem? I got into this situation due to bug in my code when tick overflow happened to often.

Comments below:

  • timers task gets active and process timers (timers.c#L596)
  • scheduler is set to suspended state (timers.c#L610)

At this point the scheduler is suspended so context switches cannot occur.

  • prvSampleTimeNow is called (timers.c#L617)
  • due to MCU running without interrupts enabled for few ticks (for example ISR was disabled to write flash memory, in some architectures during writes one can execute code only from RAM)

What causes the MCU to run with interrupts disabled here? The scheduler is locked so only the timer task and interrupts can be running. The timer task does not disable interrupts (or write to flash, as per your example), so interrupts would have to be disabled by another interrupt, and an interrupt cannot leave interrupts disabled when it exits otherwise no more interrupts would execute (including the RTOS tick interrupt).

  • TickType_t overflowed when MCU had interrupts disabled and code goes into prvSwitchTimerLists
    (timers.c#L702)

TickType_t is a type, not a variable, so which variable overflows? If you mean the tick count, then if interrupts are disabled the tick count is not going to change as it is updated inside the tick interrupt (which is disabled in your scenario).

Does that clear things up for you or do you think there may still be an issue?

Looking at the code, timer callbacks called due to a call to prvSwitchTimerLists are call with the scheduler disabled, while normally they are called with the scheduler running. While normally, the fact that timer callback should not block is not enforced, in prvSwitchTimerLists it is the case that they MUST not block, or bad things happen.

My guess is his callback does a send with a non-zero block time, which doesn’t cause a problem unless it gets called during the Scheduler suspend period.

Likely he also has a 16 bit tick counter so it can overflow somewhat frequently so the problem has a chance to show up.

Right - I see that now. Pondering.

Yes, normally not blocking is just a ‘best practices’, but there it is a requirement.

Don’t know if it would be possible for that code to just move those events to ‘tick 0’ of the new list to let them run in the normal manner (would need to see if this impacts any aspects of them like repeats).

Timer task gets active just after interrupts was enabled again and xTtickCount overflowed.

MCU is running with interrupts disabled because there’s need to write to flash memory. In Cortex-M4 during flash writes only code from RAM (or cache) can be running, flash memory reads are forbidden. So to protect from ISR firing and reading code from flash memory interrupts are disabled.

Yes, I’m using non-zero xTicksToWait in xQueueGenericSend (there’s check for that in configASSERT).

And, as I mentioned, the use of possibly blocking calls in timer callbacks is currently not allowed, but only actually checked for in this case.