arch: arm: correct fault address logging

In ARMv7-M (and ARMv8-M) architecture it is
implementation defined whether separate MMFAR and BFAR are
implemented. This commit ensures that we always get the true
faulting address displayed in case of MemManage- or BusFault.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
This commit is contained in:
Ioannis Glaropoulos 2018-02-25 14:13:56 +01:00 committed by Kumar Gala
parent 83fa6c9554
commit 571069e986

View File

@ -21,8 +21,10 @@
#ifdef CONFIG_PRINTK
#include <misc/printk.h>
#define PR_EXC(...) printk(__VA_ARGS__)
#define STORE_xFAR(reg_var, reg) u32_t reg_var = (u32_t)reg
#else
#define PR_EXC(...)
#define STORE_xFAR(reg_var, reg)
#endif /* CONFIG_PRINTK */
#if (CONFIG_FAULT_DUMP > 0)
@ -73,15 +75,26 @@ void _FaultDump(const NANO_ESF *esf, int fault)
PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
SCB_MMFSR, SCB_BFSR, SCB_MMFSR);
/* In a fault handler, to determine the true faulting address:
* 1. Read and save the MMFAR or BFAR value.
* 2. Read the MMARVALID bit in the MMFSR, or the BFARVALID bit in the
* BFSR. The MMFAR or BFAR address is valid only if this bit is 1.
*
* Software must follow this sequence because another higher priority
* exception might change the MMFAR or BFAR value.
*/
STORE_xFAR(mmfar, SCB->MMFAR);
STORE_xFAR(bfar, SCB->BFAR);
if (SCB->CFSR & CFSR_MMARVALID_Msk) {
PR_EXC("MMFAR: 0x%x\n", SCB->MMFAR);
PR_EXC("MMFAR: 0x%x\n", mmfar);
if (escalation) {
/* clear MMAR[VALID] to reset */
SCB->CFSR &= ~CFSR_MMARVALID_Msk;
}
}
if (SCB->CFSR & CFSR_BFARVALID_Msk) {
PR_EXC("BFAR: 0x%x\n", SCB->BFAR);
PR_EXC("BFAR: 0x%x\n", bfar);
if (escalation) {
/* clear CFSR_BFAR[VALID] to reset */
SCB->CFSR &= ~CFSR_BFARVALID_Msk;
@ -136,8 +149,18 @@ static void _MpuFault(const NANO_ESF *esf, int fromHardFault)
PR_EXC(" Unstacking error\n");
} else if (SCB->CFSR & CFSR_DACCVIOL_Msk) {
PR_EXC(" Data Access Violation\n");
/* In a fault handler, to determine the true faulting address:
* 1. Read and save the MMFAR value.
* 2. Read the MMARVALID bit in the MMFSR.
* The MMFAR address is valid only if this bit is 1.
*
* Software must follow this sequence because another higher
* priority exception might change the MMFAR value.
*/
STORE_xFAR(mmfar, SCB->MMFAR);
if (SCB->CFSR & CFSR_MMARVALID_Msk) {
PR_EXC(" Address: 0x%x\n", (u32_t)SCB->MMFAR);
PR_EXC(" Address: 0x%x\n", mmfar);
if (fromHardFault) {
/* clear MMAR[VALID] to reset */
SCB->CFSR &= ~CFSR_MMARVALID_Msk;
@ -168,8 +191,18 @@ static void _BusFault(const NANO_ESF *esf, int fromHardFault)
PR_EXC(" Unstacking error\n");
} else if (SCB->CFSR & CFSR_PRECISERR_Msk) {
PR_EXC(" Precise data bus error\n");
/* In a fault handler, to determine the true faulting address:
* 1. Read and save the BFAR value.
* 2. Read the BFARVALID bit in the BFSR.
* The BFAR address is valid only if this bit is 1.
*
* Software must follow this sequence because another
* higher priority exception might change the BFAR value.
*/
STORE_xFAR(bfar, SCB->BFAR);
if (SCB->CFSR & CFSR_BFARVALID_Msk) {
PR_EXC(" Address: 0x%x\n", (u32_t)SCB->BFAR);
PR_EXC(" Address: 0x%x\n", bfar);
if (fromHardFault) {
/* clear CFSR_BFAR[VALID] to reset */
SCB->CFSR &= ~CFSR_BFARVALID_Msk;