X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m3.c;h=ee9ee2577f7cef6599491a73eaee029d74849b20;hb=5f993dc17c92630514287f886cffefc560a98c42;hp=fb303a8be2943c9017e7604ef8b917d3eb3c8853;hpb=dd5bc1f89399894ea31f61c2cd28f6390e1b7e50;p=openocd.git diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index fb303a8be2..ee9ee2577f 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -5,6 +5,9 @@ * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -45,13 +48,18 @@ int cortex_m3_register_commands(struct command_context_s *cmd_ctx); /* forward declarations */ void cortex_m3_enable_breakpoints(struct target_s *target); void cortex_m3_enable_watchpoints(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_target_create(struct target_s *target, Jim_Interp *interp); int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target); -int cortex_m3_quit(); +int cortex_m3_quit(void); 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); +int cortex_m3_examine(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 = { @@ -76,6 +84,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, @@ -85,7 +94,7 @@ target_type_t cortexm3_target = .remove_watchpoint = cortex_m3_remove_watchpoint, .register_commands = cortex_m3_register_commands, - .target_command = cortex_m3_target_command, + .target_create = cortex_m3_target_create, .init_target = cortex_m3_init_target, .examine = cortex_m3_examine, .quit = cortex_m3_quit @@ -97,14 +106,14 @@ int cortex_m3_clear_halt(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; - - /* Read Debug Fault Status Register */ - ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr); - /* Write Debug Fault Status Register to enable processing to resume ?? Try with and without this !! */ - ahbap_write_system_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr); - LOG_DEBUG(" NVIC_DFSR 0x%x", cortex_m3->nvic_dfsr); - - return ERROR_OK; + + /* Read Debug Fault Status Register */ + ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr); + /* Write Debug Fault Status Register to enable processing to resume ?? Try with and without this !! */ + ahbap_write_system_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr); + LOG_DEBUG(" NVIC_DFSR 0x%x", cortex_m3->nvic_dfsr); + + return ERROR_OK; } int cortex_m3_single_step_core(target_t *target) @@ -278,8 +287,8 @@ int cortex_m3_examine_exception_reason(target_t *target) break; } swjdp_transaction_endcheck(swjdp); - LOG_DEBUG("%s SHCSR 0x%x, SR 0x%x, CFSR 0x%x, AR 0x%x", armv7m_exception_string(armv7m->exception_number), \ - shcsr, except_sr, cfsr, except_ar); + LOG_DEBUG("%s SHCSR 0x%x, SR 0x%x, CFSR 0x%x, AR 0x%x", armv7m_exception_string(armv7m->exception_number), \ + shcsr, except_sr, cfsr, except_ar); return ERROR_OK; } @@ -313,7 +322,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) { @@ -345,8 +362,10 @@ int cortex_m3_debug_entry(target_t *target) cortex_m3_examine_exception_reason(target); } - LOG_DEBUG("entered debug state in core mode: %s at PC 0x%x, target->state: %s", armv7m_mode_strings[armv7m->core_mode], \ - *(u32*)(armv7m->core_cache->reg_list[15].value), target_state_strings[target->state]); + LOG_DEBUG("entered debug state in core mode: %s at PC 0x%x, target->state: %s", + armv7m_mode_strings[armv7m->core_mode], + *(u32*)(armv7m->core_cache->reg_list[15].value), + Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name); if (armv7m->post_debug_entry) armv7m->post_debug_entry(target); @@ -357,7 +376,7 @@ int cortex_m3_debug_entry(target_t *target) int cortex_m3_poll(target_t *target) { int retval; - u32 prev_target_state = target->state; + enum target_state prev_target_state = target->state; /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; @@ -420,9 +439,9 @@ int cortex_m3_poll(target_t *target) */ #if 0 - /* Read Debug Fault Status Register, added to figure out the lockup when running flashtest.script */ + /* 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]); + LOG_DEBUG("dcb_dhcsr 0x%x, nvic_dfsr 0x%x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, Jim_Nvp_value2name( nvp_target_state, target->state )->name ); #endif return ERROR_OK; @@ -435,7 +454,8 @@ int cortex_m3_halt(target_t *target) cortex_m3_common_t *cortex_m3 = armv7m->arch_info; swjdp_common_t *swjdp = &cortex_m3->swjdp_info; - LOG_DEBUG("target->state: %s", target_state_strings[target->state]); + LOG_DEBUG("target->state: %s", + Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name ); if (target->state == TARGET_HALTED) { @@ -498,7 +518,7 @@ int cortex_m3_soft_reset_halt(struct target_s *target) retval = ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr); if (retval == ERROR_OK) { - ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr); + ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr); if ((dcb_dhcsr & S_HALT) && (cortex_m3->nvic_dfsr & DFSR_VCATCH)) { LOG_DEBUG("system reset-halted, dcb_dhcsr 0x%x, nvic_dfsr 0x%x", dcb_dhcsr, cortex_m3->nvic_dfsr); @@ -509,7 +529,7 @@ int cortex_m3_soft_reset_halt(struct target_s *target) LOG_DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%x, %i ms", dcb_dhcsr, timeout); } timeout++; - usleep(1000); + alive_sleep(1); } return ERROR_OK; @@ -543,11 +563,9 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand if (debug_execution) { /* Disable interrupts */ - /* - We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS, - This is probably the same inssue as Cortex-M3 Errata 377493: - C_MASKINTS in parallel with disabled interrupts can cause local faults to not be taken. - */ + /* We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS, + * This is probably the same inssue as Cortex-M3 Errata 377493: + * C_MASKINTS in parallel with disabled interrupts can cause local faults to not be taken. */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1); /* Make sure we are in Thumb mode */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32, @@ -634,7 +652,7 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle armv7m_restore_context(target); target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - + if (cortex_m3->dcb_dhcsr & C_MASKINTS) ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN ); ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY| C_STEP | C_DEBUGEN); @@ -660,8 +678,10 @@ 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 assert_srst = 1; - LOG_DEBUG("target->state: %s", target_state_strings[target->state]); + LOG_DEBUG("target->state: %s", + Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name ); if (!(jtag_reset_config & RESET_HAS_SRST)) { @@ -676,7 +696,7 @@ int cortex_m3_assert_reset(target_t *target) ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 ); - if (target->reset_mode == RESET_RUN) + if (!target->reset_halt) { /* Set/Clear C_MASKINTS in a separate operation */ if (cortex_m3->dcb_dhcsr & C_MASKINTS) @@ -693,13 +713,60 @@ int cortex_m3_assert_reset(target_t *target) ahbap_write_system_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET ); } - if (jtag_reset_config & RESET_SRST_PULLS_TRST) + /* 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) { - jtag_add_reset(1, 1); + /* 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 (assert_srst) + { + /* 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"); + + { + /* I do not know why this is necessary, but it fixes strange effects + * (step/resume cause a NMI after reset) on LM3S6918 -- Michael Schwingen */ + u32 tmp; + ahbap_read_system_atomic_u32(swjdp, NVIC_AIRCR, &tmp ); + } } target->state = TARGET_RESET; @@ -707,12 +774,20 @@ int cortex_m3_assert_reset(target_t *target) armv7m_invalidate_core_regs(target); + if (target->reset_halt) + { + int retval; + if ((retval = target_halt(target))!=ERROR_OK) + return retval; + } + return ERROR_OK; } int cortex_m3_deassert_reset(target_t *target) { - LOG_DEBUG("target->state: %s", target_state_strings[target->state]); + LOG_DEBUG("target->state: %s", + Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name); /* deassert reset lines */ jtag_add_reset(0, 0); @@ -735,6 +810,7 @@ void cortex_m3_enable_breakpoints(struct target_s *target) int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) { + int retval; int fp_num=0; u32 hilo; @@ -749,7 +825,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; @@ -776,8 +852,14 @@ int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) { u8 code[4]; buf_set_u32(code, 0, 32, ARMV7M_T_BKPT(0x11)); - target->type->read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr); - target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code); + if((retval = target->type->read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK) + { + return retval; + } + if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code)) != ERROR_OK) + { + return retval; + } breakpoint->set = 0x11; /* Any nice value but 0 */ } @@ -786,6 +868,7 @@ int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint) { + int retval; /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; cortex_m3_common_t *cortex_m3 = armv7m->arch_info; @@ -814,11 +897,17 @@ int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { - target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr); + if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr)) != ERROR_OK) + { + return retval; + } } else { - target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr); + if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr)) != ERROR_OK) + { + return retval; + } } } breakpoint->set = 0; @@ -835,12 +924,14 @@ int cortex_m3_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint) if (cortex_m3->auto_bp_type) { breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT; - if (breakpoint->length != 2) { - // XXX Hack: Replace all breakpoints with length != 2 with - // a hardware breakpoint. - breakpoint->type = BKPT_HARD; - breakpoint->length = 2; - } +#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)) @@ -1111,14 +1202,17 @@ int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype ty cortex_m3_common_t *cortex_m3 = armv7m->arch_info; swjdp_common_t *swjdp = &cortex_m3->swjdp_info; - // 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; - +#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); @@ -1247,7 +1341,7 @@ int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *ta return ERROR_OK; } -int cortex_m3_examine(struct command_context_s *cmd_ctx, struct target_s *target) +int cortex_m3_examine(struct target_s *target) { int retval; u32 cpuid, fpcr, dwtcr, ictr; @@ -1307,8 +1401,7 @@ int cortex_m3_examine(struct command_context_s *cmd_ctx, struct target_s *target return ERROR_OK; } - -int cortex_m3_quit() +int cortex_m3_quit(void) { return ERROR_OK; @@ -1392,7 +1485,7 @@ int cortex_m3_handle_target_request(void *priv) return ERROR_OK; } -int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, int chain_pos, char *variant) +int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, int chain_pos, const char *variant) { armv7m_common_t *armv7m; armv7m = &cortex_m3->armv7m; @@ -1420,6 +1513,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; @@ -1430,27 +1532,11 @@ int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, in return ERROR_OK; } -/* target cortex_m3 */ -int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target) +int cortex_m3_target_create(struct target_s *target, Jim_Interp *interp) { - int chain_pos; - char *variant = NULL; - cortex_m3_common_t *cortex_m3 = malloc(sizeof(cortex_m3_common_t)); - memset(cortex_m3, 0, sizeof(*cortex_m3)); - - if (argc < 4) - { - LOG_ERROR("'target cortex_m3' requires at least one additional argument"); - exit(-1); - } - - chain_pos = strtoul(args[3], NULL, 0); + cortex_m3_common_t *cortex_m3 = calloc(1,sizeof(cortex_m3_common_t)); - if (argc >= 5) - variant = args[4]; - - cortex_m3_init_arch_info(target, cortex_m3, chain_pos, variant); - cortex_m3_register_commands(cmd_ctx); + cortex_m3_init_arch_info(target, cortex_m3, target->chain_position, target->variant); return ERROR_OK; } @@ -1463,4 +1549,3 @@ int cortex_m3_register_commands(struct command_context_s *cmd_ctx) return retval; } -