X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m3.c;h=a90baafaf57f96fcdf48bb235448b9faeee4c191;hp=19b0a758bdaad524ac1bc220c934db8853fb5e29;hb=c1ee650a9aead0bd25d7aa37fd65e5a3ed0c6e38;hpb=35b3c95299a97c05078f7dd662d66c89a356869d diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index 19b0a758bd..a90baafaf5 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -43,16 +43,20 @@ 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 = { @@ -77,6 +81,7 @@ 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, @@ -88,6 +93,7 @@ target_type_t cortexm3_target = .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 }; @@ -201,8 +207,6 @@ int cortex_m3_endreset_event(target_t *target) } swjdp_transaction_endcheck(swjdp); - /* We are in process context */ - armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT); armv7m_invalidate_core_regs(target); return ERROR_OK; } @@ -315,7 +319,15 @@ int cortex_m3_debug_entry(target_t *target) } 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) { @@ -323,16 +335,25 @@ int cortex_m3_debug_entry(target_t *target) 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); @@ -412,9 +433,12 @@ int cortex_m3_poll(target_t *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; } @@ -472,13 +496,6 @@ int cortex_m3_soft_reset_halt(struct target_s *target) 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 ); @@ -512,28 +529,6 @@ int cortex_m3_soft_reset_halt(struct target_s *target) 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 */ @@ -551,13 +546,6 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand 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); @@ -568,12 +556,6 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand 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, @@ -604,10 +586,10 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand /* 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); } } @@ -651,13 +633,6 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle 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
*/ if (!current) @@ -679,9 +654,8 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle 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); @@ -700,7 +674,7 @@ int cortex_m3_assert_reset(target_t *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; - int retval; + int assert_srst = 1; LOG_DEBUG("target->state: %s", target_state_strings[target->state]); @@ -709,10 +683,12 @@ int cortex_m3_assert_reset(target_t *target) 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) @@ -724,36 +700,66 @@ int cortex_m3_assert_reset(target_t *target) 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; @@ -769,11 +775,6 @@ int cortex_m3_deassert_reset(target_t *target) 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; @@ -803,7 +804,7 @@ int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) LOG_WARNING("breakpoint already set"); return ERROR_OK; } - + if (cortex_m3->auto_bp_type) { breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT; @@ -885,10 +886,18 @@ int cortex_m3_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint) /* 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)) @@ -1118,22 +1127,28 @@ int cortex_m3_load_core_reg_u32(struct target_s *target, enum armv7m_regtype typ 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 { @@ -1146,12 +1161,24 @@ int cortex_m3_load_core_reg_u32(struct target_s *target, enum armv7m_regtype typ 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); @@ -1166,23 +1193,31 @@ int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype ty 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 { @@ -1268,6 +1303,13 @@ void cortex_m3_build_reg_cache(target_t *target) 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; @@ -1275,12 +1317,16 @@ int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *ta 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); @@ -1369,6 +1415,8 @@ int cortex_m3_target_request_data(target_t *target, u32 size, u8 *buffer) 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; @@ -1431,6 +1479,15 @@ int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, in 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; @@ -1461,7 +1518,6 @@ int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char variant = args[4]; cortex_m3_init_arch_info(target, cortex_m3, chain_pos, variant); - cortex_m3_register_commands(cmd_ctx); return ERROR_OK; }