The S32K14x MCU ARM Cortex M4F core processor handles fault exceptions using four handlers.
Handlers
UsageFault_Handler()
Usage faults are caused by an application that incorrectly uses Cortex M4 processor trying to
execute an undefined instruction
execute an instruction that makes illegal use of the Execution Program Status Register (EPSR), typically, this processor support only Thumb instruction set and it requires that all branch targets should be indicated as odd numbers, having bit[0] set.
perform an illegal load of EXC_RETURN to the PC
access a coprocessor if the access is denied or privileged only (configurable in CPACR)
make an unaligned memory access
execute an SDIV or UDIV instruction with a divisor of 0
The detection of the division by zero fault is disabled by default which means that such an operation returns zero and the fault is not detected. Similarly, the Cortex-M4 processor supports unaligned access for certain instructions. The detection on both the division by zero and the unaligned access (for every instruction) faults can be enabled in Configuration and Control Register (CCR).
BusFault_Handler()
Bus faults occur when a bus slave returns an error response while
stacking for an exception entry
unstacking for an exception return
prefetching an instruction
during floating-point lazy state preservation
Beside these faults listed above, there are also bus faults labeled as Precise and Imprecise. Imprecise bus fault occurs when an application writes to buffered memory region and continues executing subsequent instructions before the actual bus fault is detected. Therefore, at the time the exception rises the program counter doesn’t point to the instruction that has caused the bus fault. For debugging purposes, it is necessary to have “precise” program counter value to know which instruction has caused the fault exception. Imprecise bus fault can be forced to be precise by disabling the write buffer in (ACTLR_DISDEFWBUF = 1). This however might decrease the performance.
Note: The S32K144 MCU has its own system Memory Protection Unit which is implemented on the bus. Therefore, any system MPU violation triggers bus faults.
MemManage_Handler()
Typically, these exceptions rise on an attempt to access regions that are protected by the core ARM Cortex M4 Memory Protection Unit.
attempt to load or store at a protected location
instruction fetch from a protected location
stacking/unstacking fault caused by violation of the memory protection
protection violation during floating-point lazy state preservation
S32K1xx series implements its own system Memory Protection Unit on the bus and therefore an attempt to access a protected region results in a bus fault exception instead. Nevertheless, the system MPU does not protect access to peripheral registers, and as the attached example code shows, an attempt to fetch instruction from a peripheral memory region causes a MemManage fault exception.
HardFault_Handler()
This handler is the only one that has a fixed priority (-1) and is always enabled.
If other handlers are disabled (in the SHCSR register), all faults are escalated to this handler.
The escalation take place also when a fault occurs during another fault handling execution or while the vector table is read.
Priority of exception fault handlers
The fault exception handlers’ priorities, besides the HardFault handler (fixed priority -1), are configurable in fields PRI_4, PRI_5 and PRI_6 of SHPR1 register.
These fields are byte-accessible and Cortex M4 support 255 priority levels, however, S32K14x MCUs support 16 priority levels only.
Therefore, priorities are configurable in the four most significant bits of PRI_4, PRI_5 and PRI_6 only, which is similar to other NVIC IPR registers as shown below.
The lower priority number is set, the higher priority. By default, all handlers have priority set to zero.
Status and address registers for fault exceptions
Configurable Fault Status Register (CSFR) consists from three status bit fields for Usage Fault (UFSR), Bus Fault (BFSR), and Memory Management Fault (MMFSR) where each bit represents a fault exception.
There are also two auxiliary address registers. If BFARVALID is set in the BFSR register, Bus Fault Address Register (BFAR) holds the memory access location of a precise bus fault. Similarly, if MMARVALID bit is set in MMFSR register, Memory Manage Address Register (MMAR) holds the address of a MemManage fault.
Example code
To demonstrate the debugging process, the following exceptions can be forced:
attempt to access an unimplemented memory area
attempt to write to a non-gated peripheral register
write to read only register
fetching an instruction from a protected peripheral memory region
division be zero
unaligned memory access
execution of a non-thumb instruction
execution of an undefined instruction
When the program enters an exception handler, the stack frame is pushed onto the stack including the program counter value of the fault instruction. In this example, the exception handlers are declared with __attribute__((nake_)) (fault_exceptions.h), no prologue is generated and the program counter is always offset by 6 words (0x14) from the stack pointer that can be read in the handlers using either the debugger (memory view) or a SW pointer. If an application uses Process Stack Pointer (PSP) as well, it is necessary to find out whether the stack pointer comes from Main Stack Pointer (MSP) or PSP, this information is available in the EXC_RETURN value in the link register. Having a precise program counter address, we can find the fault instruction in Disassembly.
This applies to all exception except for imprecise bus faults as explained above, imprecise bus faults can be forced to be precise by disabling the Write buffer.
The CSFR register is read to determine which exception has occurred and, if available, the memory access location that has caused the exception.
References
Cortex-M4 Devices Generic User Guide Cortex-M4 Technical Reference Manual
查看全文