Konrad Anton

Possible scheduler bug in MQX 3.7 for Kinetis

Discussion created by Konrad Anton on Sep 29, 2011
Latest reply on Jun 14, 2012 by Martin Kojtal

Hello all,


the following describes what I believe to be a bug in the scheduler of MQX for Kinetis.

The scenario involves two tasks, two ISRs and the PendSV handler. The tasks in my example have (Cortex) priorities 0xC0 (LowTask) and 0x60(HighTask), the interrupts have priorities 0xA0 (LowInt) and 0x80(HighInt). 

 

  1. We start with LowTask running with BASEPRI=0xC0.
  2. LowInt fires. The LowInt handler requests the scheduler to run(set_pend_sv) (e.g. by setting an event).
  3. set_pend_sv notices that the PendSV-Pending flag is 0, computesPendSV-priority as BASEPRI-0x10=0xB0, and sets PendSV-Pending to 1.
  4. LowInt returns.
  5. PendSV fires immediately afterwards. 
  6. PendSV is interrupted by HighInt.
  7. The HighInt handler sets another event, which calls set_pend_sv. 
  8. set_pend_sv notices that PendSV-Pending flag is 1, and returns immediately.
  9. The HighInt handler returns.
  10. PendSV handler calls the scheduler, which consults the ready queuesand readies HighTask. In doing so, the scheduler sets BASEPRI=0x60.
  11. PendSV handler returns into HighTask, with PendSV-Pending=1.
  12. HighTask tries to sleep (or calls another blocking syscall), which calls set_pend_sv. 
  13. set_pend_sv notices that PendSV-Pending flag is 1, and returns immediately.
  14. The blocking syscall returns immediately to HighTask, because thePendSV handler has priority 0xB0 and can't fire.
  15. HighTask does whatever tasks do which believe to have slept.

The precise mechanism of (6) is still unclear to me, though I know of two hypotheses.

Miro Samek writes in http://embeddedgurus.com/state-space/2011/09/whats-the-state-of-your-cortex/ that he has observed

cases in which the late-arrival mechanism of the NVIC caused PendSV to be pending within PendSV (he doesn't use MQX).

 

My hypothesis is that the PendSV handler is interrupted before executing its first line, which is a disable-all-interrupts statement. I have performed experiments in which HighInt is a very busy timer interrupt which calls set_pend_sv, and I manage to find PendSV pending within the PendSV handler every couple of 10000 HighInt calls.

 

I'm aware of two suggested fixes. In his blog posting, Samek suggests clearing the PendSV-pending flag within the PendSV handler (although as a fix to a different problem).

 

Another fix involves set_pend_sv. It could be changed to update the PendSV priority every time instead of only when PendSV isn't pending. If in aptly named step (13), set_pend_sv were to change PendSV priority to 0x50, then HighTask would be properly interrupted.

 

I hope this was understandable. I've applied the second fix to my example program, and I don't get sleepless HighTasks any more.

 

Greetings

KA

Outcomes