Hi Giovanni, I think I've found the source of problem. I didn't observe the problem when I added `chSysLockFromISR` to my problematic ISRs. But I'm not sure if this is what fixed it.
I have been signaling semaphores from interrupt callbacks. But I did not use `chSysLockFromISR`. Different threads with different priorities have been waiting on these semaphores. I think problem was that; when two interrupts collide, order of rescheduling messes up. Because cpu switches to another interrupts callback during the processing of an ISR.
Here is a pseudo code of what I think was happening:
Code: Select all
high_priority_thread()
{
while(true)
{
chBSemWait(&high_pri_sem);
do_important_stuff();
}
}
low_priority_thread()
{
while(true)
{
chBSemWait(&low_pri_sem); // ASSERT happens inside this call during chSysUnlock
do_less_imporant_stuff();
}
}
isr_callback_timer()
{
do_stuff();
chBSemSignalI(&high_pri_sem); // this should wake up HIGH pri. thread
do_some_other_stuff();
}
isr_callback_exti()
{
chBSemSignalI(&low_pri_sem); // this should wake up LOW pri. thread
}
Assert was fired when low priority thread was awaking from a call to `chBSemWait`. Here is what I think was happening.
1. timer interrupt occurs, isr_callback_timer() is called
2. isr_callback_timer() signals the `high_pri_sem`
3. But, before isr exits, around `do_some_other_stuff()`...
4. pin interrupt occurs, cpu switches to isr_callback_exti()
5. isr_callback_exti() signals the low_pri_sem, and at the exit does reschedule
6. cpu returns to the isr_callback_timer(), exits it and reschedules
7. since at step #5 rescheduling is done after `low_pri_sem`, cpu switches to the LOW priority thread instead of high priority thread
Can you please confirm if this is a possible scenario? I barely understand how scheduling works.
By the way I'm using STM32F407.