rtel wrote on Friday, June 10, 2011:
The FreeRTOS book for PIC32 states that an unmodified classic ISR (i.e. with no special RTOS wrapper in assembler) can still be used with FreeRTOS as long as the ISR does not cause a task to change state. Does that simply mean that the ISR should not make any FreeRTOS API calls or are there also other catches?
As I recall, that pretty much sums it up. A task can only change state through an API call being made.
Another rule is that a classic unwrapped ISR used with FreeRTOS must not be interrupted. But interrupted by what?
- By the kernel? I.e. ISR should have same or higher interrupt priority as the kernel?
- By another ISR that uses API calls?
- Or also by ANY other classic or FreeRTOS-aware ISR having a higher interrupt priority than my classic ISR?
Again, as I recall, it would mean by any interrupt that will enter through the FreeRTOS wrapper code.
What you refer to as ‘classic’ interrupts enter through code that is generated by the compiler. If you declare the function as an interrupt the compiler generated different function prologue and epilogue assembly code. Again, if my recollection is correct, you can tell the compiler whether the body of the interrupt should run with interrupt enabled or disabled. If you tell the compiler to enable interrupts then the compiler generated prologue code will include a line to enable interrupts. Be aware that if you have ‘classic’ interrupts then the stack you have to allocate to each task will be much larger as it will have to (potentially) hold an entire interrupt stack too.
If you enter an interrupt through the FreeRTOS wrapper code, then there is a lot of ‘extra’ stuff that goes on. For example, it keeps a note of whether interrupts are nested or not, and only re-enables interrupts that have a priority higher than the currently executing interrupt. It also switches to a dedicated ISR stack to radically reduce the amount of RAM that has to be allocated to the stack of each task - because the task stacks will only ever have to hold the task stack, and never a (potentially nested) interrupt stack on top.
Because of the extra code in the FreeRTOS wrapper (the interrupt nesting count, stack swapping, etc) you cannot mix ‘classic’ and FreeRTOS interrupts in the same nesting.
You could probably have a ‘classic’ interrupt nest with an existing stack of nested ‘FreeRTOS’ interrupts, so the ‘classic’ interrupt stacks are always on top (I think the FreeRTOS demo does this with a high frequency timer, but would have to double check), but never intermingle the two or have a FreeRTOS interrupt on top of a classic interrupt.