X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm7_9_common.c;h=2b064f23120301d83a5f51c6accbde5bbfebd363;hp=ab9e973776d011f7df87158f4cfc35fe969f9427;hb=6a2fd7cad507ef24a7dc4ce3c5f8b5351dd12656;hpb=9ab9786f67f3a3532aa5db339c4c22b2ea843ad7 diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index ab9e973776..2b064f2312 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -2,7 +2,7 @@ * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * - * Copyright (C) 2007,2008 Øyvind Harboe * + * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * @@ -61,6 +61,7 @@ static int arm7_9_clear_watchpoints(arm7_9_common_t *arm7_9) LOG_DEBUG("-"); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0); embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0); + arm7_9->sw_breakpoint_count = 0; arm7_9->sw_breakpoints_added = 0; arm7_9->wp0_used = 0; arm7_9->wp1_used = arm7_9->wp1_used_default; @@ -94,7 +95,7 @@ static void arm7_9_assign_wp(arm7_9_common_t *arm7_9, breakpoint_t *breakpoint) { LOG_ERROR("BUG: no hardware comparator available"); } - LOG_DEBUG("BPID: %d (0x%08" PRIx32 ") using hw wp: %d", + LOG_DEBUG("BPID: %d (0x%08" PRIx32 ") using hw wp: %d", breakpoint->unique_id, breakpoint->address, breakpoint->set ); @@ -157,7 +158,7 @@ static int arm7_9_set_software_breakpoints(arm7_9_common_t *arm7_9) LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1"); return ERROR_FAIL; } - LOG_DEBUG("SW BP using hw wp: %d", + LOG_DEBUG("SW BP using hw wp: %d", arm7_9->sw_breakpoints_added ); return jtag_execute_queue(); @@ -227,9 +228,10 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) arm7_9_common_t *arm7_9 = armv4_5->arch_info; int retval = ERROR_OK; - LOG_DEBUG("BPID: %d, Address: 0x%08" PRIx32, + LOG_DEBUG("BPID: %d, Address: 0x%08" PRIx32 ", Type: %d" , breakpoint->unique_id, - breakpoint->address ); + breakpoint->address, + breakpoint->type); if (target->state != TARGET_HALTED) { @@ -274,9 +276,6 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) } else if (breakpoint->type == BKPT_SOFT) { - if ((retval = arm7_9_set_software_breakpoints(arm7_9)) != ERROR_OK) - return retval; - /* did we already set this breakpoint? */ if (breakpoint->set) return ERROR_OK; @@ -329,6 +328,12 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) return ERROR_OK; } } + + if ((retval = arm7_9_set_software_breakpoints(arm7_9)) != ERROR_OK) + return retval; + + arm7_9->sw_breakpoint_count++; + breakpoint->set = 1; } @@ -366,7 +371,7 @@ int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint) if (breakpoint->type == BKPT_HARD) { - LOG_DEBUG("BPID: %d Releasing hw wp: %d", + LOG_DEBUG("BPID: %d Releasing hw wp: %d", breakpoint->unique_id, breakpoint->set ); if (breakpoint->set == 1) @@ -415,6 +420,20 @@ int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint) return retval; } } + + if (--arm7_9->sw_breakpoint_count==0) + { + /* We have removed the last sw breakpoint, clear the hw breakpoint we used to implement it */ + if (arm7_9->sw_breakpoints_added == 1) + { + embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0); + } + else if (arm7_9->sw_breakpoints_added == 2) + { + embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0); + } + } + breakpoint->set = 0; } @@ -913,8 +932,9 @@ int arm7_9_poll(target_t *target) /* LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));*/ if (target->state == TARGET_UNKNOWN) { + /* Starting OpenOCD with target in debug-halt */ target->state = TARGET_RUNNING; - LOG_WARNING("DBGACK set while target was in unknown state. Reset or initialize target."); + LOG_DEBUG("DBGACK already set during server startup."); } if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { @@ -1001,6 +1021,24 @@ int arm7_9_assert_reset(target_t *target) return ERROR_FAIL; } + /* At this point trst has been asserted/deasserted once. We would + * like to program EmbeddedICE while SRST is asserted, instead of + * depending on SRST to leave that module alone. However, many CPUs + * gate the JTAG clock while SRST is asserted; or JTAG may need + * clock stability guarantees (adaptive clocking might help). + * + * So we assume JTAG access during SRST is off the menu unless it's + * been specifically enabled. + */ + bool srst_asserted = false; + + if (((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) + && (jtag_reset_config & RESET_SRST_NO_GATING)) + { + jtag_add_reset(0, 1); + srst_asserted = true; + } + if (target->reset_halt) { /* @@ -1014,6 +1052,9 @@ int arm7_9_assert_reset(target_t *target) { /* program vector catch register to catch reset vector */ embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1); + + /* extra runtest added as issues were found with certain ARM9 cores (maybe more) - AT91SAM9260 and STR9 */ + jtag_add_runtest(1, jtag_get_end_state()); } else { @@ -1030,7 +1071,7 @@ int arm7_9_assert_reset(target_t *target) if (jtag_reset_config & RESET_SRST_PULLS_TRST) { jtag_add_reset(1, 1); - } else + } else if (!srst_asserted) { jtag_add_reset(0, 1); } @@ -1165,6 +1206,13 @@ int arm7_9_soft_reset_halt(struct target_s *target) int i; int retval; + /* FIX!!! replace some of this code with tcl commands + * + * halt # the halt command is synchronous + * armv4_5 core_state arm + * + */ + if ((retval = target_halt(target)) != ERROR_OK) return retval; @@ -1430,18 +1478,10 @@ int arm7_9_debug_entry(target_t *target) context[15] -= 3 * 4; } - if ((target->debug_reason == DBG_REASON_BREAKPOINT) - || (target->debug_reason == DBG_REASON_SINGLESTEP) - || (target->debug_reason == DBG_REASON_WATCHPOINT) - || (target->debug_reason == DBG_REASON_WPTANDBKPT) - || ((target->debug_reason == DBG_REASON_DBGRQ) && (arm7_9->use_dbgrq == 0))) + if ((target->debug_reason != DBG_REASON_DBGRQ) || (!arm7_9->use_dbgrq)) context[15] -= 3 * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2); - else if (target->debug_reason == DBG_REASON_DBGRQ) - context[15] -= arm7_9->dbgreq_adjust_pc * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2); else - { - LOG_ERROR("unknown debug reason: %i", target->debug_reason); - } + context[15] -= arm7_9->dbgreq_adjust_pc * ((armv4_5->core_state == ARMV4_5_STATE_ARM) ? 4 : 2); if (armv4_5_mode_to_number(armv4_5->core_mode)==-1) return ERROR_FAIL; @@ -1837,7 +1877,7 @@ int arm7_9_resume(struct target_s *target, int current, uint32_t address, int ha { uint32_t current_opcode; target_read_u32(target, current_pc, ¤t_opcode); - LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode); + LOG_ERROR("Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode); return retval; } @@ -2042,7 +2082,7 @@ int arm7_9_step(struct target_s *target, int current, uint32_t address, int hand { uint32_t current_opcode; target_read_u32(target, current_pc, ¤t_opcode); - LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode); + LOG_ERROR("Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode); return retval; } @@ -2635,8 +2675,21 @@ static int arm7_9_dcc_completion(struct target_s *target, uint32_t exit_point, i static const uint32_t dcc_code[] = { - /* MRC TST BNE MRC STR B */ - 0xee101e10, 0xe3110001, 0x0afffffc, 0xee111e10, 0xe4801004, 0xeafffff9 + /* r0 == input, points to memory buffer + * r1 == scratch + */ + + /* spin until DCC control (c0) reports data arrived */ + 0xee101e10, /* w: mrc p14, #0, r1, c0, c0 */ + 0xe3110001, /* tst r1, #1 */ + 0x0afffffc, /* bne w */ + + /* read word from DCC (c1), write to memory */ + 0xee111e10, /* mrc p14, #0, r1, c1, c0 */ + 0xe4801004, /* str r1, [r0], #4 */ + + /* repeat */ + 0xeafffff9 /* b w */ }; int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target_s *target, uint32_t exit_point, int timeout_ms, void *arch_info)); @@ -2714,7 +2767,7 @@ int arm7_9_checksum_memory(struct target_s *target, uint32_t address, uint32_t c reg_param_t reg_params[2]; int retval; - uint32_t arm7_9_crc_code[] = { + static const uint32_t arm7_9_crc_code[] = { 0xE1A02000, /* mov r2, r0 */ 0xE3E00000, /* mov r0, #0xffffffff */ 0xE1A03001, /* mov r3, r1 */ @@ -2796,15 +2849,15 @@ int arm7_9_blank_check_memory(struct target_s *target, uint32_t address, uint32_ int retval; uint32_t i; - uint32_t erase_check_code[] = + static const uint32_t erase_check_code[] = { - /* loop: */ - 0xe4d03001, /* ldrb r3, [r0], #1 */ - 0xe0022003, /* and r2, r2, r3 */ - 0xe2511001, /* subs r1, r1, #1 */ - 0x1afffffb, /* bne loop */ - /* end: */ - 0xeafffffe /* b end */ + /* loop: */ + 0xe4d03001, /* ldrb r3, [r0], #1 */ + 0xe0022003, /* and r2, r2, r3 */ + 0xe2511001, /* subs r1, r1, #1 */ + 0x1afffffb, /* bne loop */ + /* end: */ + 0xeafffffe /* b end */ }; /* make sure we have a working area */ @@ -3113,6 +3166,7 @@ int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9) arm7_9->wp_available = 0; /* this is set up in arm7_9_clear_watchpoints() */ arm7_9->wp_available_max = 2; arm7_9->sw_breakpoints_added = 0; + arm7_9->sw_breakpoint_count = 0; arm7_9->breakpoint_count = 0; arm7_9->wp0_used = 0; arm7_9->wp1_used = 0;