PendSV pending inside PendSV handler? (Cortex-M4)
Posted 06 September 2011 - 11:45 AM
I'm debugging a driver which runs on a Freescale Kinetis K60 (Cortex-M4) with the Freescale MQX operating system.
The bug I'm trying to track down: by bombarding my system with thousands of network frames, I can get it randomly into a state where (only) the timer task is running, the PendSV-pending flag in ICSR is set, but the PendSV priority in SHPR3 is lower (0xB0) than the priority of the task (BASEPRI=0x60).
This makes a bit more sense if one considers that MQX runs everything in supervisor mode, with BASEPRI=0xC0 for low-priority tasks (at least in my version of the TWR-board BSP), and BASEPRI<0xC0 for highpriority tasks (e.g. task priority 1 runs at BASEPRI=0x60). Furthermore, when MQX wishes to run the dispatcher (e.g. when unblocking, or in the ISR epilogue if the active task pointer has changed), it sets PendSV pending with priority (BASEPRI-0x10, yes, higher priority), unless PendSV is already pending (in which case the SHPR3 is not considered). Finally, user ISRs are run with whatever value BASEPRI had when the interrupt fired.
One way this setup could lead to the bad state would be if the PendSV-pending flag were set again, with SHPR3=0xB0, during the PendSV handler. Then the PendSV handler could switch to the high-priority task, set BASEPRI=0x60, and when the high-priority task wanted to block itself, it would find PendSV pending, and do nothing.
So I wrote a check into the beginning of the PendSV handler which detects that PendSV is pending in ICSR, and jumps to a nop on which I put a breakpoint and activated the ETM tracer. After a few minutes of forced network traffic, the breakpoint was reached. Inside the PendSV handler, ICSR showed PendSV pending and SHPR3 priority=0xB0. The trace showed an immediate past in which my driver's ISR returned into the MQX ISR epilogue, which set PendSV pending and returned. Immediately afterwards, the PendSV handler was executed and my check found PendSV still pending.
Is it plausible that the PendSV-pending flag could be active immediately after entry into the PendSV handler, without an interrupt interrupting the PendSV handler?
Posted 26 September 2011 - 09:11 PM
I have written about this hardware race condition in my State Space blog entry "What's the State of your Cortex". This blog post presents a distilled hardware trace that clearly illustrates the issue. The fix of this bug is simple, and requires manual clearing of the PENDSVSET bit by writing 1 to the PENDSVCLR bit in the same register. This code should be added to the PendSV handler in your RTOS. I have verified that the problem disappeared after applying the bug fix.
I would appreciate if you could post to this forum your results (whether or not this fixes your problem).
This post has been edited by Miro Samek: 26 September 2011 - 09:19 PM
Posted 27 September 2011 - 06:48 PM
I would expect to find a PendSV pending in a PendSV interrupt, if an interrupt that preempted it pended a new PendSV interrupt.