X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m.c;h=4dc92c834e549395f91758a88d99d102c2444fd8;hp=dc8d344401abe7d83f0db75d7b379b4f45489f61;hb=2d998c09446a230b669f0ea9771dabf2dbea2fe8;hpb=c46dd490d1a26fee57ff1f32781175ad64b72e86 diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index dc8d344401..4dc92c834e 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -61,6 +61,7 @@ /* 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 target *target, uint32_t *value, int regnum) @@ -473,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) { @@ -521,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) { @@ -538,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; } @@ -1069,6 +1067,19 @@ static int cortex_m_assert_reset(struct target *target) "handler to reset any peripherals or configure hardware srst support."); } + /* + SAM4L needs to execute security initalization + startup sequence before AP access would be enabled. + During the intialization CDBGPWRUPACK is pulled low and we + need to wait for it to be set to 1 again. + */ + retval = dap_dp_poll_register(swjdp, DP_CTRL_STAT, + CDBGPWRUPACK, CDBGPWRUPACK, 100); + if (retval != ERROR_OK) { + LOG_ERROR("Failed waitnig for CDBGPWRUPACK"); + return ERROR_FAIL; + } + { /* I do not know why this is necessary, but it * fixes strange effects (step/resume cause NMI @@ -1252,6 +1263,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; @@ -1483,6 +1499,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: @@ -1546,6 +1585,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: @@ -1623,6 +1685,15 @@ 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); + 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. @@ -1631,14 +1702,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) @@ -1693,7 +1770,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; } @@ -1766,6 +1843,27 @@ 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; + + 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 @@ -1818,6 +1916,17 @@ 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); + 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); @@ -1832,6 +1941,7 @@ 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; + 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)); @@ -1850,6 +1960,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! */ @@ -1900,7 +2011,9 @@ static int cortex_m_target_request_data(struct target *target, uint32_t i; for (i = 0; i < (size * 4); i++) { - cortex_m_dcc_read(target, &data, &ctrl); + int retval = cortex_m_dcc_read(target, &data, &ctrl); + if (retval != ERROR_OK) + return retval; buffer[i] = data; } @@ -1919,8 +2032,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(target, &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)) { @@ -1928,12 +2044,12 @@ static int cortex_m_handle_target_request(void *priv) /* we assume target is quick enough */ request = data; - cortex_m_dcc_read(target, &data, &ctrl); - request |= (data << 8); - cortex_m_dcc_read(target, &data, &ctrl); - request |= (data << 16); - cortex_m_dcc_read(target, &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); } } @@ -2255,4 +2371,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, };