I've spent hours trying to answer my question, but could not find any satisfying answer.
Since ARM Cortex-M cores does not have any instruction to read the state of global interupt mask (PRIMASK register) and immediately disabling it, all frameworks are using the following sequence of two instructions:
mrs r0, PRIMASK ; Read current state
cpsid i ; Mask IRQs
But there is no explanation, why this piece of code is considered atomic... What happens when the IRQ comes in between the execution of this two instructions and the IRQ handler changes the state of PRIMASK? Like
mrs r0, PRIMASK ; Read current state
; Some weird IRQ handling happens here and changes PRIMASK
cpsid i ; Mask IRQs
Since this code is widely used, I suspect that this situation should never happen by (architecture?) design. Could somebody please explain to me why? :-) Thanks!
Enabling Interrupts to the Core To enable IRQ interrupts, clear the I bit of the CPSR; to enable FIQ interrupts, clear the F bit of the CPSR. Likewise, to disabled these interrupts, set the respective bits.
Interrupt Priority Registers (NVIC_IPR)8 bits are used to configure the priority of each interrupt. The number of supported priority levels is implementation defined and is in the range of 4-256. When less than 256 priority levels are implemented, the lower bits in the field read-as-zero.
The Cortex-M3 processor supports interrupts and system exceptions. The processor and the NVIC prioritize and handle all exceptions. An exception changes the normal flow of software control. The processor uses Handler mode to handle all exceptions except for reset.
The PRIMASK, FAULTMASK, and BASEPRI registers are used for exception or interrupt masking.
What happens when the IRQ comes in between the execution of this two instructions and the IRQ handler changes the state of PRIMASK?
The program will randomly lock up, as this would also break most other "wait for interrupt" methods (like volatile
variables).
Remember that an interrupt can only occur if it is not masked, so the interrupt handler could only ever disable interrupts. But disabling interrupts globally will also prevent other interrupts from fireing - and the code waiting for some hardware interaction usually does not re-enable interrups randomly.
That is why an interrupt handler is considered br0ken when it modifies PRIMASK
or FAULTMASK
without restoring it on exception return.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With