ARM Technical Support Knowledge Articles

Can I prevent my interrupt handlers from being interrupted?

Applies to: Cortex-M3

Answer

Exceptions (which include interrupts and faults) will only pre-empt (interrupt) the current execution context if the new exception has a strictly higher priority than the current context. The prioritization scheme is an architected feature, therefore the ARM v7-M Architecture Reference Manual should be consulted for details. The current execution priority is the highest priority of all currently active exceptions, or if no exceptions are active, the base priority level.

Three exceptions have pre-defined (very high) priorities:
-3 : Reset
-2 : NMI
-1 : Hard Fault

All other exceptions, including regular interrupts, have programmable priorities, with a maximum priority level of 0 and higher numerical values giving lower priority levels.

The priority scheme considers each exception to have an 8-bit priority value. Usually only the 3 or 4 highest order bits are implemented, with unimplemented lower order bits appearing as zeros. The base priority level can be considered to have a priority lower than the lowest programmable priority level. (Base priority level can be considered to be 256.)

The apparent 8-bit field is divided, at a position programmed in the PRIGROUP field of the Application Interrupt and Reset Control Register, into a higher order portion known as group priority (or pre-empting priority) and a lower order portion known as sub-priority).

Exceptions with configurable priority can not interrupt each other if they have the same value in their group priority field. This becomes trivially true if the PRIGROUP is programmed to '111' to select zero bits of group priority and eight bits of sub-priority; or more flexibility can be provided by allowing some pre-empting levels but programming specific exceptions to have the same group priority to cause them not to interrupt each other.

The technique of branching directly from the end of one Interrupt Service Routine (ISR) to the start of another ISR, without ever popping the interrupted context off the stack, is known as "tail chaining". Because pre-emption has a higher overhead than tail chaining, the scenario of having many interrupts with equal group prioirity is actually beneficial for overall system performance, as it wastes fewer cycles in the administrative procedure between execution of ISRs where multiple interrupts are pending (waiting to be serviced) or active at the same time.

The sub-priority field allows control over the decisions about which interrupt to service next, where there are several pending interrupts waiting to be serviced after the currently executing ISR. Where group priority and sub-priority are both equal, the interrupt number itself will be used to determine the next interrupt to be handled.

The current execution priority can be artificially boosted by software using MSR or CPS instructions to control the PRIMASK, FAULTMASK or BASEPRI settings. Setting PRIMASK (eg. CPSID i) raises the current execution priority to 0, inhibiting any exceptions of programmable priority, other than those exeptions which escalate to Hard Fault. Setting FAULTMASK (eg. CPSID f) raises the current execution priority to -1, inhibiting all exceptions, including Faults, other than NMI and Reset. Programming BASEPRI can elevate the current execution priority to any intermediate level higher than the current level but lower than priority zero.

For any Fault with configurable priority, if the fault occurs but the handler is not enabled or the priority is too low, it will automatically escalate to a Hard Fault and call the Hard Fault handler at a prioirity of -1, unless the current execution priority is already -1 or higher.


Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential