mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-01 04:43:50 +00:00
Add an option to report panic fault information
The fault status registers sometimes have useful information, so provide an option to display these. This adds about 1KB to the code size. BUG=chrome-os-partner:10146 TEST=manual: build for all boards On snow, cause a panic and see that it is reported correctly. === EXCEPTION: 03 ====== xPSR: 01000000 =========== r0 :0000000b r1 :00000047 r2 :60000000 r3 :200013dd r4 :00000000 r5 :080053f4 r6 :200013d0 r7 :00000002 r8 :00000000 r9 :200013de r10:00000000 r11:00000000 r12:00000000 sp :200009a0 lr :08002b85 pc :08003a8a Precise data bus error, Forced hard fault, Vector catch, bfar = 60000000 mmfs = 00008200, shcsr = 00000000, hfsr = 40000000, dfsr = 00000008 Change-Id: I1a18c85ee63760502c92b300f5a87e57468469a5 Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/24505 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
15
README
15
README
@@ -39,3 +39,18 @@ Build Options
|
||||
When reporting a panic, change to a completely new stack. This might
|
||||
help get a useful trace out a situation where the stack or stack
|
||||
pointer has been corrupted.
|
||||
|
||||
- CONFIG_PANIC_HELP
|
||||
|
||||
Report extra information about a panic, such as the fault address,
|
||||
here shown as bfar. This shows the reason for the fault and may help
|
||||
to determine the cause.
|
||||
|
||||
=== EXCEPTION: 03 ====== xPSR: 01000000 ===========
|
||||
r0 :0000000b r1 :00000047 r2 :60000000 r3 :200013dd
|
||||
r4 :00000000 r5 :080053f4 r6 :200013d0 r7 :00000002
|
||||
r8 :00000000 r9 :200013de r10:00000000 r11:00000000
|
||||
r12:00000000 sp :200009a0 lr :08002b85 pc :08003a8a
|
||||
Precise data bus error, Forced hard fault, Vector catch, bfar = 60000000
|
||||
mmfs = 00008200, shcsr = 00000000, hfsr = 40000000, dfsr = 00000008
|
||||
|
||||
|
||||
@@ -23,4 +23,24 @@
|
||||
|
||||
#define CPU_SCB_SYSCTRL CPUREG(0xe000ed10)
|
||||
|
||||
#define CPU_NVIC_CCR CPUREG(0xe000ed14)
|
||||
#define CPU_NVIC_SHCSR CPUREG(0xe000ed24)
|
||||
#define CPU_NVIC_MMFS CPUREG(0xe000ed28)
|
||||
#define CPU_NVIC_HFSR CPUREG(0xe000ed2c)
|
||||
#define CPU_NVIC_DFSR CPUREG(0xe000ed30)
|
||||
#define CPU_NVIC_MFAR CPUREG(0xe000ed34)
|
||||
#define CPU_NVIC_BFAR CPUREG(0xe000ed38)
|
||||
|
||||
enum {
|
||||
CPU_NVIC_MMFS_BFARVALID = 1 << 15,
|
||||
CPU_NVIC_MMFS_MFARVALID = 1 << 7,
|
||||
|
||||
CPU_NVIC_CCR_DIV_0_TRAP = 1 << 4,
|
||||
CPU_NVIC_CCR_UNALIGN_TRAP = 1 << 3,
|
||||
|
||||
CPU_NVIC_HFSR_DEBUGEVT = 1UL << 31,
|
||||
CPU_NVIC_HFSR_FORCED = 1 << 30,
|
||||
CPU_NVIC_HFSR_VECTTBL = 1 << 1,
|
||||
};
|
||||
|
||||
#endif /* __CPU_H */
|
||||
|
||||
@@ -150,6 +150,141 @@ static void print_reg(int regnum, uint32_t *regs, int index)
|
||||
panic_putc((regnum & 3) == 3 ? '\n' : ' ');
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PANIC_HELP
|
||||
/* Names for each of the bits in the mmfs register, starting at bit 0 */
|
||||
static const char * const mmfs_name[32] = {
|
||||
"Instruction access violation",
|
||||
"Data access violation",
|
||||
NULL,
|
||||
"Unstack from exception violation",
|
||||
"Stack from exception violation",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
"Instruction bus error",
|
||||
"Precise data bus error",
|
||||
"Imprecise data bus error",
|
||||
"Unstack from exception bus fault",
|
||||
"Stack from exception bus fault",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
"Undefined instructions",
|
||||
"Invalid state",
|
||||
"Invalid PC",
|
||||
"No coprocessor",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
"Unaligned",
|
||||
"Divide by 0",
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
/* Names for the first 5 bits in the DFSR */
|
||||
static const char * const dfsr_name[] = {
|
||||
"Halt request",
|
||||
"Breakpoint",
|
||||
"Data watchpoint/trace",
|
||||
"Vector catch",
|
||||
"External debug request",
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to display a separator after the previous item
|
||||
*
|
||||
* If items have been displayed already, we display a comma separator.
|
||||
* In any case, the count of items displayed is incremeneted.
|
||||
*
|
||||
* @param count Number of items displayed so far (0 for none)
|
||||
*/
|
||||
static void do_separate(int *count)
|
||||
{
|
||||
if (*count)
|
||||
panic_puts(", ");
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show a textual representaton of the fault registers
|
||||
*
|
||||
* A list of detected faults is shown, with no trailing newline.
|
||||
*
|
||||
* @param mmfs Value of Memory Manage Fault Status
|
||||
* @param hfsr Value of Hard Fault Status
|
||||
* @param dfsr Value of Debug Fault Status
|
||||
*/
|
||||
static void show_fault(uint32_t mmfs, uint32_t hfsr, uint32_t dfsr)
|
||||
{
|
||||
unsigned int upto;
|
||||
int count = 0;
|
||||
|
||||
for (upto = 0; upto < 32; upto++) {
|
||||
if ((mmfs & (1 << upto)) && mmfs_name[upto]) {
|
||||
do_separate(&count);
|
||||
panic_puts(mmfs_name[upto]);
|
||||
}
|
||||
}
|
||||
|
||||
if (hfsr & CPU_NVIC_HFSR_DEBUGEVT) {
|
||||
do_separate(&count);
|
||||
panic_puts("Debug event");
|
||||
}
|
||||
if (hfsr & CPU_NVIC_HFSR_FORCED) {
|
||||
do_separate(&count);
|
||||
panic_puts("Forced hard fault");
|
||||
}
|
||||
if (hfsr & CPU_NVIC_HFSR_VECTTBL) {
|
||||
do_separate(&count);
|
||||
panic_puts("Vector table bus fault");
|
||||
}
|
||||
|
||||
for (upto = 0; upto < 5; upto++) {
|
||||
if ((dfsr & (1 << upto))) {
|
||||
do_separate(&count);
|
||||
panic_puts(dfsr_name[upto]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show extra information that might be useful to understand a panic()
|
||||
*
|
||||
* We show fault register information, including the fault address registers
|
||||
* if valid.
|
||||
*/
|
||||
static void panic_show_extra(void)
|
||||
{
|
||||
uint32_t mmfs;
|
||||
|
||||
mmfs = CPU_NVIC_MMFS;
|
||||
show_fault(mmfs, CPU_NVIC_HFSR, CPU_NVIC_DFSR);
|
||||
if (mmfs & CPU_NVIC_MMFS_BFARVALID)
|
||||
panic_printf(", bfar = %x", CPU_NVIC_BFAR);
|
||||
if (mmfs & CPU_NVIC_MMFS_MFARVALID)
|
||||
panic_printf(", mfar = %x", CPU_NVIC_MFAR);
|
||||
panic_putc('\n');
|
||||
panic_printf("mmfs = %x, ", mmfs);
|
||||
panic_printf("shcsr = %x, ", CPU_NVIC_SHCSR);
|
||||
panic_printf("hfsr = %x, ", CPU_NVIC_HFSR);
|
||||
panic_printf("dfsr = %x", CPU_NVIC_DFSR);
|
||||
}
|
||||
#endif /* CONFIG_PANIC_HELP */
|
||||
|
||||
|
||||
/**
|
||||
* Display a message and reboot
|
||||
@@ -186,6 +321,9 @@ void report_panic(const char *msg, uint32_t *lregs)
|
||||
print_reg(13, &psp, 0);
|
||||
print_reg(14, sregs, 5);
|
||||
print_reg(15, sregs, 6);
|
||||
#ifdef CONFIG_PANIC_HELP
|
||||
panic_show_extra();
|
||||
#endif
|
||||
}
|
||||
|
||||
panic_reboot();
|
||||
|
||||
Reference in New Issue
Block a user