|
21 | 21 | #ifdef CONFIG_PRINTK
|
22 | 22 | #include <misc/printk.h>
|
23 | 23 | #define PR_EXC(...) printk(__VA_ARGS__)
|
| 24 | +#define STORE_xFAR(reg_var, reg) u32_t reg_var = (u32_t)reg |
24 | 25 | #else
|
25 | 26 | #define PR_EXC(...)
|
| 27 | +#define STORE_xFAR(reg_var, reg) |
26 | 28 | #endif /* CONFIG_PRINTK */
|
27 | 29 |
|
28 | 30 | #if (CONFIG_FAULT_DUMP > 0)
|
@@ -73,15 +75,26 @@ void _FaultDump(const NANO_ESF *esf, int fault)
|
73 | 75 | PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
|
74 | 76 | SCB_MMFSR, SCB_BFSR, SCB_MMFSR);
|
75 | 77 |
|
| 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 | + |
76 | 89 | if (SCB->CFSR & CFSR_MMARVALID_Msk) {
|
77 |
| - PR_EXC("MMFAR: 0x%x\n", SCB->MMFAR); |
| 90 | + PR_EXC("MMFAR: 0x%x\n", mmfar); |
78 | 91 | if (escalation) {
|
79 | 92 | /* clear MMAR[VALID] to reset */
|
80 | 93 | SCB->CFSR &= ~CFSR_MMARVALID_Msk;
|
81 | 94 | }
|
82 | 95 | }
|
83 | 96 | if (SCB->CFSR & CFSR_BFARVALID_Msk) {
|
84 |
| - PR_EXC("BFAR: 0x%x\n", SCB->BFAR); |
| 97 | + PR_EXC("BFAR: 0x%x\n", bfar); |
85 | 98 | if (escalation) {
|
86 | 99 | /* clear CFSR_BFAR[VALID] to reset */
|
87 | 100 | SCB->CFSR &= ~CFSR_BFARVALID_Msk;
|
@@ -136,8 +149,18 @@ static void _MpuFault(const NANO_ESF *esf, int fromHardFault)
|
136 | 149 | PR_EXC(" Unstacking error\n");
|
137 | 150 | } else if (SCB->CFSR & CFSR_DACCVIOL_Msk) {
|
138 | 151 | 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 | + |
139 | 162 | 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); |
141 | 164 | if (fromHardFault) {
|
142 | 165 | /* clear MMAR[VALID] to reset */
|
143 | 166 | SCB->CFSR &= ~CFSR_MMARVALID_Msk;
|
@@ -168,8 +191,18 @@ static void _BusFault(const NANO_ESF *esf, int fromHardFault)
|
168 | 191 | PR_EXC(" Unstacking error\n");
|
169 | 192 | } else if (SCB->CFSR & CFSR_PRECISERR_Msk) {
|
170 | 193 | 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 | + |
171 | 204 | 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); |
173 | 206 | if (fromHardFault) {
|
174 | 207 | /* clear CFSR_BFAR[VALID] to reset */
|
175 | 208 | SCB->CFSR &= ~CFSR_BFARVALID_Msk;
|
|
0 commit comments