* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* *
* Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0) *
/* forward declarations */
static int cortex_m3_store_core_reg_u32(struct target *target,
- enum armv7m_regtype type, uint32_t num, uint32_t value);
+ uint32_t num, uint32_t value);
static int cortexm3_dap_read_coreregister_u32(struct adiv5_dap *swjdp,
uint32_t *value, int regnum)
uint32_t mask_on, uint32_t mask_off)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
+ struct adiv5_dap *swjdp = cortex_m3->armv7m.arm.dap;
/* mask off status bits */
cortex_m3->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
static int cortex_m3_clear_halt(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
+ struct adiv5_dap *swjdp = cortex_m3->armv7m.arm.dap;
int retval;
/* clear step if any */
static int cortex_m3_single_step_core(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
+ struct adiv5_dap *swjdp = cortex_m3->armv7m.arm.dap;
uint32_t dhcsr_save;
int retval;
uint32_t dcb_demcr;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
- struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
+ struct adiv5_dap *swjdp = cortex_m3->armv7m.arm.dap;
struct cortex_m3_fp_comparator *fp_list = cortex_m3->fp_comparator_list;
struct cortex_m3_dwt_comparator *dwt_list = cortex_m3->dwt_comparator_list;
if (retval != ERROR_OK)
return retval;
- register_cache_invalidate(cortex_m3->armv7m.core_cache);
+ register_cache_invalidate(armv7m->arm.core_cache);
/* make sure we have latest dhcsr flags */
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
{
uint32_t shcsr = 0, except_sr = 0, cfsr = -1, except_ar = -1;
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
int retval;
retval = mem_ap_read_u32(swjdp, NVIC_SHCSR, &shcsr);
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
struct arm *arm = &armv7m->arm;
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
struct reg *r;
LOG_DEBUG(" ");
return retval;
/* Examine target state and mode
- * First load register acessible through core debug port*/
- int num_regs = armv7m->core_cache->num_regs;
+ * First load register accessible through core debug port */
+ int num_regs = arm->core_cache->num_regs;
for (i = 0; i < num_regs; i++) {
- if (!armv7m->core_cache->reg_list[i].valid)
- armv7m->read_core_reg(target, i);
+ r = &armv7m->arm.core_cache->reg_list[i];
+ if (!r->valid)
+ arm->read_core_reg(target, r, i, ARM_MODE_ANY);
}
- r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
+ r = arm->cpsr;
xPSR = buf_get_u32(r->value, 0, 32);
#ifdef ARMV7_GDB_HACKS
/* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
if (xPSR & 0xf00) {
r->dirty = r->valid;
- cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR & ~0xff);
+ cortex_m3_store_core_reg_u32(target, 16, xPSR & ~0xff);
}
/* 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;
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));
int retval = ERROR_OK;
enum target_state prev_target_state = target->state;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
+ struct adiv5_dap *swjdp = cortex_m3->armv7m.arm.dap;
/* Read from Debug Halting Control and Status Register */
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
static int cortex_m3_soft_reset_halt(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
+ struct adiv5_dap *swjdp = cortex_m3->armv7m.arm.dap;
uint32_t dcb_dhcsr = 0;
int retval, timeout = 0;
+ /* soft_reset_halt is deprecated on cortex_m as the same functionality
+ * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset'
+ * As this reset only used VC_CORERESET it would only ever reset the cortex_m
+ * core, not the peripherals */
+ LOG_WARNING("soft_reset_halt is deprecated, please use 'reset halt' instead.");
+
/* Enter debug state on reset; restore DEMCR in endreset_event() */
retval = mem_ap_write_u32(swjdp, DCB_DEMCR,
TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
target->state = TARGET_RESET;
/* registers are now invalid */
- register_cache_invalidate(cortex_m3->armv7m.core_cache);
+ register_cache_invalidate(cortex_m3->armv7m.arm.core_cache);
while (timeout < 100) {
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
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;
}
if (debug_execution) {
- r = armv7m->core_cache->reg_list + ARMV7M_PRIMASK;
+ r = armv7m->arm.core_cache->reg_list + ARMV7M_PRIMASK;
/* Disable interrupts */
/* We disable interrupts in the PRIMASK register instead of
r->valid = true;
/* Make sure we are in Thumb mode */
- r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
+ r = armv7m->arm.cpsr;
buf_set_u32(r->value, 24, 1, 1);
r->dirty = true;
r->valid = true;
target->debug_reason = DBG_REASON_NOTHALTED;
/* registers are now invalid */
- register_cache_invalidate(armv7m->core_cache);
+ register_cache_invalidate(armv7m->arm.core_cache);
if (!debug_execution) {
target->state = TARGET_RUNNING;
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
struct breakpoint *breakpoint = NULL;
struct reg *pc = armv7m->arm.pc;
bool bkpt_inst_found = false;
*
*/
- /* 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);
+ }
}
}
}
return retval;
/* registers are now invalid */
- register_cache_invalidate(cortex_m3->armv7m.core_cache);
+ register_cache_invalidate(armv7m->arm.core_cache);
if (breakpoint)
cortex_m3_set_breakpoint(target, breakpoint);
static int cortex_m3_assert_reset(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
+ struct adiv5_dap *swjdp = cortex_m3->armv7m.arm.dap;
enum cortex_m3_soft_reset_config reset_config = cortex_m3->soft_reset_config;
LOG_DEBUG("target->state: %s",
/* allow scripts to override the reset event */
target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
- register_cache_invalidate(cortex_m3->armv7m.core_cache);
+ register_cache_invalidate(cortex_m3->armv7m.arm.core_cache);
target->state = TARGET_RESET;
return ERROR_OK;
bool srst_asserted = false;
- if (jtag_reset_config & RESET_SRST_NO_GATING) {
+ if ((jtag_reset_config & RESET_HAS_SRST) &&
+ (jtag_reset_config & RESET_SRST_NO_GATING)) {
adapter_assert_reset();
srst_asserted = true;
}
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;
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("Using Cortex-M3 %s", (reset_config == CORTEX_M3_RESET_SYSRESETREQ)
+ LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M3_RESET_SYSRESETREQ)
? "SYSRESETREQ" : "VECTRESET");
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");
+ LOG_WARNING("Only resetting the Cortex-M core, use a reset-init event "
+ "handler to reset any peripherals or configure hardware srst support.");
}
{
target->state = TARGET_RESET;
jtag_add_sleep(50000);
- register_cache_invalidate(cortex_m3->armv7m.core_cache);
+ register_cache_invalidate(cortex_m3->armv7m.arm.core_cache);
if (target->reset_halt) {
retval = target_halt(target);
}
static int cortex_m3_load_core_reg_u32(struct target *target,
- enum armv7m_regtype type, uint32_t num, uint32_t *value)
+ uint32_t num, uint32_t *value)
{
int retval;
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct adiv5_dap *swjdp = &armv7m->dap;
+ 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
}
static int cortex_m3_store_core_reg_u32(struct target *target,
- enum armv7m_regtype type, uint32_t num, uint32_t value)
+ uint32_t num, uint32_t value)
{
int retval;
uint32_t reg;
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
#ifdef ARMV7_GDB_HACKS
/* If the LR register is being modified, make sure it will put us
struct reg *r;
LOG_ERROR("JTAG failure");
- r = armv7m->core_cache->reg_list + num;
+ r = armv7m->arm.core_cache->reg_list + num;
r->dirty = r->valid;
return ERROR_JTAG_DEVICE_ERROR;
}
uint32_t size, uint32_t count, uint8_t *buffer)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
int retval = ERROR_COMMAND_SYNTAX_ERROR;
if (armv7m->arm.is_armv6m) {
if (count && buffer) {
switch (size) {
case 4:
- retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
+ retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address, true);
break;
case 2:
retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
uint32_t size, uint32_t count, const uint8_t *buffer)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
int retval = ERROR_COMMAND_SYNTAX_ERROR;
if (armv7m->arm.is_armv6m) {
if (count && buffer) {
switch (size) {
case 4:
- retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
+ retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address, true);
break;
case 2:
retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
return retval;
}
-static int cortex_m3_bulk_write_memory(struct target *target, uint32_t address,
- uint32_t count, const uint8_t *buffer)
-{
- return cortex_m3_write_memory(target, address, 4, count, buffer);
-}
-
static int cortex_m3_init_target(struct command_context *cmd_ctx,
struct target *target)
{
for (j = 0; j < 3; j++, reg++)
cortex_m3_dwt_addreg(target, cache->reg_list + reg,
dwt_comp + 3 * i + j);
+
+ /* make sure we clear any watchpoints enabled on the target */
+ target_write_u32(target, comparator->dwt_comparator_address + 8, 0);
}
*register_get_last_cache_p(&target->reg_cache) = cache;
uint32_t cpuid, fpcr, mvfr0, mvfr1;
int i;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
- struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
+ struct adiv5_dap *swjdp = cortex_m3->armv7m.arm.dap;
struct armv7m_common *armv7m = target_to_armv7m(target);
/* stlink shares the examine handler but does not support
cortex_m3->fp_comparator_list[i].type =
(i < cortex_m3->fp_num_code) ? FPCR_CODE : FPCR_LITERAL;
cortex_m3->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i;
+
+ /* make sure we clear any breakpoints enabled on the target */
+ target_write_u32(target, cortex_m3->fp_comparator_list[i].fpcr_address, 0);
}
LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i",
fpcr,
uint32_t size, uint8_t *buffer)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
uint8_t data;
uint8_t ctrl;
uint32_t i;
if (!target_was_examined(target))
return ERROR_OK;
struct armv7m_common *armv7m = target_to_armv7m(target);
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
if (!target->dbg_msg_enabled)
return ERROR_OK;
struct cortex_m3_common *cm3)
{
if (cm3->common_magic != CORTEX_M3_COMMON_MAGIC) {
- command_print(cmd_ctx, "target is not a Cortex-M3");
+ command_print(cmd_ctx, "target is not a Cortex-M");
return ERROR_TARGET_INVALID;
}
return ERROR_OK;
struct target *target = get_current_target(CMD_CTX);
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
- struct adiv5_dap *swjdp = &armv7m->dap;
+ struct adiv5_dap *swjdp = armv7m->arm.dap;
uint32_t demcr = 0;
int retval;
}
n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_m3->isrmasking_mode);
- command_print(CMD_CTX, "cortex_m3 interrupt mask %s", n->name);
+ command_print(CMD_CTX, "cortex_m interrupt mask %s", n->name);
return ERROR_OK;
}
break;
}
- command_print(CMD_CTX, "cortex_m3 reset_config %s", reset_config);
+ command_print(CMD_CTX, "cortex_m reset_config %s", reset_config);
return ERROR_OK;
}
.name = "maskisr",
.handler = handle_cortex_m3_mask_interrupts_command,
.mode = COMMAND_EXEC,
- .help = "mask cortex_m3 interrupts",
+ .help = "mask cortex_m interrupts",
.usage = "['auto'|'on'|'off']",
},
{
.chain = armv7m_command_handlers,
},
{
- .name = "cortex_m3",
+ .name = "cortex_m",
.mode = COMMAND_EXEC,
- .help = "Cortex-M3 command group",
+ .help = "Cortex-M command group",
.usage = "",
.chain = cortex_m3_exec_command_handlers,
},
};
struct target_type cortexm3_target = {
- .name = "cortex_m3",
+ .name = "cortex_m",
+ .deprecated_name = "cortex_m3",
.poll = cortex_m3_poll,
.arch_state = armv7m_arch_state,
.read_memory = cortex_m3_read_memory,
.write_memory = cortex_m3_write_memory,
- .bulk_write_memory = cortex_m3_bulk_write_memory,
.checksum_memory = armv7m_checksum_memory,
.blank_check_memory = armv7m_blank_check_memory,