I am running 3 tasks (including the idle task) in an 32-bit ATMEL UC3A.
After startup and under normal operation the picture is as follows:
Task A (priority 2): Switching from Running to Delayed. That is: running for a while, then waiting on a vTaskDelay()
Task B (priority 3): Blocked on a semaphore take
Idle task (priority 0)
I also have some event handlers (interrupts) running at the same priority as the RTOS tick (0) that do not interact with the kernel.
My application runs for a while and then hangs. If I break in with the debugger the picture is the following:
- Execution is at the Idle Task (for ever)
- Task A is in the DelayedTaskList1. Which makes sense in that the tick counter is less than the task wake up time
- vTick is not called anymore (which explains why the tick counter does not increment and Task A is switched back in)
Digging further into the CPU registers I noticed that, in this ‘hanged’ state, the idle task is running from an interrupt! (According to the CPU status register the execution mode is ‘Interrupt Level 0’ and interrupts in this level are masked). The latter masks my timer interrupts causing the tick not to interrupt ever again effectively hanging the system.
Something exotic about this issue is that when I check where the tick counter froze and when Task A should have came out from the delayed tasks list the difference is always 20 ticks while the absolute counts vary quite a bit.
The problem seems to be somewhere in the context switching but I cannot tell where. I enabled the stack overflow detection with no results (no overflows).
I increased the idle task stack size from 256 to 512 and that only helped extending the running time until it hanged again. Maybe that is a clue.
How can the idle task end up running in INT_0 mode? Is the RTOS messing up the context switching? What does the 20 tick difference mean? Anybody has a clue?