aboutsummaryrefslogtreecommitdiff
path: root/src/cortexm.c
diff options
context:
space:
mode:
authorGareth McMullin2012-07-05 22:08:01 +1200
committerGareth McMullin2012-07-05 22:08:01 +1200
commit234d54c5a5bb270738895eaf0f29ca92f4590206 (patch)
tree909ec158ecfca057ce408de4643c056e522bf1b4 /src/cortexm.c
parent0433d3d12a2c07c4685e5c42dc6c7e8420defe42 (diff)
Correct stepping over programmed breakpoints.
Fixes issue #2.
Diffstat (limited to 'src/cortexm.c')
-rw-r--r--src/cortexm.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/src/cortexm.c b/src/cortexm.c
index 03dbd7a..9b8b180 100644
--- a/src/cortexm.c
+++ b/src/cortexm.c
@@ -129,6 +129,7 @@ const struct command_s cortexm_cmd_list[] = {
#define CORTEXM_DHCSR_C_DEBUGEN (1 << 0)
/* Debug Core Register Selector Register (DCRSR) */
+#define CORTEXM_DCRSR_REGWnR 0x00010000
#define CORTEXM_DCRSR_REGSEL_MASK 0x0000001F
#define CORTEXM_DCRSR_REGSEL_XPSR 0x00000010
#define CORTEXM_DCRSR_REGSEL_MSP 0x00000011
@@ -205,6 +206,7 @@ static int cortexm_check_hw_wp(struct target_s *target, uint32_t *addr);
struct cortexm_priv {
bool stepping;
+ bool on_bkpt;
/* Watchpoint unit status */
struct wp_unit_s {
uint32_t addr;
@@ -500,16 +502,24 @@ cortexm_regs_write(struct target_s *target, const void *data)
return 0;
}
+static uint32_t
+cortexm_pc_read(struct target_s *target)
+{
+ ADIv5_AP_t *ap = adiv5_target_ap(target);
+
+ adiv5_ap_mem_write(ap, CORTEXM_DCRSR, 0x0F);
+ return adiv5_ap_mem_read(ap, CORTEXM_DCRDR);
+
+ return 0;
+}
+
static int
cortexm_pc_write(struct target_s *target, const uint32_t val)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
- adiv5_ap_write(ap, ADIV5_AP_CSW, 0xA2000052);
- adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_TAR, CORTEXM_DHCSR);
-
- adiv5_ap_write(ap, ADIV5_AP_DB(2), val); /* Required to switch banks */
- adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), 0x1000F);
+ adiv5_ap_mem_write(ap, CORTEXM_DCRDR, val);
+ adiv5_ap_mem_write(ap, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F);
return 0;
}
@@ -564,6 +574,8 @@ cortexm_halt_wait(struct target_s *target)
if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(target))
return SIGSEGV;
+ /* Remember if we stopped on a breakpoint */
+ priv->on_bkpt = dfsr & (CORTEXM_DFSR_BKPT);
if (dfsr & (CORTEXM_DFSR_BKPT | CORTEXM_DFSR_DWTTRAP))
return SIGTRAP;
@@ -589,6 +601,12 @@ cortexm_halt_resume(struct target_s *target, bool step)
priv->stepping = step;
}
+ if (priv->on_bkpt) {
+ uint32_t pc = cortexm_pc_read(target);
+ if ((adiv5_ap_mem_read_halfword(ap, pc) & 0xFF00) == 0xBE00)
+ cortexm_pc_write(target, pc + 2);
+ }
+
adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr);
}