After careful examination of the source code and the Chibios traces, I have some more information on this issue, and a possible cause.
Let's say that I have the following threads:
Thread A, priority 128
Thread B, priority 129
And the following sequence:
1. Thread B executes (higher priority)
2. Thread B gets to WAITING state (call to chThdSleep())
3. Thread A starts execution.
4. SysTick Handler preempts Thread A.
5. Due to increase in system counter, Thread B gets in READY state.
6. Execution returns to Thread A. (
WRONG!!!)
7. Priority order violation gets triggered.
After this, it becomes clear to me that for some reason the SysTick handler does not perform a context switch that it had to.
Follows my SysTick handler. I can't see anything wrong with it. Comparing it to the handlers in the examples provided by Chibios, it seems identical.
Code: Select all
void SysTick_Handler()
{
CH_IRQ_PROLOGUE();
chSysLockFromISR();
chSysTimerHandlerI();
chSysUnlockFromISR();
CH_IRQ_EPILOGUE();
}
I started digging Chibios source code. I found that
CH_IRQ_EPILOGUE() calls
_port_irq_epilogue which is ultimately responsible for the context switch.
Within
_port_irq_epilogue there is the following condition check:
Code: Select all
if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0U)
According to
this, the context switch will only take place if the SysTick handler is the only interrupt being executed. If SysTick has preempted another lower priority (non-system) interrupt, there will be no context switch. I am not sure whether I would consider this a bug or a feature.
In my case there are non-system / fast-IRQs (i.e. without
CH_IRQ_PROLOGUE() and
CH_IRQ_EPILOGUE() guards), of
lower priority than SysTick. I believe that such a handler gets preempted by SysTick, which results in no switching.
Giovanni, do you believe that this would be the case? Do all fast-IRQs must be of higher priority than all system IRQs?