X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m.c;h=316089c3513a1359c1e2d8a45452968960b60a96;hb=7b641d3d4e9b0407e5410267459fcbc64f075fde;hp=08b3661ea0876dc4443e9bd3d7180ab5aa34b326;hpb=9d50f3f3afe1df4457602407c46fc158e7f8f64f;p=openocd.git diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 08b3661ea0..316089c351 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -39,6 +39,7 @@ #include "arm_opcodes.h" #include "arm_semihosting.h" #include +#include /* NOTE: most of this should work fine for the Cortex-M1 and * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M. @@ -56,8 +57,8 @@ 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) +static int cortex_m_load_core_reg_u32(struct target *target, + uint32_t regsel, uint32_t *value) { struct armv7m_common *armv7m = target_to_armv7m(target); int retval; @@ -71,7 +72,7 @@ static int cortexm_dap_read_coreregister_u32(struct target *target, return retval; } - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regnum); + retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regsel); if (retval != ERROR_OK) return retval; @@ -89,8 +90,8 @@ static int cortexm_dap_read_coreregister_u32(struct target *target, return retval; } -static int cortexm_dap_write_coreregister_u32(struct target *target, - uint32_t value, int regnum) +static int cortex_m_store_core_reg_u32(struct target *target, + uint32_t regsel, uint32_t value) { struct armv7m_common *armv7m = target_to_armv7m(target); int retval; @@ -108,7 +109,7 @@ static int cortexm_dap_write_coreregister_u32(struct target *target, if (retval != ERROR_OK) return retval; - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regnum | DCRSR_WnR); + retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regsel | DCRSR_WnR); if (retval != ERROR_OK) return retval; @@ -527,12 +528,6 @@ static int cortex_m_debug_entry(struct target *target) r = arm->cpsr; xPSR = buf_get_u32(r->value, 0, 32); - /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */ - if (xPSR & 0xf00) { - r->dirty = r->valid; - cortex_m_store_core_reg_u32(target, 16, xPSR & ~0xff); - } - /* Are we in an exception handler */ if (xPSR & 0x1FF) { armv7m->exception_number = (xPSR & 0x1FF); @@ -656,13 +651,9 @@ static int cortex_m_poll(struct target *target) } } - /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state. - * How best to model low power modes? - */ - if (target->state == TARGET_UNKNOWN) { - /* check if processor is retiring instructions */ - if (cortex_m->dcb_dhcsr & S_RETIRE_ST) { + /* check if processor is retiring instructions or sleeping */ + if (cortex_m->dcb_dhcsr & S_RETIRE_ST || cortex_m->dcb_dhcsr & S_SLEEP) { target->state = TARGET_RUNNING; retval = ERROR_OK; } @@ -827,15 +818,19 @@ static int cortex_m_resume(struct target *target, int current, * in parallel with disabled interrupts can cause local faults * to not be taken. * - * REVISIT this clearly breaks non-debug execution, since the - * PRIMASK register state isn't saved/restored... workaround - * by never resuming app code after debug execution. + * This breaks non-debug (application) execution if not + * called from armv7m_start_algorithm() which saves registers. */ buf_set_u32(r->value, 0, 1, 1); r->dirty = true; r->valid = true; - /* Make sure we are in Thumb mode */ + /* Make sure we are in Thumb mode, set xPSR.T bit */ + /* armv7m_start_algorithm() initializes entire xPSR register. + * This duplicity handles the case when cortex_m_resume() + * is used with the debug_execution flag directly, + * not called through armv7m_start_algorithm(). + */ r = armv7m->arm.cpsr; buf_set_u32(r->value, 24, 1, 1); r->dirty = true; @@ -1208,11 +1203,13 @@ static int cortex_m_assert_reset(struct target *target) if (retval3 != ERROR_OK) LOG_DEBUG("Ignoring AP write error right after reset"); - retval3 = dap_dp_init(armv7m->debug_ap->dap); - if (retval3 != ERROR_OK) + retval3 = dap_dp_init_or_reconnect(armv7m->debug_ap->dap); + if (retval3 != ERROR_OK) { LOG_ERROR("DP initialisation failed"); - - else { + /* The error return value must not be propagated in this case. + * SYSRESETREQ or VECTRESET have been possibly triggered + * so reset processing should continue */ + } else { /* I do not know why this is necessary, but it * fixes strange effects (step/resume cause NMI * after reset) on LM3S6918 -- Michael Schwingen @@ -1255,7 +1252,8 @@ static int cortex_m_deassert_reset(struct target *target) if ((jtag_reset_config & RESET_HAS_SRST) && !(jtag_reset_config & RESET_SRST_NO_GATING) && target_was_examined(target)) { - int retval = dap_dp_init(armv7m->debug_ap->dap); + + int retval = dap_dp_init_or_reconnect(armv7m->debug_ap->dap); if (retval != ERROR_OK) { LOG_ERROR("DP initialisation failed"); return retval; @@ -1610,176 +1608,6 @@ void cortex_m_enable_watchpoints(struct target *target) } } -static int cortex_m_load_core_reg_u32(struct target *target, - uint32_t num, uint32_t *value) -{ - int retval; - - /* NOTE: we "know" here that the register identifiers used - * in the v7m header match the Cortex-M3 Debug Core Register - * Selector values for R0..R15, xPSR, MSP, and PSP. - */ - switch (num) { - case 0 ... 18: - /* read a normal core register */ - retval = cortexm_dap_read_coreregister_u32(target, value, num); - - if (retval != ERROR_OK) { - LOG_ERROR("JTAG failure %i", retval); - return ERROR_JTAG_DEVICE_ERROR; - } - 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: - case ARMV7M_CONTROL: - /* Cortex-M3 packages these four registers as bitfields - * 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(target, value, 20); - - switch (num) { - case ARMV7M_PRIMASK: - *value = buf_get_u32((uint8_t *)value, 0, 1); - break; - - case ARMV7M_BASEPRI: - *value = buf_get_u32((uint8_t *)value, 8, 8); - break; - - case ARMV7M_FAULTMASK: - *value = buf_get_u32((uint8_t *)value, 16, 1); - break; - - case ARMV7M_CONTROL: - *value = buf_get_u32((uint8_t *)value, 24, 3); - break; - } - - LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value); - break; - - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; -} - -static int cortex_m_store_core_reg_u32(struct target *target, - uint32_t num, uint32_t value) -{ - int retval; - uint32_t reg; - struct armv7m_common *armv7m = target_to_armv7m(target); - - /* NOTE: we "know" here that the register identifiers used - * in the v7m header match the Cortex-M3 Debug Core Register - * Selector values for R0..R15, xPSR, MSP, and PSP. - */ - switch (num) { - case 0 ... 18: - retval = cortexm_dap_write_coreregister_u32(target, value, num); - if (retval != ERROR_OK) { - struct reg *r; - - LOG_ERROR("JTAG failure"); - r = armv7m->arm.core_cache->reg_list + num; - r->dirty = r->valid; - return ERROR_JTAG_DEVICE_ERROR; - } - 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: - case ARMV7M_CONTROL: - /* Cortex-M3 packages these four registers as bitfields - * 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(target, ®, 20); - - switch (num) { - case ARMV7M_PRIMASK: - buf_set_u32((uint8_t *)®, 0, 1, value); - break; - - case ARMV7M_BASEPRI: - buf_set_u32((uint8_t *)®, 8, 8, value); - break; - - case ARMV7M_FAULTMASK: - buf_set_u32((uint8_t *)®, 16, 1, value); - break; - - case ARMV7M_CONTROL: - buf_set_u32((uint8_t *)®, 24, 3, value); - break; - } - - cortexm_dap_write_coreregister_u32(target, reg, 20); - - LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value); - break; - - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; -} - static int cortex_m_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { @@ -2218,7 +2046,6 @@ int cortex_m_examine(struct target *target) 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); } @@ -2663,6 +2490,9 @@ static const struct command_registration cortex_m_command_handlers[] = { .usage = "", .chain = cortex_m_exec_command_handlers, }, + { + .chain = rtt_target_command_handlers, + }, COMMAND_REGISTRATION_DONE };