/* forward declarations */
static int cortex_m3_store_core_reg_u32(struct target *target,
/* forward declarations */
static int cortex_m3_store_core_reg_u32(struct target *target,
static int cortex_m3_clear_halt(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
static int cortex_m3_clear_halt(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
static int cortex_m3_single_step_core(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
static int cortex_m3_single_step_core(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
* Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
* HALT can put the core into an unknown state.
*/
* Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
* HALT can put the core into an unknown state.
*/
retval = mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
if (retval != ERROR_OK)
return retval;
}
retval = mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
retval = mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
if (retval != ERROR_OK)
return retval;
}
retval = mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
uint32_t dcb_demcr;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
uint32_t dcb_demcr;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
struct cortex_m3_fp_comparator *fp_list = cortex_m3->fp_comparator_list;
struct cortex_m3_dwt_comparator *dwt_list = cortex_m3->dwt_comparator_list;
struct cortex_m3_fp_comparator *fp_list = cortex_m3->fp_comparator_list;
struct cortex_m3_dwt_comparator *dwt_list = cortex_m3->dwt_comparator_list;
/* this register is used for emulated dcc channel */
retval = mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
/* this register is used for emulated dcc channel */
retval = mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
retval = target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
if (retval != ERROR_OK)
return retval;
}
/* Restore DWT registers */
retval = target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
if (retval != ERROR_OK)
return retval;
}
/* Restore DWT registers */
- /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
- /* only check the debug reason if we don't know it already */
+ /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason
+ * only check the debug reason if we don't know it already */
target->debug_reason = DBG_REASON_BREAKPOINT;
if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
target->debug_reason = DBG_REASON_WPTANDBKPT;
target->debug_reason = DBG_REASON_BREAKPOINT;
if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
target->debug_reason = DBG_REASON_WPTANDBKPT;
target->debug_reason = DBG_REASON_WATCHPOINT;
else if (cortex_m3->nvic_dfsr & DFSR_VCATCH)
target->debug_reason = DBG_REASON_BREAKPOINT;
target->debug_reason = DBG_REASON_WATCHPOINT;
else if (cortex_m3->nvic_dfsr & DFSR_VCATCH)
target->debug_reason = DBG_REASON_BREAKPOINT;
{
uint32_t shcsr = 0, except_sr = 0, cfsr = -1, except_ar = -1;
struct armv7m_common *armv7m = target_to_armv7m(target);
{
uint32_t shcsr = 0, except_sr = 0, cfsr = -1, except_ar = -1;
struct armv7m_common *armv7m = target_to_armv7m(target);
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
struct arm *arm = &armv7m->arm;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
struct arm *arm = &armv7m->arm;
if (!armv7m->core_cache->reg_list[i].valid)
armv7m->read_core_reg(target, i);
}
if (!armv7m->core_cache->reg_list[i].valid)
armv7m->read_core_reg(target, i);
}
- cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
+ cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR & ~0xff);
armv7m->core_mode = ARMV7M_MODE_HANDLER;
armv7m->exception_number = (xPSR & 0x1FF);
arm->core_mode = ARM_MODE_HANDLER;
arm->map = armv7m_msp_reg_map;
armv7m->core_mode = ARMV7M_MODE_HANDLER;
armv7m->exception_number = (xPSR & 0x1FF);
arm->core_mode = ARM_MODE_HANDLER;
arm->map = armv7m_msp_reg_map;
unsigned control = buf_get_u32(armv7m->core_cache
->reg_list[ARMV7M_CONTROL].value, 0, 2);
/* is this thread privileged? */
armv7m->core_mode = control & 1;
arm->core_mode = armv7m->core_mode
unsigned control = buf_get_u32(armv7m->core_cache
->reg_list[ARMV7M_CONTROL].value, 0, 2);
/* is this thread privileged? */
armv7m->core_mode = control & 1;
arm->core_mode = armv7m->core_mode
LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
armv7m_mode_strings[armv7m->core_mode],
LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
armv7m_mode_strings[armv7m->core_mode],
int retval = ERROR_OK;
enum target_state prev_target_state = target->state;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
int retval = ERROR_OK;
enum target_state prev_target_state = target->state;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
/* Read from Debug Halting Control and Status Register */
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
/* Read from Debug Halting Control and Status Register */
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
*/
if (cortex_m3->dcb_dhcsr & S_LOCKUP) {
LOG_ERROR("%s -- clearing lockup after double fault",
*/
if (cortex_m3->dcb_dhcsr & S_LOCKUP) {
LOG_ERROR("%s -- clearing lockup after double fault",
cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
target->debug_reason = DBG_REASON_DBGRQ;
cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
target->debug_reason = DBG_REASON_DBGRQ;
/* check if still in reset */
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
if (retval != ERROR_OK)
return retval;
/* check if still in reset */
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
if (retval != ERROR_OK)
return retval;
/* Cannot switch context while running so endreset is
* called with target->state == TARGET_RESET
*/
LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32,
/* Cannot switch context while running so endreset is
* called with target->state == TARGET_RESET
*/
LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32,
cortex_m3_endreset_event(target);
target->state = TARGET_RUNNING;
prev_target_state = TARGET_RUNNING;
}
cortex_m3_endreset_event(target);
target->state = TARGET_RUNNING;
prev_target_state = TARGET_RUNNING;
}
- if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET))
- {
- if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
+ if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) {
+ retval = cortex_m3_debug_entry(target);
+ if (retval != ERROR_OK)
LOG_DEBUG("target->state: %s",
target_state_name(target));
LOG_DEBUG("target->state: %s",
target_state_name(target));
- if (target->state == TARGET_RESET)
- {
- if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
- {
+ if (target->state == TARGET_RESET) {
+ if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
static int cortex_m3_soft_reset_halt(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
static int cortex_m3_soft_reset_halt(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
LOG_DEBUG("waiting for system reset-halt, "
"DHCSR 0x%08x, %d ms",
(unsigned) dcb_dhcsr, timeout);
LOG_DEBUG("waiting for system reset-halt, "
"DHCSR 0x%08x, %d ms",
(unsigned) dcb_dhcsr, timeout);
if (!breakpoint->set)
cortex_m3_set_breakpoint(target, breakpoint);
breakpoint = breakpoint->next;
if (!breakpoint->set)
cortex_m3_set_breakpoint(target, breakpoint);
breakpoint = breakpoint->next;
target_free_all_working_areas(target);
cortex_m3_enable_breakpoints(target);
cortex_m3_enable_watchpoints(target);
}
target_free_all_working_areas(target);
cortex_m3_enable_breakpoints(target);
cortex_m3_enable_watchpoints(target);
}
buf_set_u32(r->value, 0, 32, address);
r->dirty = true;
r->valid = true;
buf_set_u32(r->value, 0, 32, address);
r->dirty = true;
r->valid = true;
* the core will break again */
if (!breakpoint_find(target, buf_get_u32(r->value, 0, 32))
* the core will break again */
if (!breakpoint_find(target, buf_get_u32(r->value, 0, 32))
resume_pc = buf_get_u32(r->value, 0, 32);
armv7m_restore_context(target);
/* the front-end may request us not to handle breakpoints */
resume_pc = buf_get_u32(r->value, 0, 32);
armv7m_restore_context(target);
/* the front-end may request us not to handle breakpoints */
cortex_m3_unset_breakpoint(target, breakpoint);
cortex_m3_single_step_core(target);
cortex_m3_set_breakpoint(target, breakpoint);
cortex_m3_unset_breakpoint(target, breakpoint);
cortex_m3_single_step_core(target);
cortex_m3_set_breakpoint(target, breakpoint);
target->state = TARGET_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
target->state = TARGET_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
target->state = TARGET_DEBUG_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
target->state = TARGET_DEBUG_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
/* int irqstepcount = 0; */
static int cortex_m3_step(struct target *target, int current,
/* int irqstepcount = 0; */
static int cortex_m3_step(struct target *target, int current,
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
struct breakpoint *breakpoint = NULL;
struct reg *pc = armv7m->arm.pc;
bool bkpt_inst_found = false;
int retval;
bool isr_timed_out = false;
struct breakpoint *breakpoint = NULL;
struct reg *pc = armv7m->arm.pc;
bool bkpt_inst_found = false;
int retval;
bool isr_timed_out = false;
/* if no bkpt instruction is found at pc then we can perform
* a normal step, otherwise we have to manually step over the bkpt
* instruction - as such simulate a step */
/* if no bkpt instruction is found at pc then we can perform
* a normal step, otherwise we have to manually step over the bkpt
* instruction - as such simulate a step */
/* Automatic ISR masking mode off: Just step over the next instruction */
if ((cortex_m3->isrmasking_mode != CORTEX_M3_ISRMASK_AUTO))
/* Automatic ISR masking mode off: Just step over the next instruction */
if ((cortex_m3->isrmasking_mode != CORTEX_M3_ISRMASK_AUTO))
- retval = breakpoint_add(target, pc_value , 2, BKPT_TYPE_BY_ADDR(pc_value));
+ 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)
bool tmp_bp_set = (retval == ERROR_OK);
/* No more breakpoints left, just do a step */
if (!tmp_bp_set)
- retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
- if (retval != ERROR_OK)
- {
+ retval = mem_ap_read_atomic_u32(swjdp,
+ DCB_DHCSR,
+ &cortex_m3->dcb_dhcsr);
+ if (retval != ERROR_OK) {
/* Remove the temporary breakpoint */
breakpoint_remove(target, pc_value);
/* Remove the temporary breakpoint */
breakpoint_remove(target, pc_value);
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);
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);
- " nvic_icsr = 0x%" PRIx32,
- cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
+ " nvic_icsr = 0x%" PRIx32,
+ cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
- " nvic_icsr = 0x%" PRIx32,
- cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
+ " nvic_icsr = 0x%" PRIx32,
+ cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
static int cortex_m3_assert_reset(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
static int cortex_m3_assert_reset(struct target *target)
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
enum cortex_m3_soft_reset_config reset_config = cortex_m3->soft_reset_config;
LOG_DEBUG("target->state: %s",
enum cortex_m3_soft_reset_config reset_config = cortex_m3->soft_reset_config;
LOG_DEBUG("target->state: %s",
+ /* some cores support connecting while srst is asserted
+ * use that mode is it has been configured */
+
+ bool srst_asserted = false;
+
+ if (jtag_reset_config & RESET_SRST_NO_GATING) {
+ adapter_assert_reset();
+ srst_asserted = true;
+ }
+
/* Enable debug requests */
int retval;
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
if (retval != ERROR_OK)
return retval;
/* Enable debug requests */
int retval;
retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
if (retval != ERROR_OK)
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_atomic_u32(swjdp, DCB_DHCSR,
DBGKEY | C_DEBUGEN | C_HALT);
if (retval != ERROR_OK)
retval = mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
DBGKEY | C_DEBUGEN | C_HALT);
if (retval != ERROR_OK)
/* clear C_HALT in dhcsr reg */
cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
/* clear C_HALT in dhcsr reg */
cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
/* Halt in debug on reset; endreset_event() restores DEMCR.
*
* REVISIT catching BUSERR presumably helps to defend against
/* Halt in debug on reset; endreset_event() restores DEMCR.
*
* REVISIT catching BUSERR presumably helps to defend against
/* Use a standard Cortex-M3 software reset mechanism.
* We default to using VECRESET as it is supported on all current cores.
* This has the disadvantage of not resetting the peripherals, so a
/* Use a standard Cortex-M3 software reset mechanism.
* We default to using VECRESET as it is supported on all current cores.
* This has the disadvantage of not resetting the peripherals, so a
if (reset_config == CORTEX_M3_RESET_VECTRESET) {
LOG_WARNING("Only resetting the Cortex-M3 core, use a reset-init event "
if (reset_config == CORTEX_M3_RESET_VECTRESET) {
LOG_WARNING("Only resetting the Cortex-M3 core, use a reset-init event "
- if (target->reset_halt)
- {
- if ((retval = target_halt(target)) != ERROR_OK)
+ if (target->reset_halt) {
+ retval = target_halt(target);
+ if (retval != ERROR_OK)
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct cortex_m3_fp_comparator *comparator_list = cortex_m3->fp_comparator_list;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct cortex_m3_fp_comparator *comparator_list = cortex_m3->fp_comparator_list;
LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint->unique_id);
return ERROR_OK;
}
if (cortex_m3->auto_bp_type)
LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint->unique_id);
return ERROR_OK;
}
if (cortex_m3->auto_bp_type)
hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
comparator_list[fp_num].used = 1;
comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1;
hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
comparator_list[fp_num].used = 1;
comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1;
- 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 "", fp_num, comparator_list[fp_num].fpcr_value);
- if (!cortex_m3->fpb_enabled)
- {
+ 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 "",
+ fp_num,
+ comparator_list[fp_num].fpcr_value);
+ if (!cortex_m3->fpb_enabled) {
LOG_DEBUG("FPB wasn't enabled, do it now");
target_write_u32(target, FP_CTRL, 3);
}
LOG_DEBUG("FPB wasn't enabled, do it now");
target_write_u32(target, FP_CTRL, 3);
}
}
LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
}
LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
LOG_WARNING("breakpoint not set");
return ERROR_OK;
}
LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
LOG_WARNING("breakpoint not set");
return ERROR_OK;
}
LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
LOG_DEBUG("Invalid FP Comparator number in breakpoint");
return ERROR_OK;
}
comparator_list[fp_num].used = 0;
comparator_list[fp_num].fpcr_value = 0;
LOG_DEBUG("Invalid FP Comparator number in breakpoint");
return ERROR_OK;
}
comparator_list[fp_num].used = 0;
comparator_list[fp_num].fpcr_value = 0;
- target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value);
- }
- else
- {
+ target_write_u32(target, comparator_list[fp_num].fpcr_address,
+ comparator_list[fp_num].fpcr_value);
+ } else {
- if (breakpoint->length == 4)
- {
- if ((retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
- {
+ if (breakpoint->length == 4) {
+ retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1,
+ breakpoint->orig_instr);
+ if (retval != ERROR_OK)
- }
- }
- else
- {
- if ((retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
- {
+ } else {
+ retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1,
+ breakpoint->orig_instr);
+ if (retval != ERROR_OK)
- if(breakpoint->type != BKPT_TYPE_BY_ADDR(breakpoint->address)) {
- if (breakpoint->type == BKPT_HARD)
- {
+ if (breakpoint->type != BKPT_TYPE_BY_ADDR(breakpoint->address)) {
+ if (breakpoint->type == BKPT_HARD) {
LOG_INFO("flash patch comparator requested outside code memory region");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
LOG_INFO("flash patch comparator requested outside code memory region");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
LOG_INFO("soft breakpoint requested in code (flash) memory region");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
}
LOG_INFO("soft breakpoint requested in code (flash) memory region");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
}
LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
LOG_INFO("only breakpoints of two bytes length supported");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
LOG_INFO("only breakpoints of two bytes length supported");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
/* REVISIT why check? FBP can be updated with core running ... */
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
/* REVISIT why check? FBP can be updated with core running ... */
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (cortex_m3->auto_bp_type)
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (cortex_m3->auto_bp_type)
- comparator->used && dwt_num < cortex_m3->dwt_num_comp;
- comparator++, dwt_num++)
+ comparator->used && dwt_num < cortex_m3->dwt_num_comp;
+ comparator++, dwt_num++)
comparator->comp = watchpoint->address;
target_write_u32(target, comparator->dwt_comparator_address + 0,
comparator->comp = watchpoint->address;
target_write_u32(target, comparator->dwt_comparator_address + 0,
- case WPT_READ:
- comparator->function = 5;
- break;
- case WPT_WRITE:
- comparator->function = 6;
- break;
- case WPT_ACCESS:
- comparator->function = 7;
- break;
+ case WPT_READ:
+ comparator->function = 5;
+ break;
+ case WPT_WRITE:
+ comparator->function = 6;
+ break;
+ case WPT_ACCESS:
+ comparator->function = 7;
+ break;
- watchpoint->unique_id, dwt_num,
- (unsigned) comparator->comp,
- (unsigned) comparator->mask,
- (unsigned) comparator->function);
+ watchpoint->unique_id, dwt_num,
+ (unsigned) comparator->comp,
+ (unsigned) comparator->mask,
+ (unsigned) comparator->function);
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct cortex_m3_dwt_comparator *comparator;
int dwt_num;
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct cortex_m3_dwt_comparator *comparator;
int dwt_num;
return ERROR_OK;
}
dwt_num = watchpoint->set - 1;
LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
return ERROR_OK;
}
dwt_num = watchpoint->set - 1;
LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
- watchpoint->unique_id, dwt_num,
- (unsigned) watchpoint->address);
+ watchpoint->unique_id, dwt_num,
+ (unsigned) watchpoint->address);
comparator->used = 0;
comparator->function = 0;
target_write_u32(target, comparator->dwt_comparator_address + 8,
comparator->used = 0;
comparator->function = 0;
target_write_u32(target, comparator->dwt_comparator_address + 8,
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
/* REVISIT why check? DWT can be updated with core running ... */
{
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
/* REVISIT why check? DWT can be updated with core running ... */
cortex_m3->dwt_comp_available++;
LOG_DEBUG("dwt_comp_available: %d", cortex_m3->dwt_comp_available);
cortex_m3->dwt_comp_available++;
LOG_DEBUG("dwt_comp_available: %d", cortex_m3->dwt_comp_available);
if (!watchpoint->set)
cortex_m3_set_watchpoint(target, watchpoint);
watchpoint = watchpoint->next;
if (!watchpoint->set)
cortex_m3_set_watchpoint(target, watchpoint);
watchpoint = watchpoint->next;
/* 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) {
/* 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 = cortexm3_dap_read_coreregister_u32(swjdp, value, num);
+ case 0 ... 18:
+ /* read a normal core register */
+ retval = cortexm3_dap_read_coreregister_u32(swjdp, 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_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.
- */
- cortexm3_dap_read_coreregister_u32(swjdp, value, 20);
+ 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;
- switch (num)
- {
- case ARMV7M_PRIMASK:
- *value = buf_get_u32((uint8_t*)value, 0, 1);
- 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.
+ */
+ cortexm3_dap_read_coreregister_u32(swjdp, value, 20);
- case ARMV7M_CONTROL:
- *value = buf_get_u32((uint8_t*)value, 24, 2);
- 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, 2);
+ break;
+ }
* Selector values for R0..R15, xPSR, MSP, and PSP.
*/
switch (num) {
* Selector values for R0..R15, xPSR, MSP, and PSP.
*/
switch (num) {
- case 0 ... 18:
- retval = cortexm3_dap_write_coreregister_u32(swjdp, value, num);
- if (retval != ERROR_OK)
- {
- struct reg *r;
+ case 0 ... 18:
+ retval = cortexm3_dap_write_coreregister_u32(swjdp, value, num);
+ if (retval != ERROR_OK) {
+ struct reg *r;
+
+ LOG_ERROR("JTAG failure");
+ r = armv7m->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;
- LOG_ERROR("JTAG failure");
- r = armv7m->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_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.
- */
- cortexm3_dap_read_coreregister_u32(swjdp, ®, 20);
+ 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.
+ */
+ cortexm3_dap_read_coreregister_u32(swjdp, ®, 20);
- switch (num)
- {
- case ARMV7M_PRIMASK:
- buf_set_u32((uint8_t*)®, 0, 1, value);
- break;
+ 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_BASEPRI:
+ buf_set_u32((uint8_t *)®, 8, 8, value);
+ break;
- case ARMV7M_FAULTMASK:
- buf_set_u32((uint8_t*)®, 16, 1, value);
- break;
+ case ARMV7M_FAULTMASK:
+ buf_set_u32((uint8_t *)®, 16, 1, value);
+ break;
- case ARMV7M_CONTROL:
- buf_set_u32((uint8_t*)®, 24, 2, value);
- break;
- }
+ case ARMV7M_CONTROL:
+ buf_set_u32((uint8_t *)®, 24, 2, value);
+ break;
+ }
+ if (armv7m->arm.is_armv6m) {
+ /* armv6m does not handle unaligned memory access */
+ if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+ }
+
- case 4:
- retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
- break;
- case 2:
- retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
- break;
- case 1:
- retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
- break;
+ case 4:
+ retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
+ break;
+ case 2:
+ retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
+ break;
+ case 1:
+ retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
+ break;
+ if (armv7m->arm.is_armv6m) {
+ /* armv6m does not handle unaligned memory access */
+ if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+ }
+
- case 4:
- retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
- break;
- case 2:
- retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
- break;
- case 1:
- retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
- break;
+ case 4:
+ retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
+ break;
+ case 2:
+ retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
+ break;
+ case 1:
+ retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
+ break;
{
return cortex_m3_write_memory(target, address, 4, count, buffer);
}
static int cortex_m3_init_target(struct command_context *cmd_ctx,
{
return cortex_m3_write_memory(target, address, 4, count, buffer);
}
static int cortex_m3_init_target(struct command_context *cmd_ctx,
for (reg = 0; reg < 2; reg++)
cortex_m3_dwt_addreg(target, cache->reg_list + reg,
for (reg = 0; reg < 2; reg++)
cortex_m3_dwt_addreg(target, cache->reg_list + reg,
comparator = cm3->dwt_comparator_list;
for (i = 0; i < cm3->dwt_num_comp; i++, comparator++) {
comparator = cm3->dwt_comparator_list;
for (i = 0; i < cm3->dwt_num_comp; i++, comparator++) {
comparator->dwt_comparator_address = DWT_COMP0 + 0x10 * i;
for (j = 0; j < 3; j++, reg++)
cortex_m3_dwt_addreg(target, cache->reg_list + reg,
comparator->dwt_comparator_address = DWT_COMP0 + 0x10 * i;
for (j = 0; j < 3; j++, reg++)
cortex_m3_dwt_addreg(target, cache->reg_list + reg,
}
*register_get_last_cache_p(&target->reg_cache) = cache;
cm3->dwt_cache = cache;
LOG_DEBUG("DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s",
}
*register_get_last_cache_p(&target->reg_cache) = cache;
cm3->dwt_cache = cache;
LOG_DEBUG("DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s",
- dwtcr, cm3->dwt_num_comp,
- (dwtcr & (0xf << 24)) ? " only" : "/trigger");
+ dwtcr, cm3->dwt_num_comp,
+ (dwtcr & (0xf << 24)) ? " only" : "/trigger");
/* REVISIT: if num_comp > 1, check whether comparator #1 can
* implement single-address data value watchpoints ... so we
/* REVISIT: if num_comp > 1, check whether comparator #1 can
* implement single-address data value watchpoints ... so we
-static int cortex_m3_examine(struct target *target)
+#define MVFR0 0xe000ef40
+#define MVFR1 0xe000ef44
+
+#define MVFR0_DEFAULT_M4 0x10110021
+#define MVFR1_DEFAULT_M4 0x11000011
+
+int cortex_m3_examine(struct target *target)
- if (((cpuid >> 4) & 0xc3f) == 0xc23)
- LOG_DEBUG("Cortex-M3 r%" PRId8 "p%" PRId8 " processor detected",
- (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
+ /* Get CPU Type */
+ i = (cpuid >> 4) & 0xf;
+
+ LOG_DEBUG("Cortex-M%d r%" PRId8 "p%" PRId8 " processor detected",
+ i, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
+ /* test for floating point feature on cortex-m4 */
+ if (i == 4) {
+ target_read_u32(target, MVFR0, &mvfr0);
+ target_read_u32(target, MVFR1, &mvfr1);
+
+ if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) {
+ LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i);
+ armv7m->fp_feature = FPv4_SP;
+ }
+ } else if (i == 0) {
+ /* Cortex-M0 does not support unaligned memory access */
+ armv7m->arm.is_armv6m = true;
+ }
+
+ if (i == 4 || i == 3) {
+ /* Cortex-M3/M4 has 4096 bytes autoincrement range */
+ armv7m->dap.tar_autoincr_block = (1 << 12);
+ }
+
/* NOTE: FPB and DWT are both optional. */
/* Setup FPB */
target_read_u32(target, FP_CTRL, &fpcr);
cortex_m3->auto_bp_type = 1;
/* NOTE: FPB and DWT are both optional. */
/* Setup FPB */
target_read_u32(target, FP_CTRL, &fpcr);
cortex_m3->auto_bp_type = 1;
- cortex_m3->fp_comparator_list = calloc(cortex_m3->fp_num_code + cortex_m3->fp_num_lit, sizeof(struct cortex_m3_fp_comparator));
+ cortex_m3->fp_comparator_list = calloc(
+ cortex_m3->fp_num_code + cortex_m3->fp_num_lit,
+ sizeof(struct cortex_m3_fp_comparator));
- for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++)
- {
- cortex_m3->fp_comparator_list[i].type = (i < cortex_m3->fp_num_code) ? FPCR_CODE : FPCR_LITERAL;
+ for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++) {
+ cortex_m3->fp_comparator_list[i].type =
+ (i < cortex_m3->fp_num_code) ? FPCR_CODE : FPCR_LITERAL;
- LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i", fpcr, cortex_m3->fp_num_code, cortex_m3->fp_num_lit);
+ LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i",
+ fpcr,
+ cortex_m3->fp_num_code,
+ cortex_m3->fp_num_lit);
/* Setup DWT */
cortex_m3_dwt_setup(cortex_m3, target);
/* These hardware breakpoints only work for code in flash! */
LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
/* Setup DWT */
cortex_m3_dwt_setup(cortex_m3, target);
/* These hardware breakpoints only work for code in flash! */
LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
- target_name(target),
- cortex_m3->fp_num_code,
- cortex_m3->dwt_num_comp);
+ target_name(target),
+ cortex_m3->fp_num_code,
+ cortex_m3->dwt_num_comp);
- mem_ap_read_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
+ mem_ap_read_buf_u16(swjdp, (uint8_t *)&dcrdr, 1, DCB_DCRDR);
- retval = mem_ap_write_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
+ retval = mem_ap_write_buf_u16(swjdp, (uint8_t *)&dcrdr, 1, DCB_DCRDR);
uint8_t data;
uint8_t ctrl;
cortex_m3_dcc_read(swjdp, &data, &ctrl);
/* check if we have data */
uint8_t data;
uint8_t ctrl;
cortex_m3_dcc_read(swjdp, &data, &ctrl);
/* check if we have data */
/* Leave (only) generic DAP stuff for debugport_init(); */
armv7m->dap.jtag_info = &cortex_m3->jtag_info;
armv7m->dap.memaccess_tck = 8;
/* Leave (only) generic DAP stuff for debugport_init(); */
armv7m->dap.jtag_info = &cortex_m3->jtag_info;
armv7m->dap.memaccess_tck = 8;
- /* Cortex-M3 has 4096 bytes autoincrement range */
- armv7m->dap.tar_autoincr_block = (1 << 12);
+
+ /* Cortex-M3/M4 has 4096 bytes autoincrement range
+ * but set a safe default to 1024 to support Cortex-M0
+ * this will be changed in cortex_m3_examine if a M3/M4 is detected */
+ armv7m->dap.tar_autoincr_block = (1 << 10);
/* register arch-specific functions */
armv7m->examine_debug_reason = cortex_m3_examine_debug_reason;
/* register arch-specific functions */
armv7m->examine_debug_reason = cortex_m3_examine_debug_reason;
target_register_timer_callback(cortex_m3_handle_target_request, 1, 1, target);
target_register_timer_callback(cortex_m3_handle_target_request, 1, 1, target);
cortex_m3->common_magic = CORTEX_M3_COMMON_MAGIC;
cortex_m3_init_arch_info(target, cortex_m3, target->tap);
cortex_m3->common_magic = CORTEX_M3_COMMON_MAGIC;
cortex_m3_init_arch_info(target, cortex_m3, target->tap);
/*--------------------------------------------------------------------------*/
static int cortex_m3_verify_pointer(struct command_context *cmd_ctx,
/*--------------------------------------------------------------------------*/
static int cortex_m3_verify_pointer(struct command_context *cmd_ctx,
{
if (cm3->common_magic != CORTEX_M3_COMMON_MAGIC) {
command_print(cmd_ctx, "target is not a Cortex-M3");
{
if (cm3->common_magic != CORTEX_M3_COMMON_MAGIC) {
command_print(cmd_ctx, "target is not a Cortex-M3");
- { "hard_err", VC_HARDERR, },
- { "int_err", VC_INTERR, },
- { "bus_err", VC_BUSERR, },
- { "state_err", VC_STATERR, },
- { "chk_err", VC_CHKERR, },
- { "nocp_err", VC_NOCPERR, },
- { "mm_err", VC_MMERR, },
- { "reset", VC_CORERESET, },
+ { "hard_err", VC_HARDERR, },
+ { "int_err", VC_INTERR, },
+ { "bus_err", VC_BUSERR, },
+ { "state_err", VC_STATERR, },
+ { "chk_err", VC_CHKERR, },
+ { "nocp_err", VC_NOCPERR, },
+ { "mm_err", VC_MMERR, },
+ { "reset", VC_CORERESET, },
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 target *target = get_current_target(CMD_CTX);
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
command_print(CMD_CTX, "%9s: %s", vec_ids[i].name,
(demcr & vec_ids[i].mask) ? "catch" : "ignore");
}
command_print(CMD_CTX, "%9s: %s", vec_ids[i].name,
(demcr & vec_ids[i].mask) ? "catch" : "ignore");
}
static const Jim_Nvp nvp_maskisr_modes[] = {
{ .name = "auto", .value = CORTEX_M3_ISRMASK_AUTO },
static const Jim_Nvp nvp_maskisr_modes[] = {
{ .name = "auto", .value = CORTEX_M3_ISRMASK_AUTO },
- { .name = "off" , .value = CORTEX_M3_ISRMASK_OFF },
- { .name = "on" , .value = CORTEX_M3_ISRMASK_ON },
- { .name = NULL , .value = -1 },
+ { .name = "off", .value = CORTEX_M3_ISRMASK_OFF },
+ { .name = "on", .value = CORTEX_M3_ISRMASK_ON },
+ { .name = NULL, .value = -1 },
if (strcmp(*CMD_ARGV, "sysresetreq") == 0)
cortex_m3->soft_reset_config = CORTEX_M3_RESET_SYSRESETREQ;
else if (strcmp(*CMD_ARGV, "vectreset") == 0)
cortex_m3->soft_reset_config = CORTEX_M3_RESET_VECTRESET;
}
if (strcmp(*CMD_ARGV, "sysresetreq") == 0)
cortex_m3->soft_reset_config = CORTEX_M3_RESET_SYSRESETREQ;
else if (strcmp(*CMD_ARGV, "vectreset") == 0)
cortex_m3->soft_reset_config = CORTEX_M3_RESET_VECTRESET;
}