aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth McMullin2011-02-21 20:57:56 +1300
committerGareth McMullin2011-02-21 20:57:56 +1300
commit32cabac0f3f2113f04569e8c6201920e30ed8e73 (patch)
treea543db82fe2d0724c591bf3798ff5b390c60af40
parent0dfdc25bb27a6cf56f13a1f9a1c1b233d6aab107 (diff)
Stack is now unwound on hardfault.
-rw-r--r--src/cortexm3.c43
-rw-r--r--src/gdb_main.c9
-rw-r--r--src/include/target.h3
3 files changed, 52 insertions, 3 deletions
diff --git a/src/cortexm3.c b/src/cortexm3.c
index 4fd7fdb..0e34b99 100644
--- a/src/cortexm3.c
+++ b/src/cortexm3.c
@@ -51,6 +51,7 @@ static void cm3_reset(struct target_s *target);
static void ap_halt_resume(struct target_s *target, uint8_t step);
static int ap_halt_wait(struct target_s *target);
static void ap_halt_request(struct target_s *target);
+static int cm3_fault_unwind(struct target_s *target);
static int cm3_set_hw_bp(struct target_s *target, uint32_t addr);
static int cm3_clear_hw_bp(struct target_s *target, uint32_t addr);
@@ -88,6 +89,7 @@ cm3_probe(struct target_s *target)
target->halt_request = ap_halt_request;
target->halt_wait = ap_halt_wait;
target->halt_resume = ap_halt_resume;
+ target->fault_unwind = cm3_fault_unwind;
target->regs_size = 16<<2;
/* if not STM32 try LMI */
@@ -110,6 +112,9 @@ cm3_attach(struct target_s *target)
/* TRCENA | VC_CORERESET */
adiv5_ap_mem_write(t->ap, 0xE000EDFC, 0x01000401);
+ /* Reset DFSR flags */
+ adiv5_ap_mem_write(t->ap, 0xE000ED30UL, 0x1F);
+
/* Clear any stale breakpoints */
for(i = 0; i < 6; i++) {
adiv5_ap_mem_write(t->ap, 0xE0002008 + i*4, 0);
@@ -218,6 +223,12 @@ cm3_reset(struct target_s *target)
*/
adiv5_ap_mem_write(t->ap, 0xE000ED0C, 0x05FA0004);
adiv5_ap_mem_write(t->ap, 0xE000ED0C, 0x05FA0001);
+
+ /* FIXME: poll for release from reset! */
+ for(int i = 0; i < 10000; i++) asm("nop");
+
+ /* Reset DFSR flags */
+ adiv5_ap_mem_write(t->ap, 0xE000ED30UL, 0x1F);
}
static void
@@ -252,6 +263,38 @@ ap_halt_resume(struct target_s *target, uint8_t step)
adiv5_ap_mem_write(t->ap, 0xE000EDF0UL, step?0xA05F000DUL:0xA05F0001UL);
}
+static int cm3_fault_unwind(struct target_s *target)
+{
+ struct target_ap_s *t = (void *)target;
+ uint32_t dfsr = adiv5_ap_mem_read(t->ap, 0xE000ED30UL); //DFSR
+ //gdb_outf("DFSR = 0x%08X\n", dfsr);
+ adiv5_ap_mem_write(t->ap, 0xE000ED30UL, dfsr);/* write back to reset */
+ if(dfsr & (1 << 3)) { // VCATCH
+ /* Unwind exception */
+ uint32_t regs[16];
+ uint32_t stack[8];
+ /* Read registers for post-exception stack pointer */
+ ap_regs_read(target, regs);
+ gdb_outf("SP pre exception 0x%08X\n", regs[13]);
+ /* Read stack for pre-exception registers */
+ target_mem_read_words(target, stack, regs[13], 8 << 2);
+ regs[0] = stack[0];
+ regs[1] = stack[1];
+ regs[2] = stack[2];
+ regs[3] = stack[3];
+ regs[12] = stack[4];
+ regs[14] = stack[5];
+ regs[15] = stack[6];
+ gdb_outf("PC pre exception 0x%08X\n", regs[15]);
+ /* FIXME: stack[7] contains xPSR when this is supported */
+
+ /* Write pre-exception registers back to core */
+ ap_regs_write(target, regs);
+
+ return 1;
+ }
+ return 0;
+}
/* The following routines implement hardware breakpoints.
* The Flash Patch and Breakpoint (FPB) system is used. */
diff --git a/src/gdb_main.c b/src/gdb_main.c
index 7ff4745..dd96822 100644
--- a/src/gdb_main.c
+++ b/src/gdb_main.c
@@ -160,14 +160,17 @@ gdb_main(void)
SET_RUN_STATE(0);
/* Report reason for halt */
- if(target_check_hw_wp(cur_target, &watch_addr))
+ if(target_check_hw_wp(cur_target, &watch_addr)) {
/* Watchpoint hit */
gdb_putpacket_f("T05watch:%08X;", watch_addr);
- else if(sent_int)
+ } else if(target_fault_unwind(cur_target)) {
+ gdb_putpacketz("T0b");
+ } else if(sent_int) {
/* Target interrupted */
gdb_putpacketz("T02");
- else
+ } else {
gdb_putpacketz("T05");
+ }
break;
}
diff --git a/src/include/target.h b/src/include/target.h
index bd32c0f..aa20f39 100644
--- a/src/include/target.h
+++ b/src/include/target.h
@@ -77,6 +77,8 @@
#define target_halt_resume(target, step) \
(target)->halt_resume((target), (step))
+#define target_fault_unwind(target) \
+ ((target)->fault_unwind?(target)->fault_unwind((target)):0)
/* Break-/watchpoint functions */
#define target_set_hw_bp(target, addr) \
@@ -145,6 +147,7 @@ typedef struct target_s {
void (*halt_request)(struct target_s *target);
int (*halt_wait)(struct target_s *target);
void (*halt_resume)(struct target_s *target, uint8_t step);
+ int (*fault_unwind)(struct target_s *target);
/* Break-/watchpoint functions */
int (*set_hw_bp)(struct target_s *target, uint32_t addr);