Skip to content

Commit 571069e

Browse files
ioannisggalak
authored andcommitted
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 <[email protected]>
1 parent 83fa6c9 commit 571069e

File tree

1 file changed

+37
-4
lines changed

1 file changed

+37
-4
lines changed

arch/arm/core/fault.c

+37-4
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
#ifdef CONFIG_PRINTK
2222
#include <misc/printk.h>
2323
#define PR_EXC(...) printk(__VA_ARGS__)
24+
#define STORE_xFAR(reg_var, reg) u32_t reg_var = (u32_t)reg
2425
#else
2526
#define PR_EXC(...)
27+
#define STORE_xFAR(reg_var, reg)
2628
#endif /* CONFIG_PRINTK */
2729

2830
#if (CONFIG_FAULT_DUMP > 0)
@@ -73,15 +75,26 @@ void _FaultDump(const NANO_ESF *esf, int fault)
7375
PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
7476
SCB_MMFSR, SCB_BFSR, SCB_MMFSR);
7577

78+
/* In a fault handler, to determine the true faulting address:
79+
* 1. Read and save the MMFAR or BFAR value.
80+
* 2. Read the MMARVALID bit in the MMFSR, or the BFARVALID bit in the
81+
* BFSR. The MMFAR or BFAR address is valid only if this bit is 1.
82+
*
83+
* Software must follow this sequence because another higher priority
84+
* exception might change the MMFAR or BFAR value.
85+
*/
86+
STORE_xFAR(mmfar, SCB->MMFAR);
87+
STORE_xFAR(bfar, SCB->BFAR);
88+
7689
if (SCB->CFSR & CFSR_MMARVALID_Msk) {
77-
PR_EXC("MMFAR: 0x%x\n", SCB->MMFAR);
90+
PR_EXC("MMFAR: 0x%x\n", mmfar);
7891
if (escalation) {
7992
/* clear MMAR[VALID] to reset */
8093
SCB->CFSR &= ~CFSR_MMARVALID_Msk;
8194
}
8295
}
8396
if (SCB->CFSR & CFSR_BFARVALID_Msk) {
84-
PR_EXC("BFAR: 0x%x\n", SCB->BFAR);
97+
PR_EXC("BFAR: 0x%x\n", bfar);
8598
if (escalation) {
8699
/* clear CFSR_BFAR[VALID] to reset */
87100
SCB->CFSR &= ~CFSR_BFARVALID_Msk;
@@ -136,8 +149,18 @@ static void _MpuFault(const NANO_ESF *esf, int fromHardFault)
136149
PR_EXC(" Unstacking error\n");
137150
} else if (SCB->CFSR & CFSR_DACCVIOL_Msk) {
138151
PR_EXC(" Data Access Violation\n");
152+
/* In a fault handler, to determine the true faulting address:
153+
* 1. Read and save the MMFAR value.
154+
* 2. Read the MMARVALID bit in the MMFSR.
155+
* The MMFAR address is valid only if this bit is 1.
156+
*
157+
* Software must follow this sequence because another higher
158+
* priority exception might change the MMFAR value.
159+
*/
160+
STORE_xFAR(mmfar, SCB->MMFAR);
161+
139162
if (SCB->CFSR & CFSR_MMARVALID_Msk) {
140-
PR_EXC(" Address: 0x%x\n", (u32_t)SCB->MMFAR);
163+
PR_EXC(" Address: 0x%x\n", mmfar);
141164
if (fromHardFault) {
142165
/* clear MMAR[VALID] to reset */
143166
SCB->CFSR &= ~CFSR_MMARVALID_Msk;
@@ -168,8 +191,18 @@ static void _BusFault(const NANO_ESF *esf, int fromHardFault)
168191
PR_EXC(" Unstacking error\n");
169192
} else if (SCB->CFSR & CFSR_PRECISERR_Msk) {
170193
PR_EXC(" Precise data bus error\n");
194+
/* In a fault handler, to determine the true faulting address:
195+
* 1. Read and save the BFAR value.
196+
* 2. Read the BFARVALID bit in the BFSR.
197+
* The BFAR address is valid only if this bit is 1.
198+
*
199+
* Software must follow this sequence because another
200+
* higher priority exception might change the BFAR value.
201+
*/
202+
STORE_xFAR(bfar, SCB->BFAR);
203+
171204
if (SCB->CFSR & CFSR_BFARVALID_Msk) {
172-
PR_EXC(" Address: 0x%x\n", (u32_t)SCB->BFAR);
205+
PR_EXC(" Address: 0x%x\n", bfar);
173206
if (fromHardFault) {
174207
/* clear CFSR_BFAR[VALID] to reset */
175208
SCB->CFSR &= ~CFSR_BFARVALID_Msk;

0 commit comments

Comments
 (0)