summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2012-06-03 10:16:07 -0700
committerGerrit <chrome-bot@google.com>2012-06-19 18:45:27 -0700
commit004c607a96d650f9f6ac0891b32a458253c080dc (patch)
tree909564e861f3a0dbcb99e07d23005adce827d33a /core
parentebf79b00a9f77c7d4bb8b0acb633380937593f91 (diff)
downloadchrome-ec-004c607a96d650f9f6ac0891b32a458253c080dc.tar.gz
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>
Diffstat (limited to 'core')
-rw-r--r--core/cortex-m/cpu.h20
-rw-r--r--core/cortex-m/panic.c138
2 files changed, 158 insertions, 0 deletions
diff --git a/core/cortex-m/cpu.h b/core/cortex-m/cpu.h
index 7e032164a7..2e75d6c1c5 100644
--- a/core/cortex-m/cpu.h
+++ b/core/cortex-m/cpu.h
@@ -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 */
diff --git a/core/cortex-m/panic.c b/core/cortex-m/panic.c
index 8e022857ef..d249974b06 100644
--- a/core/cortex-m/panic.c
+++ b/core/cortex-m/panic.c
@@ -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();