X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fcortex_m3.c;h=ca629cc6ff9cdbb49048ab3f9084716e9f1d32cb;hp=852326a7ac3f8212b98137ea1488621e1d5e92e5;hb=45af9d83c90134ec929599bf4a05360e8bd1e8be;hpb=eba4e394d834c5088f95412a6d3bdba622a691fc diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index 852326a7ac..ca629cc6ff 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -1,6 +1,7 @@ /*************************************************************************** * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * + * * * Copyright (C) 2006 by Magnus Lundin * * lundin@mlu.mine.nu * * * @@ -23,8 +24,6 @@ #include "config.h" #endif -#define USE_SP_REGS - #include "replacements.h" #include "cortex_m3.h" @@ -32,6 +31,7 @@ #include "register.h" #include "target.h" +#include "target_request.h" #include "log.h" #include "jtag.h" #include "arm_jtag.h" @@ -52,7 +52,8 @@ int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *ta 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); + target_type_t cortexm3_target = { .name = "cortex_m3", @@ -60,6 +61,8 @@ target_type_t cortexm3_target = .poll = cortex_m3_poll, .arch_state = armv7m_arch_state, + .target_request_data = cortex_m3_target_request_data, + .halt = cortex_m3_halt, .resume = cortex_m3_resume, .step = cortex_m3_step, @@ -74,7 +77,8 @@ target_type_t cortexm3_target = .read_memory = cortex_m3_read_memory, .write_memory = cortex_m3_write_memory, .bulk_write_memory = cortex_m3_bulk_write_memory, - + .checksum_memory = armv7m_checksum_memory, + .run_algorithm = armv7m_run_algorithm, .add_breakpoint = cortex_m3_add_breakpoint, @@ -134,12 +138,13 @@ int cortex_m3_exec_opcode(target_t *target,u32 opcode, int len /* MODE, r0_inval ahbap_write_system_u32(swjdp, 0x20000000, opcode); ahbap_write_coreregister_u32(swjdp, 0x20000000, 15); cortex_m3_single_step_core(target); - armv7m->core_cache->reg_list[15].dirty = 1; + armv7m->core_cache->reg_list[15].dirty = armv7m->core_cache->reg_list[15].valid; retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram); return retvalue; } +#if 0 /* Enable interrupts */ int cortex_m3_cpsie(target_t *target, u32 IF) { @@ -151,10 +156,12 @@ int cortex_m3_cpsid(target_t *target, u32 IF) { return cortex_m3_exec_opcode(target, ARMV7M_T_CPSID(IF), 2); } +#endif int cortex_m3_endreset_event(target_t *target) { int i; + u32 dcb_demcr; /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; @@ -163,13 +170,17 @@ int cortex_m3_endreset_event(target_t *target) cortex_m3_fp_comparator_t *fp_list = cortex_m3->fp_comparator_list; cortex_m3_dwt_comparator_t *dwt_list = cortex_m3->dwt_comparator_list; - DEBUG(" "); + ahbap_read_system_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr); + DEBUG("DCB_DEMCR = 0x%8.8x",dcb_demcr); + + 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 ); /* Enable trace and dwt */ - 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 ); /* Monitor bus faults */ ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA ); @@ -189,6 +200,7 @@ int cortex_m3_endreset_event(target_t *target) target_write_u32(target, dwt_list[i].dwt_comparator_address | 0x4, dwt_list[i].mask); target_write_u32(target, dwt_list[i].dwt_comparator_address | 0x8, dwt_list[i].function); } + swjdp_transaction_endcheck(swjdp); /* Make sure working_areas are all free */ target_free_all_working_areas(target); @@ -204,7 +216,6 @@ int cortex_m3_examine_debug_reason(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; /* 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 */ @@ -212,16 +223,15 @@ int cortex_m3_examine_debug_reason(target_t *target) if ((target->debug_reason != DBG_REASON_DBGRQ) && (target->debug_reason != DBG_REASON_SINGLESTEP)) { + /* INCOMPLETE */ - /* INCOPMPLETE */ - - if (cortex_m3->nvic_dfsr & 0x2) + if (cortex_m3->nvic_dfsr & DFSR_BKPT) { target->debug_reason = DBG_REASON_BREAKPOINT; - if (cortex_m3->nvic_dfsr & 0x4) + if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP) target->debug_reason = DBG_REASON_WPTANDBKPT; } - else if (cortex_m3->nvic_dfsr & 0x4) + else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP) target->debug_reason = DBG_REASON_WATCHPOINT; } @@ -281,7 +291,7 @@ int cortex_m3_examine_exception_reason(target_t *target) int cortex_m3_debug_entry(target_t *target) { - int i, irq_is_pending; + int i; u32 xPSR; int retval; @@ -313,19 +323,16 @@ int cortex_m3_debug_entry(target_t *target) /* For IT instructions xPSR must be reloaded on resume and clear on debug exec*/ if (xPSR & 0xf00) { - armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1; + armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = armv7m->core_cache->reg_list[ARMV7M_xPSR].valid; cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff); } - /* Now we can load SP core registers */ -#ifdef USE_SP_REGS for (i = ARMV7M_PRIMASK; i < ARMV7NUMCOREREGS; i++) { if (!armv7m->core_cache->reg_list[i].valid) armv7m->read_core_reg(target, i); } -#endif /* Are we in an exception handler */ armv7m->core_mode = (xPSR & 0x1FF) ? ARMV7M_MODE_HANDLER : ARMV7M_MODE_THREAD; @@ -343,38 +350,7 @@ int cortex_m3_debug_entry(target_t *target) return ERROR_OK; } -int cortex_m3_restore_context(target_t *target) -{ - int i; - - /* get pointers to arch-specific information */ - armv7m_common_t *armv7m = target->arch_info; - cortex_m3_common_t *cortex_m3 = armv7m->arch_info; - - DEBUG(" "); - - if (armv7m->pre_restore_context) - armv7m->pre_restore_context(target); - -#ifdef USE_SP_REGS - for (i = ARMV7NUMCOREREGS; i >= 0; i--) -#else - for (i = ARMV7M_PSP; i >= 0; i--) -#endif - { - if (armv7m->core_cache->reg_list[i].dirty) - { - armv7m->write_core_reg(target, i); - } - } - - if (armv7m->post_restore_context) - armv7m->post_restore_context(target); - - return ERROR_OK; -} - -enum target_state cortex_m3_poll(target_t *target) +int cortex_m3_poll(target_t *target) { int retval; u32 prev_target_state = target->state; @@ -389,15 +365,22 @@ enum target_state cortex_m3_poll(target_t *target) if (retval != ERROR_OK) { target->state = TARGET_UNKNOWN; - return TARGET_UNKNOWN; + return retval; } if (cortex_m3->dcb_dhcsr & S_RESET_ST) { - target->state = TARGET_RESET; - return target->state; + /* check if still in reset */ + ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr); + + if (cortex_m3->dcb_dhcsr & S_RESET_ST) + { + target->state = TARGET_RESET; + return ERROR_OK; + } } - else if (target->state == TARGET_RESET) + + if (target->state == TARGET_RESET) { /* Cannot switch context while running so endreset is called with target->state == TARGET_RESET */ DEBUG("Exit from reset with dcb_dhcsr 0x%x", cortex_m3->dcb_dhcsr); @@ -435,7 +418,7 @@ enum target_state cortex_m3_poll(target_t *target) /* 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); 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]); - return target->state; + return ERROR_OK; } int cortex_m3_halt(target_t *target) @@ -447,6 +430,35 @@ int cortex_m3_halt(target_t *target) DEBUG("target->state: %s", target_state_strings[target->state]); + if (target->state == TARGET_HALTED) + { + WARNING("target was already halted"); + return ERROR_OK; + } + + if (target->state == TARGET_UNKNOWN) + { + WARNING("target was in unknown state when halt was requested"); + } + + if (target->state == TARGET_RESET) + { + if ((jtag_reset_config & RESET_SRST_PULLS_TRST) && jtag_srst) + { + ERROR("can't request a halt while in reset if nSRST pulls nTRST"); + return ERROR_TARGET_FAILURE; + } + else + { + /* we came here in a reset_halt or reset_init sequence + * debug entry was already prepared in cortex_m3_prepare_reset_halt() + */ + target->debug_reason = DBG_REASON_DBGRQ; + + return ERROR_OK; + } + } + /* Write to Debug Halting Control and Status Register */ ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT ); @@ -508,14 +520,19 @@ 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_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 ); + + ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr); + ahbap_read_system_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr); + DEBUG("dcb_dhcsr 0x%x, dcb_demcr 0x%x, ", dcb_dhcsr, dcb_demcr); return ERROR_OK; } @@ -582,7 +599,7 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand resume_pc = buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32); - cortex_m3_restore_context(target); + armv7m_restore_context(target); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) @@ -623,7 +640,7 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand return ERROR_OK; } -//int irqstepcount=0; +/* int irqstepcount=0; */ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle_breakpoints) { /* get pointers to arch-specific information */ @@ -656,7 +673,7 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle target->debug_reason = DBG_REASON_SINGLESTEP; - cortex_m3_restore_context(target); + armv7m_restore_context(target); target_call_event_callbacks(target, TARGET_EVENT_RESUMED); @@ -684,9 +701,27 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle int cortex_m3_assert_reset(target_t *target) { int retval; - + armv7m_common_t *armv7m = target->arch_info; + cortex_m3_common_t *cortex_m3 = armv7m->arch_info; + swjdp_common_t *swjdp = &cortex_m3->swjdp_info; + DEBUG("target->state: %s", target_state_strings[target->state]); + ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 ); + + if (target->reset_mode == RESET_RUN) + { + /* 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 ); + + 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); + } + if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN) { /* assert SRST and TRST */ @@ -1100,7 +1135,7 @@ int cortex_m3_load_core_reg_u32(struct target_s *target, enum armv7m_regtype typ ERROR("JTAG failure %i",retval); return ERROR_JTAG_DEVICE_ERROR; } - //DEBUG("load from core reg %i value 0x%x",num,*value); + /* DEBUG("load from core reg %i value 0x%x",num,*value); */ } else if (type == ARMV7M_REGISTER_CORE_SP) /* Special purpose core register */ { @@ -1116,8 +1151,8 @@ int cortex_m3_load_core_reg_u32(struct target_s *target, enum armv7m_regtype typ 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 = 1; - armv7m->core_cache->reg_list[15].dirty = 1; + 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); DEBUG("load from special reg %i value 0x%x", SYSm, *value); @@ -1142,7 +1177,7 @@ int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype ty if (retval != ERROR_OK) { ERROR("JTAG failure %i", retval); - armv7m->core_cache->reg_list[num].dirty = 1; + armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid; return ERROR_JTAG_DEVICE_ERROR; } DEBUG("write core reg %i value 0x%x", num, value); @@ -1162,7 +1197,7 @@ int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype ty 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 = 1; + 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); DEBUG("write special reg %i value 0x%x ", SYSm, value); @@ -1178,39 +1213,31 @@ int cortex_m3_read_memory(struct target_s *target, u32 address, u32 size, u32 co 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; /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_INVALID_ARGUMENTS; - - if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) - return ERROR_TARGET_UNALIGNED_ACCESS; - /* Is not optimal, autoincrement of tar should be used ( ahbap_block_read and CSW_ADDRINC_SINGLE ) */ + /* cortex_m3 handles unaligned memory access */ + switch (size) { case 4: - /* TODOLATER Check error return value ! */ - { - ahbap_read_buf(swjdp, buffer, 4 * count, address); - } + retval = ahbap_read_buf_u32(swjdp, buffer, 4 * count, address); break; case 2: - { - ahbap_read_buf_u16(swjdp, buffer, 2 * count, address); - } + retval = ahbap_read_buf_u16(swjdp, buffer, 2 * count, address); break; case 1: - { - ahbap_read_buf(swjdp, buffer, count, address); - } + retval = ahbap_read_buf_u8(swjdp, buffer, count, address); break; default: ERROR("BUG: we shouldn't get here"); exit(-1); } - return ERROR_OK; + return retval; } int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer) @@ -1219,45 +1246,34 @@ int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 c 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; /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_INVALID_ARGUMENTS; - - if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) - return ERROR_TARGET_UNALIGNED_ACCESS; - + switch (size) { case 4: - /* TODOLATER Check error return value ! */ - { - ahbap_write_buf(swjdp, buffer, 4 * count, address); - } + retval = ahbap_write_buf_u32(swjdp, buffer, 4 * count, address); break; case 2: - { - ahbap_write_buf_u16(swjdp, buffer, 2 * count, address); - } + retval = ahbap_write_buf_u16(swjdp, buffer, 2 * count, address); break; case 1: - { - ahbap_write_buf(swjdp, buffer, count, address); - } + retval = ahbap_write_buf_u8(swjdp, buffer, count, address); break; default: ERROR("BUG: we shouldn't get here"); exit(-1); } - return ERROR_OK; + return retval; } int cortex_m3_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer) { - cortex_m3_write_memory(target, address, 4, count, buffer); - - return ERROR_OK; + return cortex_m3_write_memory(target, address, 4, count, buffer); } void cortex_m3_build_reg_cache(target_t *target) @@ -1267,7 +1283,7 @@ void cortex_m3_build_reg_cache(target_t *target) int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target) { - u32 did1, dc0, cpuid, fpcr, dwtcr, ictr; + u32 cpuid, fpcr, dwtcr, ictr; int i; /* get pointers to arch-specific information */ @@ -1326,13 +1342,87 @@ int cortex_m3_quit() return ERROR_OK; } +int cortex_m3_dcc_read(swjdp_common_t *swjdp, u8 *value, u8 *ctrl) +{ + u16 dcrdr; + + ahbap_read_buf_u16( swjdp, (u8*)&dcrdr, 1, DCB_DCRDR); + *ctrl = (u8)dcrdr; + *value = (u8)(dcrdr >> 8); + + DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl); + + /* write ack back to software dcc register + * signify we have read data */ + if (dcrdr & (1 << 0)) + { + dcrdr = 0; + ahbap_write_buf_u16( swjdp, (u8*)&dcrdr, 1, DCB_DCRDR); + } + + return ERROR_OK; +} + +int cortex_m3_target_request_data(target_t *target, u32 size, u8 *buffer) +{ + armv7m_common_t *armv7m = target->arch_info; + cortex_m3_common_t *cortex_m3 = armv7m->arch_info; + swjdp_common_t *swjdp = &cortex_m3->swjdp_info; + u8 data; + u8 ctrl; + int i; + + for (i = 0; i < (size * 4); i++) + { + cortex_m3_dcc_read(swjdp, &data, &ctrl); + buffer[i] = data; + } + + return ERROR_OK; +} + +int cortex_m3_handle_target_request(void *priv) +{ + target_t *target = priv; + armv7m_common_t *armv7m = target->arch_info; + cortex_m3_common_t *cortex_m3 = armv7m->arch_info; + swjdp_common_t *swjdp = &cortex_m3->swjdp_info; + + if (!target->dbg_msg_enabled) + return ERROR_OK; + + if (target->state == TARGET_RUNNING) + { + u8 data; + u8 ctrl; + + cortex_m3_dcc_read(swjdp, &data, &ctrl); + + /* check if we have data */ + if (ctrl & (1 << 0)) + { + u32 request; + + /* we assume target is quick enough */ + request = data; + cortex_m3_dcc_read(swjdp, &data, &ctrl); + request |= (data << 8); + cortex_m3_dcc_read(swjdp, &data, &ctrl); + request |= (data << 16); + cortex_m3_dcc_read(swjdp, &data, &ctrl); + request |= (data << 24); + target_request(target, request); + } + } + + return ERROR_OK; +} + int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, int chain_pos, char *variant) { armv7m_common_t *armv7m; armv7m = &cortex_m3->armv7m; - arm_jtag_t *jtag_info = &cortex_m3->jtag_info; - /* prepare JTAG information for the new target */ cortex_m3->jtag_info.chain_pos = chain_pos; cortex_m3->jtag_info.scann_size = 4; @@ -1360,7 +1450,9 @@ int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, in armv7m->arch_info = cortex_m3; armv7m->load_core_reg_u32 = cortex_m3_load_core_reg_u32; armv7m->store_core_reg_u32 = cortex_m3_store_core_reg_u32; -// armv7m->full_context = cortex_m3_full_context; + /* armv7m->full_context = cortex_m3_full_context; */ + + target_register_timer_callback(cortex_m3_handle_target_request, 1, 1, target); return ERROR_OK; } @@ -1371,6 +1463,7 @@ int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char 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) {