int cortex_m3_register_commands(struct command_context_s *cmd_ctx);
/* forward declarations */
-void cortex_m3_unset_all_breakpoints_and_watchpoints(struct target_s *target);
void cortex_m3_enable_breakpoints(struct target_s *target);
void cortex_m3_enable_watchpoints(struct target_s *target);
-void cortex_m3_disable_bkpts_and_wpts(struct target_s *target);
int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
int cortex_m3_quit();
int cortex_m3_load_core_reg_u32(target_t *target, enum armv7m_regtype type, u32 num, u32 *value);
int cortex_m3_store_core_reg_u32(target_t *target, enum armv7m_regtype type, u32 num, u32 value);
int cortex_m3_target_request_data(target_t *target, u32 size, u8 *buffer);
+int cortex_m3_examine(struct command_context_s *cmd_ctx, struct target_s *target);
+
+#ifdef ARMV7_GDB_HACKS
+extern u8 armv7m_gdb_dummy_cpsr_value[];
+extern reg_t armv7m_gdb_dummy_cpsr_reg;
+#endif
target_type_t cortexm3_target =
{
.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,
.run_algorithm = armv7m_run_algorithm,
.register_commands = cortex_m3_register_commands,
.target_command = cortex_m3_target_command,
.init_target = cortex_m3_init_target,
+ .examine = cortex_m3_examine,
.quit = cortex_m3_quit
};
}
swjdp_transaction_endcheck(swjdp);
- /* We are in process context */
- armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
armv7m_invalidate_core_regs(target);
return ERROR_OK;
}
}
xPSR = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32);
-
+
+#ifdef ARMV7_GDB_HACKS
+ /* copy real xpsr reg for gdb, setting thumb bit */
+ buf_set_u32(armv7m_gdb_dummy_cpsr_value, 0, 32, xPSR);
+ buf_set_u32(armv7m_gdb_dummy_cpsr_value, 5, 1, 1);
+ armv7m_gdb_dummy_cpsr_reg.valid = armv7m->core_cache->reg_list[ARMV7M_xPSR].valid;
+ armv7m_gdb_dummy_cpsr_reg.dirty = armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty;
+#endif
+
/* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
if (xPSR & 0xf00)
{
cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
}
- /* Now we can load SP core registers */
+ /* Now we can load SP core registers */
for (i = ARMV7M_PRIMASK; i < ARMV7NUMCOREREGS; i++)
{
if (!armv7m->core_cache->reg_list[i].valid)
- armv7m->read_core_reg(target, i);
+ armv7m->read_core_reg(target, i);
}
/* Are we in an exception handler */
- armv7m->core_mode = (xPSR & 0x1FF) ? ARMV7M_MODE_HANDLER : ARMV7M_MODE_THREAD;
- armv7m->exception_number = xPSR & 0x1FF;
+ if (xPSR & 0x1FF)
+ {
+ armv7m->core_mode = ARMV7M_MODE_HANDLER;
+ armv7m->exception_number = (xPSR & 0x1FF);
+ }
+ else
+ {
+ armv7m->core_mode = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1);
+ armv7m->exception_number = 0;
+ }
+
if (armv7m->exception_number)
{
cortex_m3_examine_exception_reason(target);
target->state = TARGET_SLEEP;
*/
+#if 0
/* Read Debug Fault Status Register, added to figure out the lockup when running flashtest.script */
- ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
- LOG_DEBUG("dcb_dhcsr 0x%x, nvic_dfsr 0x%x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, target_state_strings[target->state]);
+ ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
+ LOG_DEBUG("dcb_dhcsr 0x%x, nvic_dfsr 0x%x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, target_state_strings[target->state]);
+#endif
+
return ERROR_OK;
}
swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
u32 dcb_dhcsr = 0;
int retval, timeout = 0;
-
- /* Check that we are using process_context, or change and print warning */
- if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
- {
- LOG_DEBUG("Changing to process contex registers");
- armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
- }
/* Enter debug state on reset, cf. end_reset_event() */
ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET );
return ERROR_OK;
}
-int cortex_m3_prepare_reset_halt(struct target_s *target)
-{
- armv7m_common_t *armv7m = target->arch_info;
- cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
- swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
- u32 dcb_demcr, dcb_dhcsr;
-
- /* Enable debug requests */
- ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
- if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
- ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN );
-
- /* Enter debug state on reset, cf. end_reset_event() */
- ahbap_write_system_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET );
-
- ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
- ahbap_read_system_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
- LOG_DEBUG("dcb_dhcsr 0x%x, dcb_demcr 0x%x, ", dcb_dhcsr, dcb_demcr);
-
- return ERROR_OK;
-}
-
int cortex_m3_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
{
/* get pointers to arch-specific information */
if (!debug_execution)
{
- /* Check that we are using process_context, or change and print warning */
- if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
- {
- LOG_DEBUG("Incorrect context in resume");
- armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
- }
-
target_free_all_working_areas(target);
cortex_m3_enable_breakpoints(target);
cortex_m3_enable_watchpoints(target);
dcb_dhcsr = DBGKEY | C_DEBUGEN;
if (debug_execution)
{
- /* Check that we are using debug_context, or change and print warning */
- if (armv7m_get_context(target) != ARMV7M_DEBUG_CONTEXT)
- {
- LOG_DEBUG("Incorrect context in debug_exec resume");
- armv7m_use_context(target, ARMV7M_DEBUG_CONTEXT);
- }
/* Disable interrupts */
/*
We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
/* Single step past breakpoint at current address */
if ((breakpoint = breakpoint_find(target, resume_pc)))
{
- LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
- cortex_m3_unset_breakpoint(target, breakpoint);
- cortex_m3_single_step_core(target);
- cortex_m3_set_breakpoint(target, breakpoint);
+ LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
+ cortex_m3_unset_breakpoint(target, breakpoint);
+ cortex_m3_single_step_core(target);
+ cortex_m3_set_breakpoint(target, breakpoint);
}
}
LOG_WARNING("target not halted");
return ERROR_TARGET_NOT_HALTED;
}
-
- /* Check that we are using process_context, or change and print warning */
- if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
- {
- LOG_WARNING("Incorrect context in step, must be process");
- armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
- }
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current)
ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY| C_STEP | C_DEBUGEN);
ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
- /* If we run in process context then registers are now invalid */
- if (armv7m_get_context(target) == ARMV7M_PROCESS_CONTEXT)
- armv7m_invalidate_core_regs(target);
+ /* registers are now invalid */
+ armv7m_invalidate_core_regs(target);
if (breakpoint)
cortex_m3_set_breakpoint(target, breakpoint);
armv7m_common_t *armv7m = target->arch_info;
cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
- int retval;
+ int assert_srst = 1;
LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
LOG_ERROR("Can't assert SRST");
return ERROR_FAIL;
}
- /* FIX!!! should this be removed as we're asserting trst anyway? */
- if ((retval=cortex_m3_prepare_reset_halt(target))!=ERROR_OK)
- return retval;
+ /* Enable debug requests */
+ ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
+ if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
+ ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN );
+
ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 );
if (target->reset_mode == RESET_RUN)
cortex_m3_clear_halt(target);
/* Enter debug state on reset, cf. end_reset_event() */
- ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN );
ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
}
+ else
+ {
+ /* Enter debug state on reset, cf. end_reset_event() */
+ ahbap_write_system_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET );
+ }
- if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN)
+ /* following hack is to handle luminary reset
+ * when srst is asserted the luminary device seesm to also clear the debug registers
+ * which does not match the armv7 debug TRM */
+
+ if (strcmp(cortex_m3->variant, "lm3s") == 0)
{
- /* assert SRST and TRST */
- /* system would get ouf sync if we didn't reset test-logic, too */
- jtag_add_reset(1, 1);
- jtag_add_sleep(5000);
+ /* get revision of lm3s target, only early silicon has this issue
+ * Fury Rev B, DustDevil Rev B, Tempest all ok */
+
+ u32 did0;
+
+ if (target_read_u32(target, 0x400fe000, &did0) == ERROR_OK)
+ {
+ switch ((did0 >> 16) & 0xff)
+ {
+ case 0:
+ /* all Sandstorm suffer issue */
+ assert_srst = 0;
+ break;
+
+ case 1:
+ case 3:
+ /* only Fury/DustDevil rev A suffer reset problems */
+ if (((did0 >> 8) & 0xff) == 0)
+ assert_srst = 0;
+ break;
+ }
+ }
}
-
- if (jtag_reset_config & RESET_SRST_PULLS_TRST)
+
+ if (assert_srst)
{
- jtag_add_reset(1, 1);
- } else
+ /* default to asserting srst */
+ if (jtag_reset_config & RESET_SRST_PULLS_TRST)
+ {
+ jtag_add_reset(1, 1);
+ }
+ else
+ {
+ jtag_add_reset(0, 1);
+ }
+ }
+ else
{
- jtag_add_reset(0, 1);
+ /* this causes the luminary device to reset using the watchdog */
+ ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ );
+ LOG_DEBUG("Using Luminary Reset: SYSRESETREQ");
}
target->state = TARGET_RESET;
jtag_add_sleep(50000);
- #if 0
- if ((target->reset_mode==RESET_HALT)||(target->reset_mode==RESET_INIT))
- {
- cortex_m3_halt(target);
- }
- #endif
- armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
armv7m_invalidate_core_regs(target);
return ERROR_OK;
return ERROR_OK;
}
-void cortex_m3_unset_all_breakpoints_and_watchpoints(struct target_s *target)
-{
-
-}
-
void cortex_m3_enable_breakpoints(struct target_s *target)
{
breakpoint_t *breakpoint = target->breakpoints;
LOG_WARNING("breakpoint already set");
return ERROR_OK;
}
-
+
if (cortex_m3->auto_bp_type)
{
breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
/* get pointers to arch-specific information */
armv7m_common_t *armv7m = target->arch_info;
cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
-
+
if (cortex_m3->auto_bp_type)
{
breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
+#ifdef ARMV7_GDB_HACKS
+ if (breakpoint->length != 2) {
+ /* XXX Hack: Replace all breakpoints with length != 2 with
+ * a hardware breakpoint. */
+ breakpoint->type = BKPT_HARD;
+ breakpoint->length = 2;
+ }
+#endif
}
if ((breakpoint->type == BKPT_HARD) && (breakpoint->address >= 0x20000000))
else if (type == ARMV7M_REGISTER_CORE_SP) /* Special purpose core register */
{
/* read other registers */
- u32 savedram;
- u32 SYSm;
- u32 instr;
- SYSm = num & 0x1F;
+ ahbap_read_coreregister_u32(swjdp, value, 20);
- ahbap_read_system_u32(swjdp, 0x20000000, &savedram);
- instr = ARMV7M_T_MRS(0, SYSm);
- ahbap_write_system_u32(swjdp, 0x20000000, ARMV7M_T_MRS(0, SYSm));
- ahbap_write_coreregister_u32(swjdp, 0x20000000, 15);
- cortex_m3_single_step_core(target);
- ahbap_read_coreregister_u32(swjdp, value, 0);
- armv7m->core_cache->reg_list[0].dirty = armv7m->core_cache->reg_list[0].valid;
- armv7m->core_cache->reg_list[15].dirty = armv7m->core_cache->reg_list[15].valid;
- ahbap_write_system_u32(swjdp, 0x20000000, savedram);
- swjdp_transaction_endcheck(swjdp);
- LOG_DEBUG("load from special reg %i value 0x%x", SYSm, *value);
+ switch (num)
+ {
+ case 19:
+ *value = buf_get_u32((u8*)value, 0, 8);
+ break;
+
+ case 20:
+ *value = buf_get_u32((u8*)value, 8, 8);
+ break;
+
+ case 21:
+ *value = buf_get_u32((u8*)value, 16, 8);
+ break;
+
+ case 22:
+ *value = buf_get_u32((u8*)value, 24, 8);
+ break;
+ }
+
+ LOG_DEBUG("load from special reg %i value 0x%x", num, *value);
}
else
{
int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype type, u32 num, u32 value)
{
int retval;
+ u32 reg;
/* get pointers to arch-specific information */
armv7m_common_t *armv7m = target->arch_info;
cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+#ifdef ARMV7_GDB_HACKS
+ /* If the LR register is being modified, make sure it will put us
+ * in "thumb" mode, or an INVSTATE exception will occur. This is a
+ * hack to deal with the fact that gdb will sometimes "forge"
+ * return addresses, and doesn't set the LSB correctly (i.e., when
+ * printing expressions containing function calls, it sets LR=0.) */
+
+ if (num == 14)
+ value |= 0x01;
+#endif
+
if ((type == ARMV7M_REGISTER_CORE_GP) && (num <= ARMV7M_PSP))
{
retval = ahbap_write_coreregister_u32(swjdp, value, num);
else if (type == ARMV7M_REGISTER_CORE_SP) /* Special purpose core register */
{
/* write other registers */
- u32 savedram , tempr0;
- u32 SYSm;
- u32 instr;
- SYSm = num & 0x1F;
- ahbap_read_system_u32(swjdp, 0x20000000, &savedram);
- instr = ARMV7M_T_MSR(SYSm, 0);
- ahbap_write_system_u32(swjdp, 0x20000000, ARMV7M_T_MSR(SYSm, 0));
- ahbap_read_coreregister_u32(swjdp, &tempr0, 0);
- ahbap_write_coreregister_u32(swjdp, value, 0);
- ahbap_write_coreregister_u32(swjdp, 0x20000000, 15);
- cortex_m3_single_step_core(target);
- ahbap_write_coreregister_u32(swjdp, tempr0, 0);
- armv7m->core_cache->reg_list[15].dirty = armv7m->core_cache->reg_list[15].valid;
- ahbap_write_system_u32(swjdp, 0x20000000, savedram);
- swjdp_transaction_endcheck(swjdp);
- LOG_DEBUG("write special reg %i value 0x%x ", SYSm, value);
+ ahbap_read_coreregister_u32(swjdp, ®, 20);
+
+ switch (num)
+ {
+ case 19:
+ buf_set_u32((u8*)®, 0, 8, value);
+ break;
+
+ case 20:
+ buf_set_u32((u8*)®, 8, 8, value);
+ break;
+
+ case 21:
+ buf_set_u32((u8*)®, 16, 8, value);
+ break;
+
+ case 22:
+ buf_set_u32((u8*)®, 24, 8, value);
+ break;
+ }
+
+ ahbap_write_coreregister_u32(swjdp, reg, 20);
+
+ LOG_DEBUG("write special reg %i value 0x%x ", num, value);
}
else
{
int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
{
+ cortex_m3_build_reg_cache(target);
+ return ERROR_OK;
+}
+
+int cortex_m3_examine(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+ int retval;
u32 cpuid, fpcr, dwtcr, ictr;
int i;
armv7m_common_t *armv7m = target->arch_info;
cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+
+ target->type->examined = 1;
- cortex_m3_build_reg_cache(target);
- ahbap_debugport_init(swjdp);
+ if ((retval=ahbap_debugport_init(swjdp))!=ERROR_OK)
+ return retval;
/* Read from Device Identification Registers */
- target_read_u32(target, CPUID, &cpuid);
+ if ((retval=target_read_u32(target, CPUID, &cpuid))!=ERROR_OK)
+ return retval;
+
if (((cpuid >> 4) & 0xc3f) == 0xc23)
LOG_DEBUG("CORTEX-M3 processor detected");
LOG_DEBUG("cpuid: 0x%8.8x", cpuid);
int cortex_m3_handle_target_request(void *priv)
{
target_t *target = priv;
+ if (!target->type->examined)
+ return ERROR_OK;
armv7m_common_t *armv7m = target->arch_info;
cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
armv7m->pre_restore_context = NULL;
armv7m->post_restore_context = NULL;
+ if (variant)
+ {
+ cortex_m3->variant = strdup(variant);
+ }
+ else
+ {
+ cortex_m3->variant = strdup("");
+ }
+
armv7m_init_arch_info(target, armv7m);
armv7m->arch_info = cortex_m3;
armv7m->load_core_reg_u32 = cortex_m3_load_core_reg_u32;
variant = args[4];
cortex_m3_init_arch_info(target, cortex_m3, chain_pos, variant);
- cortex_m3_register_commands(cmd_ctx);
return ERROR_OK;
}