Fault handling
In ARMv7-M and the ARMv8-M architecture with Main Extension, several Fault Status Registers (XFSR) are available to allow fault handlers to identify the cause of the fault exceptions. Each fault has an associated Fault Status Register. Fault Address Registers (XFAR) are available to indicate the address of the access that triggers the fault.
The fault status registers indicate the cause of a fault. For synchronous BusFaults and MemManage faults, the fault address register indicates the address that is accessed by the operation that caused the fault.
The following table shows the fault status and fault address registers:
Handler |
Status register name |
Address register name |
Register description |
HardFault |
HFSR |
- |
HardFault Status Register |
MemManage |
MMFSR |
- |
MemManage Fault Status Register |
MMFAR |
MemManage Fault Address Register |
||
BusFault |
BFSR |
- |
BusFault Status Register |
- |
BFAR |
BusFault Address Register |
|
UsageFault |
UFSR |
- |
UsageFault Status Register |
The following table shows:
- The type of fault
- The handler that is used for the fault.
- The corresponding fault status register, and
- The register bit that indicates that the fault has occurred.
Fault |
Handler |
Bit name |
Fault status register |
Bus error on a vector read |
HardFault |
VECTTBL |
HardFault Status Register |
Fault escalated to a hard fault |
FORCED |
||
MPU or default memory map mismatch: |
MemManage |
- |
MemManage Fault Status Register |
On instruction access |
IACCVIOL |
||
On data access |
DACCVIOL |
||
During exception stacking |
MSTKERR |
||
During exception unstacking |
MUNSKERR |
||
During lazy floating-point state preservation |
MLSPERR |
||
Bus error: |
BusFault |
- |
- |
During exception stacking |
STKERR |
BusFault Status Register |
|
During exception unstacking |
UNSTKERR |
||
During instruction prefetch |
BUSERR |
||
During lazy floating-point state preservation |
LSPERR |
||
Precise data bus error |
PRECISERR |
||
Imprecise data bus error |
IMPRECISERR |
||
Attempt to access a coprocessor |
UsageFault |
NOCP |
UsageFault Status Register |
UNDEFINED instruction |
- |
UNDEFINSTR |
|
Attempt to enter an invalid instruction set state |
INVSTATE |
||
Invalid EXC_RETURN value |
INVPC |
||
Illegal unaligned load or store |
UNALIGNED |
||
Divide By 0 |
DIVBYZERO |
Note
A fault inside a HardFault handler locks up the core.
Synchronous and Asynchronous bus faults
Bus Faults are subdivided into two classes:
A synchronous bus fault. |
This is also described as a precise bus fault in older versions of ARM documents, and refers to the fault exception that takes place immediately after the bus transfer is carried out. |
An asynchronous bus fault. |
This is also described as an imprecise bus fault in older versions of ARM documents, and refers to the fault exception that can take place a certain time after the bus transfer is carried out, where the processor could have executed further instructions before the exception sequence started. |
Synchronous bus fault
A synchronous BusFault can escalate into lockup if it occurs inside an NMI or HardFault handler. Cache maintenance operations can also trigger a bus fault.
The fault handler can use BFSR
to determine whether faults are asynchronous
or synchronous. Asynchronous faults are often unrecoverable, as you do not know which
code caused the error.
Asynchronous bus fault
An asynchronous bus fault can happen when there is write buffering in the processor design. As a result, the processor pipeline proceeds to subsequent instruction execution before the bus error response is observed.
Debug accesses can also trigger Bus Faults. Debugger load or store accesses are synchronous, and are visible to the debugger interface only.
When an asynchronous bus fault is triggered, the BusFault exception is pended. If another higher priority interrupt event arrived at the same time, the higher priority interrupt handler is executed first, and then the Bus Fault exception takes place. If the BusFault handler is not enabled, the HardFault exception is pended instead. The HardFault caused by the asynchronous BusFault never escalates into lockup.
Lockup state
The processor enters lockup state if a fault occurs when executing the NMI or HardFault handlers. When NMI is Non-secure and a Security violation is detected, it triggers a Secure HardFault at priority level 3. When the processor is in lockup state, it does not execute any instructions.
The processor remains in lockup state until either:
- It is reset.
- An NMI occurs.
- A debugger halts it.
Note
If lockup state occurs from the NMI handler, a subsequent NMI does not cause the processor to leave lockup state.
Non-secure fault handler considerations
When migrating software from ARMv6-M or ARMv7-M to ARMv8-M architecture, software developers that create Non-secure software must be aware of some possible changes:
- The HardFault and BusFault handler might no longer be used because the Secure software on chip has its own HardFault and BusFault handlers (AIRCR.BFHFNMINS might be set to 0).
- Self-reset might not be accessible from Non-secure software. When TrustZone technology for ARMv8-M is implemented, Secure software can configure whether Non-secure software can access the SYSRESETREQ bit in AIRCR. Also, the AIRCR.VECTRESET bit in ARMv7-M is not available in ARMv8-M architecture.
General considerations
In general, software developers for Secure software:
- Must always implement fault handlers to ensure that software developers creating Non-secure software can be aware of problems during software development.
- Secure software must utilize stack limit registers to ensure that stack overflow in Secure software can be detected and handled by a Secure HardFault or Usage Fault handler.
- Secure fault handlers must not call Non-secure functions to prevent Non-secure code gaining access to the Secure state which can be used for DoS attack.