X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m.c;h=89d70beceb7769b604825bf39399c84fdc3c877c;hp=5fa78ca8c3ce6bc450e8781928527d08bb61d258;hb=fc2abe63fd3cea7497da7be2955d333bd3f800b9;hpb=2aab7d3ce2b53200ed01eeedb8348fa4b977bed3 diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 5fa78ca8c3..89d70beceb 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -451,18 +451,16 @@ static int cortex_m3_debug_entry(struct target *target) /* Are we in an exception handler */ if (xPSR & 0x1FF) { - armv7m->core_mode = ARMV7M_MODE_HANDLER; armv7m->exception_number = (xPSR & 0x1FF); arm->core_mode = ARM_MODE_HANDLER; arm->map = armv7m_msp_reg_map; } else { - unsigned control = buf_get_u32(armv7m->core_cache + unsigned control = buf_get_u32(arm->core_cache ->reg_list[ARMV7M_CONTROL].value, 0, 2); /* is this thread privileged? */ - armv7m->core_mode = control & 1; - arm->core_mode = armv7m->core_mode + arm->core_mode = control & 1 ? ARM_MODE_USER_THREAD : ARM_MODE_THREAD; @@ -479,7 +477,7 @@ static int cortex_m3_debug_entry(struct target *target) cortex_m3_examine_exception_reason(target); LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s", - armv7m_mode_strings[armv7m->core_mode], + arm_mode_name(arm->core_mode), *(uint32_t *)(arm->pc->value), target_state_name(target)); @@ -677,7 +675,7 @@ static int cortex_m3_soft_reset_halt(struct target *target) return ERROR_OK; } -static void cortex_m3_enable_breakpoints(struct target *target) +void cortex_m3_enable_breakpoints(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; @@ -854,45 +852,78 @@ static int cortex_m3_step(struct target *target, int current, * */ - /* Set a temporary break point */ - retval = breakpoint_add(target, pc_value, 2, BKPT_TYPE_BY_ADDR(pc_value)); - bool tmp_bp_set = (retval == ERROR_OK); - - /* No more breakpoints left, just do a step */ - if (!tmp_bp_set) + /* 2012-09-29 ph + * + * If a break point is already set on the lower half word then a break point on + * the upper half word will not break again when the core is restarted. So we + * just step over the instruction with interrupts disabled. + * + * The documentation has no information about this, it was found by observation + * on STM32F1 and STM32F2. Proper explanation welcome. STM32F0 dosen't seem to + * suffer from this problem. + * + * To add some confusion: pc_value has bit 0 always set, while the breakpoint + * address has it always cleared. The former is done to indicate thumb mode + * to gdb. + * + */ + if ((pc_value & 0x02) && breakpoint_find(target, pc_value & ~0x03)) { + LOG_DEBUG("Stepping over next instruction with interrupts disabled"); + cortex_m3_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0); cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT); + /* Re-enable interrupts */ + cortex_m3_write_debug_halt_mask(target, C_HALT, C_MASKINTS); + } else { - /* Start the core */ - LOG_DEBUG("Starting core to serve pending interrupts"); - int64_t t_start = timeval_ms(); - cortex_m3_write_debug_halt_mask(target, 0, C_HALT | C_STEP); - - /* Wait for pending handlers to complete or timeout */ - do { - retval = mem_ap_read_atomic_u32(swjdp, - DCB_DHCSR, - &cortex_m3->dcb_dhcsr); - if (retval != ERROR_OK) { - target->state = TARGET_UNKNOWN; - return retval; - } - isr_timed_out = ((timeval_ms() - t_start) > 500); - } while (!((cortex_m3->dcb_dhcsr & S_HALT) || isr_timed_out)); - - /* Remove the temporary breakpoint */ - breakpoint_remove(target, pc_value); - - if (isr_timed_out) { - LOG_DEBUG("Interrupt handlers didn't complete within time, " - "leaving target running"); - } else { - /* Step over next instruction with interrupts disabled */ - cortex_m3_write_debug_halt_mask(target, - C_HALT | C_MASKINTS, - 0); + + /* Set a temporary break point */ + if (breakpoint) + retval = cortex_m3_set_breakpoint(target, breakpoint); + else + retval = breakpoint_add(target, pc_value, 2, BKPT_TYPE_BY_ADDR(pc_value)); + bool tmp_bp_set = (retval == ERROR_OK); + + /* No more breakpoints left, just do a step */ + if (!tmp_bp_set) cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT); - /* Re-enable interrupts */ - cortex_m3_write_debug_halt_mask(target, C_HALT, C_MASKINTS); + else { + /* Start the core */ + LOG_DEBUG("Starting core to serve pending interrupts"); + int64_t t_start = timeval_ms(); + cortex_m3_write_debug_halt_mask(target, 0, C_HALT | C_STEP); + + /* Wait for pending handlers to complete or timeout */ + do { + retval = mem_ap_read_atomic_u32(swjdp, + DCB_DHCSR, + &cortex_m3->dcb_dhcsr); + if (retval != ERROR_OK) { + target->state = TARGET_UNKNOWN; + return retval; + } + isr_timed_out = ((timeval_ms() - t_start) > 500); + } while (!((cortex_m3->dcb_dhcsr & S_HALT) || isr_timed_out)); + + /* only remove breakpoint if we created it */ + if (breakpoint) + cortex_m3_unset_breakpoint(target, breakpoint); + else { + /* Remove the temporary breakpoint */ + breakpoint_remove(target, pc_value); + } + + if (isr_timed_out) { + LOG_DEBUG("Interrupt handlers didn't complete within time, " + "leaving target running"); + } else { + /* Step over next instruction with interrupts disabled */ + cortex_m3_write_debug_halt_mask(target, + C_HALT | C_MASKINTS, + 0); + cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT); + /* Re-enable interrupts */ + cortex_m3_write_debug_halt_mask(target, C_HALT, C_MASKINTS); + } } } } @@ -973,6 +1004,14 @@ static int cortex_m3_assert_reset(struct target *target) return retval; } + /* If the processor is sleeping in a WFI or WFE instruction, the + * C_HALT bit must be asserted to regain control */ + if (cortex_m3->dcb_dhcsr & S_SLEEP) { + retval = mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); + if (retval != ERROR_OK) + return retval; + } + retval = mem_ap_write_u32(swjdp, DCB_DCRDR, 0); if (retval != ERROR_OK) return retval; @@ -1025,7 +1064,7 @@ static int cortex_m3_assert_reset(struct target *target) if (reset_config == CORTEX_M3_RESET_VECTRESET) { LOG_WARNING("Only resetting the Cortex-M3 core, use a reset-init event " - "handler to reset any peripherals"); + "handler to reset any peripherals or configure hardware srst support."); } {