spacewrench wrote on Saturday, February 16, 2008:
I’m playing with FreeRTOS on a GameBoy Advance (ARM7TDMI processor), and I started my port with the GCC version for LPC2000. There’s several weird things in there, and I wonder whether they’re workarounds for (possibly old) GCC bugs, or whether I just don’t understand ARM Deep Magic well enough.
For example, SAVE_CONTEXT does:
STMDB LR,{R0-LR}^
NOP
SUB LR, LR, #60
instead of just:
STMDB LR!,{R0-LR}^
Maybe there’s an issue with write-back when you’re using the IRQ LR to save USR/SYS regs, including USR/SYS-LR? The same thing shows up in RESTORE_CONTEXT, too.
Also, the stack frame prepared by pxPortInitaliseStack has this comment:
/* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the
tasks context. */
and it stores a task-specific value for ulCriticalNesting at the bottom of the stack frame. However, despite the comment, it appears that ulCriticalNesting isn’t used to set the processor interrupt flags when a task is swapped in. In fact, I think the CriticalNesting counter may introduce a problem: normally, when you go from CriticalNesting == 0 to CriticalNesting > 0, the processor interrupt flags are cleared (IRQ disabled). Therefore, if CriticalNesting > 0, the timer interrupt won’t happen, and the task won’t be preempted. But if the task YIELDs within a critical section, don’t Bad Things happen? When the next task runs, interrupts will be re-enabled. Then, when the first task resumes, interrupts will still be on, even though CriticalNesting > 0. Maybe YIELDing while interrupts are disabled should cause a panic?