Reputation: 57
I attended a lecture on FreeRtos and Cortex M where the instructor advised that if ISR safe version of API is not used from ISR it can lead to Usage fault exception in Cortex M processors.This would happen because this can involve going from interrupt context(interrupt handler) to task context(thread handler) My question is why this task switch would be considered illegal and what would be the repercussions of such a switch?
Upvotes: 2
Views: 11486
Reputation: 93566
This answer is generic and not FreeRTOS nor Cortex-M specific - it applies to any typical RTOS on any platform:
RTOS API calls that cause the scheduler to run cannot be called from the interrupt service routine. For example, if you give a semaphore, normally the scheduler runs to switch to any task pending on that semaphore; this is inappropriate in an ISR, where the scheduler must run once when the interrupt context exits; obviously you do not want a context switch before the interrupt has completed and there may be other API calls or preemption by higher priority interrupts that cause a different task to become runable; making that assessment only once when the context switch will occur maintains deterministic behaviour.
The ISR specific versions of functions do not invoke the scheduler immediately; instead they set a flag to indicate that the scheduler must run on exit from the interrupt context.
Typically an ISR that makes RTOS API calls must have a prologue and epilogue; specific enter/exit interrupt calls or macros. This prologue, increments a counter that is decremented in the epilogue; if the counter is zero and the schedule flag is set, the scheduler will run. The counter is to prevent the scheduler from running on exit from a nested interrupt. This ensures that the scheduler only runs once on exit form the lowest priority pending interrupt.
Whether or why a "uasge fault" would occur is a FreeRTOS specific implementation detail, and largely academic. An RTOS could equally trap the usage of a non-ISR safe call in an ISR and run a more specific error handler, if it does not bother to do so, then the resulting behaviour might trigger a usage fault; it seems a somewhat crude mechanism to rely on; Usage Fault is a very broad trap and could happen for a number of reasons:
Usage Fault: detects execution of undefined instructions, unaligned memory access for load/store multiple. When enabled, divide-by-zero and other unaligned memory accesses are also detected.
Some RTOS do not have ISR specific functions, instead the API calls that cause scheduling detect internally the ISR context and behave differently in that context - this is simpler and safer for the programmer, but carries a small overhead to test the context on every such call. An API that handles ISR safety internally also means that calling functions that may themselves make OS API calls is simpler since those functions themselves need not be ISR specific.
Upvotes: 2
Reputation: 1704
On a Cortex-M (some of) the current context will be stored on stack in use before the interrupt (on interrupt entry), so if you were in a task and it was interrupted some of the current context would be stored on the task stack (via the PSP). The interrupt itself always runs on the MSP. If the interrupt does not return to the task which it interrupted then the interrupted task will have a messed up stack (as it restores the stored context on exit) as well as trying to restore an incorrect context for the task which was switched to.
On a context switch(which happens in an interrupt) again some of the context is automatically stored on the task stack, but the OS also stores the rest of the context on the task stack as well. When it does the switch and exits the interrupt, the OS restores the context it stored itself for the task and then the rest of the context is automatically restored by exiting the interrupt. This works as it is ensured that the stack is left in the correct format. Look at interrupt entry / exit in the Cortex-M4 Generic User Guide.
Not all processors work like this.
Upvotes: 4