The S32K14x MCU ARM Cortex M4F core processor handles fault exceptions using four handlers.
Usage faults are caused by an application that incorrectly uses Cortex M4 processor trying to
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).
Bus faults occur when a bus slave returns an error response while
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.
Typically, these exceptions rise on an attempt to access regions that are protected by the core ARM Cortex M4 Memory Protection Unit.
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.
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.
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.
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.
To demonstrate the debugging process, the following exceptions can be forced:
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.