X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m.c;h=88b226d85c8ad86e6167ad7a67a0fdb457b18b2f;hb=332023fb23aefb30d20b0d7f48d12ed9facdba40;hp=3b4629730f27d3535a4da800bcfd45c32f70f5a9;hpb=1c975fe30b8fb380907133462cc38a0b2e9de565;p=openocd.git diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 3b4629730f..88b226d85c 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -61,85 +61,72 @@ /* forward declarations */ static int cortex_m_store_core_reg_u32(struct target *target, uint32_t num, uint32_t value); +static void cortex_m_dwt_free(struct target *target); -static int cortexm_dap_read_coreregister_u32(struct adiv5_dap *swjdp, +static int cortexm_dap_read_coreregister_u32(struct target *target, uint32_t *value, int regnum) { + struct armv7m_common *armv7m = target_to_armv7m(target); + struct adiv5_dap *swjdp = armv7m->arm.dap; int retval; uint32_t dcrdr; /* because the DCB_DCRDR is used for the emulated dcc channel * we have to save/restore the DCB_DCRDR when used */ + if (target->dbg_msg_enabled) { + retval = mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr); + if (retval != ERROR_OK) + return retval; + } - retval = mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr); - if (retval != ERROR_OK) - return retval; - - /* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */ - retval = dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0); - if (retval != ERROR_OK) - return retval; - retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum); - if (retval != ERROR_OK) - return retval; - - /* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */ - retval = dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0); - if (retval != ERROR_OK) - return retval; - retval = dap_queue_ap_read(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value); + retval = mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); if (retval != ERROR_OK) return retval; - retval = dap_run(swjdp); + retval = mem_ap_read_atomic_u32(swjdp, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; - /* restore DCB_DCRDR - this needs to be in a seperate - * transaction otherwise the emulated DCC channel breaks */ - if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRDR, dcrdr); + if (target->dbg_msg_enabled) { + /* restore DCB_DCRDR - this needs to be in a separate + * transaction otherwise the emulated DCC channel breaks */ + if (retval == ERROR_OK) + retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRDR, dcrdr); + } return retval; } -static int cortexm_dap_write_coreregister_u32(struct adiv5_dap *swjdp, +static int cortexm_dap_write_coreregister_u32(struct target *target, uint32_t value, int regnum) { + struct armv7m_common *armv7m = target_to_armv7m(target); + struct adiv5_dap *swjdp = armv7m->arm.dap; int retval; uint32_t dcrdr; /* because the DCB_DCRDR is used for the emulated dcc channel * we have to save/restore the DCB_DCRDR when used */ + if (target->dbg_msg_enabled) { + retval = mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr); + if (retval != ERROR_OK) + return retval; + } - retval = mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr); - if (retval != ERROR_OK) - return retval; - - /* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */ - retval = dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0); - if (retval != ERROR_OK) - return retval; - retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value); - if (retval != ERROR_OK) - return retval; - - /* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */ - retval = dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0); - if (retval != ERROR_OK) - return retval; - retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR); + retval = mem_ap_write_u32(swjdp, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; - retval = dap_run(swjdp); + retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRSR, regnum | DCRSR_WnR); if (retval != ERROR_OK) return retval; - /* restore DCB_DCRDR - this needs to be in a seperate - * transaction otherwise the emulated DCC channel breaks */ - if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRDR, dcrdr); + if (target->dbg_msg_enabled) { + /* restore DCB_DCRDR - this needs to be in a seperate + * transaction otherwise the emulated DCC channel breaks */ + if (retval == ERROR_OK) + retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRDR, dcrdr); + } return retval; } @@ -214,6 +201,24 @@ static int cortex_m_single_step_core(struct target *target) return ERROR_OK; } +static int cortex_m_enable_fpb(struct target *target) +{ + int retval = target_write_u32(target, FP_CTRL, 3); + if (retval != ERROR_OK) + return retval; + + /* check the fpb is actually enabled */ + uint32_t fpctrl; + retval = target_read_u32(target, FP_CTRL, &fpctrl); + if (retval != ERROR_OK) + return retval; + + if (fpctrl & 1) + return ERROR_OK; + + return ERROR_FAIL; +} + static int cortex_m_endreset_event(struct target *target) { int i; @@ -265,9 +270,11 @@ static int cortex_m_endreset_event(struct target *target) */ /* Enable FPB */ - retval = target_write_u32(target, FP_CTRL, 3); - if (retval != ERROR_OK) + retval = cortex_m_enable_fpb(target); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to enable the FPB"); return retval; + } cortex_m->fpb_enabled = 1; @@ -467,7 +474,7 @@ static int cortex_m_debug_entry(struct target *target) LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s", arm_mode_name(arm->core_mode), - *(uint32_t *)(arm->pc->value), + buf_get_u32(arm->pc->value, 0, 32), target_state_name(target)); if (armv7m->post_debug_entry) { @@ -515,15 +522,8 @@ static int cortex_m_poll(struct target *target) } if (cortex_m->dcb_dhcsr & S_RESET_ST) { - /* check if still in reset */ - retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m->dcb_dhcsr); - if (retval != ERROR_OK) - return retval; - - if (cortex_m->dcb_dhcsr & S_RESET_ST) { - target->state = TARGET_RESET; - return ERROR_OK; - } + target->state = TARGET_RESET; + return ERROR_OK; } if (target->state == TARGET_RESET) { @@ -532,7 +532,11 @@ static int cortex_m_poll(struct target *target) */ LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32, cortex_m->dcb_dhcsr); - cortex_m_endreset_event(target); + retval = cortex_m_endreset_event(target); + if (retval != ERROR_OK) { + target->state = TARGET_UNKNOWN; + return retval; + } target->state = TARGET_RUNNING; prev_target_state = TARGET_RUNNING; } @@ -751,7 +755,7 @@ static int cortex_m_resume(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)", + LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")", breakpoint->address, breakpoint->unique_id); cortex_m_unset_breakpoint(target, breakpoint); @@ -1049,12 +1053,6 @@ static int cortex_m_assert_reset(struct target *target) * This has the disadvantage of not resetting the peripherals, so a * reset-init event handler is needed to perform any peripheral resets. */ - retval = mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, - AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ) - ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET)); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ) ? "SYSRESETREQ" : "VECTRESET"); @@ -1063,6 +1061,18 @@ static int cortex_m_assert_reset(struct target *target) "handler to reset any peripherals or configure hardware srst support."); } + retval = mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, + AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ) + ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET)); + if (retval != ERROR_OK) + LOG_DEBUG("Ignoring AP write error right after reset"); + + retval = ahbap_debugport_init(swjdp); + if (retval != ERROR_OK) { + LOG_ERROR("DP initialisation failed"); + return retval; + } + { /* I do not know why this is necessary, but it * fixes strange effects (step/resume cause NMI @@ -1097,6 +1107,17 @@ static int cortex_m_deassert_reset(struct target *target) /* deassert reset lines */ adapter_deassert_reset(); + enum reset_types jtag_reset_config = jtag_get_reset_config(); + + if ((jtag_reset_config & RESET_HAS_SRST) && + !(jtag_reset_config & RESET_SRST_NO_GATING)) { + int retval = ahbap_debugport_init(target_to_cm(target)->armv7m.arm.dap); + if (retval != ERROR_OK) { + LOG_ERROR("DP initialisation failed"); + return retval; + } + } + return ERROR_OK; } @@ -1104,12 +1125,11 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint { int retval; int fp_num = 0; - uint32_t hilo; struct cortex_m_common *cortex_m = target_to_cm(target); struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list; if (breakpoint->set) { - LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint->unique_id); + LOG_WARNING("breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id); return ERROR_OK; } @@ -1117,6 +1137,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address); if (breakpoint->type == BKPT_HARD) { + uint32_t fpcr_value; while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code)) fp_num++; if (fp_num >= cortex_m->fp_num_code) { @@ -1124,9 +1145,17 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint return ERROR_FAIL; } breakpoint->set = fp_num + 1; - hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; + fpcr_value = breakpoint->address | 1; + if (cortex_m->fp_rev == 0) { + uint32_t hilo; + hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; + fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1; + } else if (cortex_m->fp_rev > 1) { + LOG_ERROR("Unhandled Cortex-M Flash Patch Breakpoint architecture revision"); + return ERROR_FAIL; + } comparator_list[fp_num].used = 1; - comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1; + comparator_list[fp_num].fpcr_value = fpcr_value; target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value); LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32 "", @@ -1134,7 +1163,13 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint comparator_list[fp_num].fpcr_value); if (!cortex_m->fpb_enabled) { LOG_DEBUG("FPB wasn't enabled, do it now"); - target_write_u32(target, FP_CTRL, 3); + retval = cortex_m_enable_fpb(target); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to enable the FPB"); + return retval; + } + + cortex_m->fpb_enabled = 1; } } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; @@ -1159,7 +1194,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint breakpoint->set = true; } - LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", + LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, @@ -1180,7 +1215,7 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi return ERROR_OK; } - LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", + LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, @@ -1240,6 +1275,11 @@ int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } + if (breakpoint->length == 3) { + LOG_DEBUG("Using a two byte breakpoint for 32bit Thumb-2 request"); + breakpoint->length = 2; + } + if ((breakpoint->length != 2)) { LOG_INFO("only breakpoints of two bytes length supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -1454,8 +1494,6 @@ static int cortex_m_load_core_reg_u32(struct target *target, uint32_t num, uint32_t *value) { int retval; - struct armv7m_common *armv7m = target_to_armv7m(target); - struct adiv5_dap *swjdp = armv7m->arm.dap; /* NOTE: we "know" here that the register identifiers used * in the v7m header match the Cortex-M3 Debug Core Register @@ -1464,7 +1502,7 @@ static int cortex_m_load_core_reg_u32(struct target *target, switch (num) { case 0 ... 18: /* read a normal core register */ - retval = cortexm_dap_read_coreregister_u32(swjdp, value, num); + retval = cortexm_dap_read_coreregister_u32(target, value, num); if (retval != ERROR_OK) { LOG_ERROR("JTAG failure %i", retval); @@ -1473,6 +1511,29 @@ static int cortex_m_load_core_reg_u32(struct target *target, LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value); break; + case ARMV7M_FPSCR: + /* Floating-point Status and Registers */ + retval = target_write_u32(target, DCB_DCRSR, 0x21); + if (retval != ERROR_OK) + return retval; + retval = target_read_u32(target, DCB_DCRDR, value); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value); + break; + + case ARMV7M_S0 ... ARMV7M_S31: + /* Floating-point Status and Registers */ + retval = target_write_u32(target, DCB_DCRSR, num - ARMV7M_S0 + 0x40); + if (retval != ERROR_OK) + return retval; + retval = target_read_u32(target, DCB_DCRDR, value); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32, + (int)(num - ARMV7M_S0), *value); + break; + case ARMV7M_PRIMASK: case ARMV7M_BASEPRI: case ARMV7M_FAULTMASK: @@ -1481,7 +1542,7 @@ static int cortex_m_load_core_reg_u32(struct target *target, * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ - cortexm_dap_read_coreregister_u32(swjdp, value, 20); + cortexm_dap_read_coreregister_u32(target, value, 20); switch (num) { case ARMV7M_PRIMASK: @@ -1517,7 +1578,6 @@ static int cortex_m_store_core_reg_u32(struct target *target, int retval; uint32_t reg; struct armv7m_common *armv7m = target_to_armv7m(target); - struct adiv5_dap *swjdp = armv7m->arm.dap; /* NOTE: we "know" here that the register identifiers used * in the v7m header match the Cortex-M3 Debug Core Register @@ -1525,7 +1585,7 @@ static int cortex_m_store_core_reg_u32(struct target *target, */ switch (num) { case 0 ... 18: - retval = cortexm_dap_write_coreregister_u32(swjdp, value, num); + retval = cortexm_dap_write_coreregister_u32(target, value, num); if (retval != ERROR_OK) { struct reg *r; @@ -1537,6 +1597,29 @@ static int cortex_m_store_core_reg_u32(struct target *target, LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value); break; + case ARMV7M_FPSCR: + /* Floating-point Status and Registers */ + retval = target_write_u32(target, DCB_DCRDR, value); + if (retval != ERROR_OK) + return retval; + retval = target_write_u32(target, DCB_DCRSR, 0x21 | (1<<16)); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("write FPSCR value 0x%" PRIx32, value); + break; + + case ARMV7M_S0 ... ARMV7M_S31: + /* Floating-point Status and Registers */ + retval = target_write_u32(target, DCB_DCRDR, value); + if (retval != ERROR_OK) + return retval; + retval = target_write_u32(target, DCB_DCRSR, (num - ARMV7M_S0 + 0x40) | (1<<16)); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32, + (int)(num - ARMV7M_S0), value); + break; + case ARMV7M_PRIMASK: case ARMV7M_BASEPRI: case ARMV7M_FAULTMASK: @@ -1545,7 +1628,7 @@ static int cortex_m_store_core_reg_u32(struct target *target, * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ - cortexm_dap_read_coreregister_u32(swjdp, ®, 20); + cortexm_dap_read_coreregister_u32(target, ®, 20); switch (num) { case ARMV7M_PRIMASK: @@ -1565,7 +1648,7 @@ static int cortex_m_store_core_reg_u32(struct target *target, break; } - cortexm_dap_write_coreregister_u32(swjdp, reg, 20); + cortexm_dap_write_coreregister_u32(target, reg, 20); LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value); break; @@ -1614,6 +1697,18 @@ static int cortex_m_init_target(struct command_context *cmd_ctx, return ERROR_OK; } +void cortex_m_deinit_target(struct target *target) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + + free(cortex_m->fp_comparator_list); + + cortex_m_dwt_free(target); + armv7m_free_reg_cache(target); + + free(cortex_m); +} + /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid" * on r/w if the core is not running, and clear on resume or reset ... or * at least, in a post_restore_context() method. @@ -1622,14 +1717,20 @@ static int cortex_m_init_target(struct command_context *cmd_ctx, struct dwt_reg_state { struct target *target; uint32_t addr; - uint32_t value; /* scratch/cache */ + uint8_t value[4]; /* scratch/cache */ }; static int cortex_m_dwt_get_reg(struct reg *reg) { struct dwt_reg_state *state = reg->arch_info; - return target_read_u32(state->target, state->addr, &state->value); + uint32_t tmp; + int retval = target_read_u32(state->target, state->addr, &tmp); + if (retval != ERROR_OK) + return retval; + + buf_set_u32(state->value, 0, 32, tmp); + return ERROR_OK; } static int cortex_m_dwt_set_reg(struct reg *reg, uint8_t *buf) @@ -1684,7 +1785,7 @@ static void cortex_m_dwt_addreg(struct target *t, struct reg *r, struct dwt_reg r->name = d->name; r->size = d->size; - r->value = &state->value; + r->value = state->value; r->arch_info = state; r->type = &dwt_reg_type; } @@ -1719,7 +1820,7 @@ fail1: free(cm->dwt_comparator_list); goto fail0; } - cache->name = "cortex-m3 dwt registers"; + cache->name = "Cortex-M DWT registers"; cache->num_regs = 2 + cm->dwt_num_comp * 3; cache->reg_list = calloc(cache->num_regs, sizeof *cache->reg_list); if (!cache->reg_list) { @@ -1757,6 +1858,28 @@ fail1: */ } +static void cortex_m_dwt_free(struct target *target) +{ + struct cortex_m_common *cm = target_to_cm(target); + struct reg_cache *cache = cm->dwt_cache; + + free(cm->dwt_comparator_list); + cm->dwt_comparator_list = NULL; + cm->dwt_num_comp = 0; + + if (cache) { + register_unlink_cache(&target->reg_cache, cache); + + if (cache->reg_list) { + for (size_t i = 0; i < cache->num_regs; i++) + free(cache->reg_list[i].arch_info); + free(cache->reg_list); + } + free(cache); + } + cm->dwt_cache = NULL; +} + #define MVFR0 0xe000ef40 #define MVFR1 0xe000ef44 @@ -1809,11 +1932,36 @@ int cortex_m_examine(struct target *target) armv7m->arm.is_armv6m = true; } + if (armv7m->fp_feature != FPv4_SP && + armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) { + /* free unavailable FPU registers */ + size_t idx; + + for (idx = ARMV7M_NUM_CORE_REGS_NOFP; + idx < armv7m->arm.core_cache->num_regs; + idx++) { + free(armv7m->arm.core_cache->reg_list[idx].value); + free(armv7m->arm.core_cache->reg_list[idx].feature); + free(armv7m->arm.core_cache->reg_list[idx].reg_data_type); + } + armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP; + } + if (i == 4 || i == 3) { /* Cortex-M3/M4 has 4096 bytes autoincrement range */ armv7m->dap.tar_autoincr_block = (1 << 12); } + /* Configure trace modules */ + retval = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr); + if (retval != ERROR_OK) + return retval; + + if (armv7m->trace_config.config_type != DISABLED) { + armv7m_trace_tpiu_config(target); + armv7m_trace_itm_config(target); + } + /* NOTE: FPB and DWT are both optional. */ /* Setup FPB */ @@ -1823,6 +1971,10 @@ int cortex_m_examine(struct target *target) cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF); cortex_m->fp_num_lit = (fpcr >> 8) & 0xF; cortex_m->fp_code_available = cortex_m->fp_num_code; + /* Detect flash patch revision, see RM DDI 0403E.b page C1-817. + Revision is zero base, fp_rev == 1 means Rev.2 ! */ + cortex_m->fp_rev = (fpcr >> 28) & 0xf; + free(cortex_m->fp_comparator_list); cortex_m->fp_comparator_list = calloc( cortex_m->fp_num_code + cortex_m->fp_num_lit, sizeof(struct cortex_m_fp_comparator)); @@ -1841,6 +1993,7 @@ int cortex_m_examine(struct target *target) cortex_m->fp_num_lit); /* Setup DWT */ + cortex_m_dwt_free(target); cortex_m_dwt_setup(cortex_m, target); /* These hardware breakpoints only work for code in flash! */ @@ -1853,12 +2006,19 @@ int cortex_m_examine(struct target *target) return ERROR_OK; } -static int cortex_m_dcc_read(struct adiv5_dap *swjdp, uint8_t *value, uint8_t *ctrl) +static int cortex_m_dcc_read(struct target *target, uint8_t *value, uint8_t *ctrl) { + struct armv7m_common *armv7m = target_to_armv7m(target); + struct adiv5_dap *swjdp = armv7m->arm.dap; uint16_t dcrdr; + uint8_t buf[2]; int retval; - mem_ap_read_buf_u16(swjdp, (uint8_t *)&dcrdr, 2, DCB_DCRDR); + retval = mem_ap_read(swjdp, buf, 2, 1, DCB_DCRDR, false); + if (retval != ERROR_OK) + return retval; + + dcrdr = target_buffer_get_u16(target, buf); *ctrl = (uint8_t)dcrdr; *value = (uint8_t)(dcrdr >> 8); @@ -1867,8 +2027,8 @@ static int cortex_m_dcc_read(struct adiv5_dap *swjdp, uint8_t *value, uint8_t *c /* write ack back to software dcc register * signify we have read data */ if (dcrdr & (1 << 0)) { - dcrdr = 0; - retval = mem_ap_write_buf_u16(swjdp, (uint8_t *)&dcrdr, 2, DCB_DCRDR); + target_buffer_set_u16(target, buf, 0); + retval = mem_ap_write(swjdp, buf, 2, 1, DCB_DCRDR, false); if (retval != ERROR_OK) return retval; } @@ -1879,14 +2039,14 @@ static int cortex_m_dcc_read(struct adiv5_dap *swjdp, uint8_t *value, uint8_t *c static int cortex_m_target_request_data(struct target *target, uint32_t size, uint8_t *buffer) { - struct armv7m_common *armv7m = target_to_armv7m(target); - struct adiv5_dap *swjdp = armv7m->arm.dap; uint8_t data; uint8_t ctrl; uint32_t i; for (i = 0; i < (size * 4); i++) { - cortex_m_dcc_read(swjdp, &data, &ctrl); + int retval = cortex_m_dcc_read(target, &data, &ctrl); + if (retval != ERROR_OK) + return retval; buffer[i] = data; } @@ -1898,8 +2058,6 @@ static int cortex_m_handle_target_request(void *priv) struct target *target = priv; if (!target_was_examined(target)) return ERROR_OK; - struct armv7m_common *armv7m = target_to_armv7m(target); - struct adiv5_dap *swjdp = armv7m->arm.dap; if (!target->dbg_msg_enabled) return ERROR_OK; @@ -1907,8 +2065,11 @@ static int cortex_m_handle_target_request(void *priv) if (target->state == TARGET_RUNNING) { uint8_t data; uint8_t ctrl; + int retval; - cortex_m_dcc_read(swjdp, &data, &ctrl); + retval = cortex_m_dcc_read(target, &data, &ctrl); + if (retval != ERROR_OK) + return retval; /* check if we have data */ if (ctrl & (1 << 0)) { @@ -1916,12 +2077,12 @@ static int cortex_m_handle_target_request(void *priv) /* we assume target is quick enough */ request = data; - cortex_m_dcc_read(swjdp, &data, &ctrl); - request |= (data << 8); - cortex_m_dcc_read(swjdp, &data, &ctrl); - request |= (data << 16); - cortex_m_dcc_read(swjdp, &data, &ctrl); - request |= (data << 24); + for (int i = 1; i <= 3; i++) { + retval = cortex_m_dcc_read(target, &data, &ctrl); + if (retval != ERROR_OK) + return retval; + request |= ((uint32_t)data << (i * 8)); + } target_request(target, request); } } @@ -2196,6 +2357,9 @@ static const struct command_registration cortex_m_command_handlers[] = { { .chain = armv7m_command_handlers, }, + { + .chain = armv7m_trace_command_handlers, + }, { .name = "cortex_m", .mode = COMMAND_EXEC, @@ -2243,4 +2407,5 @@ struct target_type cortexm_target = { .target_create = cortex_m_target_create, .init_target = cortex_m_init_target, .examine = cortex_m_examine, + .deinit_target = cortex_m_deinit_target, };