X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m3.c;h=7125e5af590f0009b1717b93ea7cde5b8305c399;hp=a90baafaf57f96fcdf48bb235448b9faeee4c191;hb=503bb08f9993c59a4b3206600555a42fd18459b6;hpb=85fc1e06fa086dc12dddf20d826d705e6505250d diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index a90baafaf5..7125e5af59 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 * @@ -41,17 +44,18 @@ /* cli handling */ int cortex_m3_register_commands(struct command_context_s *cmd_ctx); +int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); /* 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[]; @@ -91,26 +95,44 @@ 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 }; +int cortex_m3_write_debug_halt_mask(target_t *target, u32 mask_on, u32 mask_off) +{ + /* 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; + + /* mask off status bits */ + cortex_m3->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off); + /* create new register mask */ + cortex_m3->dcb_dhcsr |= DBGKEY | C_DEBUGEN | mask_on; + + return ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, cortex_m3->dcb_dhcsr); +} + int cortex_m3_clear_halt(target_t *target) { /* 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; - - /* 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; + + /* clear step if any */ + cortex_m3_write_debug_halt_mask(target, C_HALT, C_STEP); + + /* 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) @@ -119,12 +141,19 @@ int cortex_m3_single_step_core(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; - + u32 dhcsr_save; + + /* backup dhcsr reg */ + dhcsr_save = cortex_m3->dcb_dhcsr; + + /* mask interrupts if not done already */ if (!(cortex_m3->dcb_dhcsr & C_MASKINTS)) - ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN ); - ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN ); - cortex_m3->dcb_dhcsr |= C_MASKINTS; + ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN); + ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN); LOG_DEBUG(" "); + + /* restore dhcsr reg */ + cortex_m3->dcb_dhcsr = dhcsr_save; cortex_m3_clear_halt(target); return ERROR_OK; @@ -144,7 +173,7 @@ int cortex_m3_exec_opcode(target_t *target,u32 opcode, int len /* MODE, r0_inval ahbap_write_coreregister_u32(swjdp, 0x20000000, 15); cortex_m3_single_step_core(target); armv7m->core_cache->reg_list[15].dirty = armv7m->core_cache->reg_list[15].valid; - retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram); + retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram); return retvalue; } @@ -178,16 +207,21 @@ int cortex_m3_endreset_event(target_t *target) ahbap_read_system_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr); LOG_DEBUG("DCB_DEMCR = 0x%8.8x",dcb_demcr); - ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 ); + /* this regsiter is used for emulated dcc channel */ + ahbap_write_system_u32(swjdp, DCB_DCRDR, 0); /* 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_DHCSR, DBGKEY | C_DEBUGEN); + + /* clear any interrupt masking */ + cortex_m3_write_debug_halt_mask(target, 0, C_MASKINTS); + /* Enable trace and dwt */ - ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR ); + ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR); /* Monitor bus faults */ - ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA ); + ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA); /* Enable FPB */ target_write_u32(target, FP_CTRL, 3); @@ -284,8 +318,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; } @@ -359,8 +393,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); @@ -371,7 +407,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; @@ -434,9 +470,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_simple( nvp_target_state, target->state )->name ); #endif return ERROR_OK; @@ -444,12 +480,8 @@ int cortex_m3_poll(target_t *target) int cortex_m3_halt(target_t *target) { - /* 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; - - 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) { @@ -481,7 +513,7 @@ int cortex_m3_halt(target_t *target) } /* Write to Debug Halting Control and Status Register */ - ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT ); + cortex_m3_write_debug_halt_mask(target, C_HALT, 0); target->debug_reason = DBG_REASON_DBGRQ; @@ -498,10 +530,10 @@ int cortex_m3_soft_reset_halt(struct target_s *target) int retval, timeout = 0; /* Enter debug state on reset, cf. end_reset_event() */ - ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET ); + ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); /* Request a reset */ - ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET ); + ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET); target->state = TARGET_RESET; /* registers are now invalid */ @@ -512,7 +544,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); @@ -523,7 +555,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; @@ -533,10 +565,8 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand { /* 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; breakpoint_t *breakpoint = NULL; - u32 dcb_dhcsr, resume_pc; + u32 resume_pc; if (target->state != TARGET_HALTED) { @@ -549,23 +579,23 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand target_free_all_working_areas(target); cortex_m3_enable_breakpoints(target); cortex_m3_enable_watchpoints(target); - - /* TODOLATER Interrupt handling/disable for debug execution, cache ... ... */ } - dcb_dhcsr = DBGKEY | C_DEBUGEN; 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 issue 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); + armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1; + armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1; + /* Make sure we are in Thumb mode */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32, buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1<<24)); + armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1; + armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1; } /* current = 1: continue on current pc, otherwise continue at
*/ @@ -592,13 +622,10 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand cortex_m3_set_breakpoint(target, breakpoint); } } - - /* Set/Clear C_MASKINTS in a separate operation */ - if ((cortex_m3->dcb_dhcsr & C_MASKINTS) != (dcb_dhcsr & C_MASKINTS)) - ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, dcb_dhcsr | C_HALT ); /* Restart core */ - ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, dcb_dhcsr ); + cortex_m3_write_debug_halt_mask(target, 0, C_HALT); + target->debug_reason = DBG_REASON_NOTHALTED; /* registers are now invalid */ @@ -607,13 +634,13 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - LOG_DEBUG("target resumed at 0x%x",resume_pc); + LOG_DEBUG("target resumed at 0x%x", resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); - LOG_DEBUG("target debug resumed at 0x%x",resume_pc); + LOG_DEBUG("target debug resumed at 0x%x", resume_pc); } return ERROR_OK; @@ -648,10 +675,9 @@ 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); + + /* set step and clear halt */ + cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT); ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr); /* registers are now invalid */ @@ -676,7 +702,8 @@ int cortex_m3_assert_reset(target_t *target) 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)) { @@ -687,15 +714,15 @@ int cortex_m3_assert_reset(target_t *target) /* 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_DHCSR, DBGKEY | C_DEBUGEN); 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) - ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT ); + ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT); cortex_m3_clear_halt(target); @@ -705,7 +732,7 @@ int cortex_m3_assert_reset(target_t *target) 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 ); + ahbap_write_system_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); } /* following hack is to handle luminary reset @@ -753,8 +780,15 @@ int cortex_m3_assert_reset(target_t *target) else { /* this causes the luminary device to reset using the watchdog */ - ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ ); + 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; @@ -762,12 +796,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); @@ -790,6 +832,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; @@ -804,7 +847,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; @@ -831,8 +874,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 */ } @@ -841,6 +890,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; @@ -869,11 +919,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; @@ -1307,7 +1363,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; @@ -1318,56 +1374,59 @@ int cortex_m3_examine(struct command_context_s *cmd_ctx, struct target_s *target cortex_m3_common_t *cortex_m3 = armv7m->arch_info; swjdp_common_t *swjdp = &cortex_m3->swjdp_info; - target->type->examined = 1; - - if ((retval=ahbap_debugport_init(swjdp))!=ERROR_OK) - return retval; - - /* Read from Device Identification Registers */ - if ((retval=target_read_u32(target, CPUID, &cpuid))!=ERROR_OK) + if ((retval = ahbap_debugport_init(swjdp)) != ERROR_OK) return retval; - if (((cpuid >> 4) & 0xc3f) == 0xc23) - LOG_DEBUG("CORTEX-M3 processor detected"); - LOG_DEBUG("cpuid: 0x%8.8x", cpuid); - - target_read_u32(target, NVIC_ICTR, &ictr); - cortex_m3->intlinesnum = (ictr & 0x1F) + 1; - cortex_m3->intsetenable = calloc(cortex_m3->intlinesnum, 4); - for (i = 0; i < cortex_m3->intlinesnum; i++) - { - target_read_u32(target, NVIC_ISE0 + 4 * i, cortex_m3->intsetenable + i); - LOG_DEBUG("interrupt enable[%i] = 0x%8.8x", i, cortex_m3->intsetenable[i]); - } - - /* Setup FPB */ - target_read_u32(target, FP_CTRL, &fpcr); - cortex_m3->auto_bp_type = 1; - cortex_m3->fp_num_code = (fpcr >> 4) & 0xF; - cortex_m3->fp_num_lit = (fpcr >> 8) & 0xF; - cortex_m3->fp_code_available = cortex_m3->fp_num_code; - cortex_m3->fp_comparator_list = calloc(cortex_m3->fp_num_code + cortex_m3->fp_num_lit, sizeof(cortex_m3_fp_comparator_t)); - for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++) + if (!target->type->examined) { - 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; - } - LOG_DEBUG("FPB fpcr 0x%x, numcode %i, numlit %i", fpcr, cortex_m3->fp_num_code, cortex_m3->fp_num_lit); + target->type->examined = 1; - /* Setup DWT */ - target_read_u32(target, DWT_CTRL, &dwtcr); - cortex_m3->dwt_num_comp = (dwtcr >> 28) & 0xF; - cortex_m3->dwt_comp_available = cortex_m3->dwt_num_comp; - cortex_m3->dwt_comparator_list=calloc(cortex_m3->dwt_num_comp, sizeof(cortex_m3_dwt_comparator_t)); - for (i = 0; i < cortex_m3->dwt_num_comp; i++) - { - cortex_m3->dwt_comparator_list[i].dwt_comparator_address = DWT_COMP0 + 0x10 * i; + /* Read from Device Identification Registers */ + 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); + + target_read_u32(target, NVIC_ICTR, &ictr); + cortex_m3->intlinesnum = (ictr & 0x1F) + 1; + cortex_m3->intsetenable = calloc(cortex_m3->intlinesnum, 4); + for (i = 0; i < cortex_m3->intlinesnum; i++) + { + target_read_u32(target, NVIC_ISE0 + 4 * i, cortex_m3->intsetenable + i); + LOG_DEBUG("interrupt enable[%i] = 0x%8.8x", i, cortex_m3->intsetenable[i]); + } + + /* Setup FPB */ + target_read_u32(target, FP_CTRL, &fpcr); + cortex_m3->auto_bp_type = 1; + cortex_m3->fp_num_code = (fpcr >> 4) & 0xF; + cortex_m3->fp_num_lit = (fpcr >> 8) & 0xF; + cortex_m3->fp_code_available = cortex_m3->fp_num_code; + cortex_m3->fp_comparator_list = calloc(cortex_m3->fp_num_code + cortex_m3->fp_num_lit, sizeof(cortex_m3_fp_comparator_t)); + 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; + cortex_m3->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i; + } + LOG_DEBUG("FPB fpcr 0x%x, numcode %i, numlit %i", fpcr, cortex_m3->fp_num_code, cortex_m3->fp_num_lit); + + /* Setup DWT */ + target_read_u32(target, DWT_CTRL, &dwtcr); + cortex_m3->dwt_num_comp = (dwtcr >> 28) & 0xF; + cortex_m3->dwt_comp_available = cortex_m3->dwt_num_comp; + cortex_m3->dwt_comparator_list = calloc(cortex_m3->dwt_num_comp, sizeof(cortex_m3_dwt_comparator_t)); + for (i = 0; i < cortex_m3->dwt_num_comp; i++) + { + cortex_m3->dwt_comparator_list[i].dwt_comparator_address = DWT_COMP0 + 0x10 * i; + } } return ERROR_OK; } -int cortex_m3_quit() +int cortex_m3_quit(void) { return ERROR_OK; @@ -1451,13 +1510,13 @@ 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, jtag_tap_t *tap, const char *variant) { armv7m_common_t *armv7m; armv7m = &cortex_m3->armv7m; /* prepare JTAG information for the new target */ - cortex_m3->jtag_info.chain_pos = chain_pos; + cortex_m3->jtag_info.tap = tap; cortex_m3->jtag_info.scann_size = 4; cortex_m3->swjdp_info.dp_select_value = -1; @@ -1498,26 +1557,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); - } + cortex_m3_common_t *cortex_m3 = calloc(1,sizeof(cortex_m3_common_t)); - chain_pos = strtoul(args[3], NULL, 0); - - if (argc >= 5) - variant = args[4]; - - cortex_m3_init_arch_info(target, cortex_m3, chain_pos, variant); + cortex_m3_init_arch_info(target, cortex_m3, target->tap, target->variant); return ERROR_OK; } @@ -1525,8 +1569,46 @@ int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char int cortex_m3_register_commands(struct command_context_s *cmd_ctx) { int retval; + command_t *cortex_m3_cmd; retval = armv7m_register_commands(cmd_ctx); + cortex_m3_cmd = register_command(cmd_ctx, NULL, "cortex_m3", NULL, COMMAND_ANY, "cortex_m3 specific commands"); + register_command(cmd_ctx, cortex_m3_cmd, "maskisr", handle_cortex_m3_mask_interrupts_command, COMMAND_EXEC, "mask cortex_m3 interrupts ['on'|'off']"); + return retval; } + +int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + target_t *target = get_current_target(cmd_ctx); + armv7m_common_t *armv7m = target->arch_info; + cortex_m3_common_t *cortex_m3 = armv7m->arch_info; + + if (target->state != TARGET_HALTED) + { + command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd); + return ERROR_OK; + } + + if (argc > 0) + { + if (!strcmp(args[0], "on")) + { + cortex_m3_write_debug_halt_mask(target, C_HALT|C_MASKINTS, 0); + } + else if (!strcmp(args[0], "off")) + { + cortex_m3_write_debug_halt_mask(target, C_HALT, C_MASKINTS); + } + else + { + command_print(cmd_ctx, "usage: cortex_m3 maskisr ['on'|'off']"); + } + } + + command_print(cmd_ctx, "cortex_m3 interrupt mask %s", + (cortex_m3->dcb_dhcsr & C_MASKINTS) ? "on" : "off"); + + return ERROR_OK; +}