X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm11.c;h=f46e424b90882d5c282dfbc886888d9d8607eccf;hp=9f85bd78413f2daba1b4af83c3a8121c47b1e989;hb=6a2fd7cad507ef24a7dc4ce3c5f8b5351dd12656;hpb=55f4e430e8c1c7382d27695c56e8ca95ba7b7dec diff --git a/src/target/arm11.c b/src/target/arm11.c index 9f85bd7841..f46e424b90 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -29,6 +29,7 @@ #include "arm11.h" #include "armv4_5.h" #include "arm_simulator.h" +#include "time_support.h" #include "target_type.h" @@ -53,7 +54,6 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11); bool arm11_config_memwrite_burst = true; bool arm11_config_memwrite_error_fatal = true; uint32_t arm11_vcr = 0; -bool arm11_config_memrw_no_increment = false; bool arm11_config_step_irq_enable = false; bool arm11_config_hardware_step = false; @@ -451,7 +451,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11) } #endif - arm11_run_instr_data_prepare(arm11); + retval = arm11_run_instr_data_prepare(arm11); + if (retval != ERROR_OK) + return retval; /* save r0 - r14 */ @@ -472,7 +474,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11) if (R(DSCR) & ARM11_DSCR_RDTR_FULL) { /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */ - arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR)); + retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR)); + if (retval != ERROR_OK) + return retval; } else { @@ -482,7 +486,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11) /* save CPSR */ /* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */ - arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR)); + retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR)); + if (retval != ERROR_OK) + return retval; /* save PC */ @@ -515,11 +521,15 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11) /* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */ /* MCR p15,0,R0,c1,c0,0 */ - arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0); + retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0); + if (retval != ERROR_OK) + return retval; } - arm11_run_instr_data_finish(arm11); + retval = arm11_run_instr_data_finish(arm11); + if (retval != ERROR_OK) + return retval; arm11_dump_reg_changes(arm11); @@ -564,8 +574,11 @@ void arm11_dump_reg_changes(arm11_common_t * arm11) int arm11_leave_debug_state(arm11_common_t * arm11) { FNC_INFO; + int retval; - arm11_run_instr_data_prepare(arm11); + retval = arm11_run_instr_data_prepare(arm11); + if (retval != ERROR_OK) + return retval; /** \todo TODO: handle other mode registers */ @@ -582,7 +595,9 @@ int arm11_leave_debug_state(arm11_common_t * arm11) // LOG_DEBUG("RESTORE R" ZU " %08x", i, R(RX + i)); } - arm11_run_instr_data_finish(arm11); + retval = arm11_run_instr_data_finish(arm11); + if (retval != ERROR_OK) + return retval; /* spec says clear wDTR and rDTR; we assume they are clear as otherwise our programming would be sloppy */ @@ -593,36 +608,56 @@ int arm11_leave_debug_state(arm11_common_t * arm11) if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL)) { + /* + The wDTR/rDTR two registers that are used to send/receive data to/from + the core in tandem with corresponding instruction codes that are + written into the core. The RDTR FULL/WDTR FULL flag indicates that the + registers hold data that was written by one side (CPU or JTAG) and not + read out by the other side. + */ LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08" PRIx32 ")", DSCR); + return ERROR_FAIL; } } - arm11_run_instr_data_prepare(arm11); + retval = arm11_run_instr_data_prepare(arm11); + if (retval != ERROR_OK) + return retval; /* restore original wDTR */ if ((R(DSCR) & ARM11_DSCR_WDTR_FULL) || arm11->reg_list[ARM11_RC_WDTR].dirty) { /* MCR p14,0,R0,c0,c5,0 */ - arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR)); + retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR)); + if (retval != ERROR_OK) + return retval; } /* restore CPSR */ /* MSR CPSR,R0*/ - arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR)); + retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR)); + if (retval != ERROR_OK) + return retval; + /* restore PC */ /* MOV PC,R0 */ - arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC)); + retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC)); + if (retval != ERROR_OK) + return retval; + /* restore R0 */ /* MRC p14,0,r0,c0,c5,0 */ arm11_run_instr_data_to_core1(arm11, 0xee100e15, R(R0)); - arm11_run_instr_data_finish(arm11); + retval = arm11_run_instr_data_finish(arm11); + if (retval != ERROR_OK) + return retval; /* restore DSCR */ @@ -674,9 +709,6 @@ int arm11_poll(struct target_s *target) arm11_common_t * arm11 = target->arch_info; - if (arm11->trst_active) - return ERROR_OK; - uint32_t dscr; CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr)); @@ -756,12 +788,6 @@ int arm11_halt(struct target_s *target) return ERROR_OK; } - if (arm11->trst_active) - { - arm11->halt_requested = true; - return ERROR_OK; - } - arm11_add_IR(arm11, ARM11_HALT, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); @@ -1171,22 +1197,16 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl return ERROR_OK; } -/* target reset control */ -int arm11_assert_reset(struct target_s *target) +int arm11_assert_reset(target_t *target) { FNC_INFO; -#if 0 - /* assert reset lines */ - /* resets only the DBGTAP, not the ARM */ - - jtag_add_reset(1, 0); - jtag_add_sleep(5000); - - arm11_common_t * arm11 = target->arch_info; - arm11->trst_active = true; -#endif - + /* FIX! we really should assert srst here, but + * how do we reset the target into the halted state? + * + * Also arm11 behaves "funny" when srst is asserted + * (as of writing the rules are not understood). + */ if (target->reset_halt) { CHECK_RETVAL(target_halt(target)); @@ -1195,25 +1215,8 @@ int arm11_assert_reset(struct target_s *target) return ERROR_OK; } -int arm11_deassert_reset(struct target_s *target) +int arm11_deassert_reset(target_t *target) { - FNC_INFO; - -#if 0 - LOG_DEBUG("target->state: %s", - target_state_name(target)); - - - /* deassert reset lines */ - jtag_add_reset(0, 0); - - arm11_common_t * arm11 = target->arch_info; - arm11->trst_active = false; - - if (arm11->halt_requested) - return arm11_halt(target); -#endif - return ERROR_OK; } @@ -1255,10 +1258,16 @@ int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], i /* target memory access * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit) * count: number of items of + * + * arm11_config_memrw_no_increment - in the future we may want to be able + * to read/write a range of data to a "port". a "port" is an action on + * read memory address for some peripheral. */ -int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +int arm11_read_memory_inner(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer, + bool arm11_config_memrw_no_increment) { /** \todo TODO: check if buffer cast to uint32_t* and uint16_t* might cause alignment problems */ + int retval; FNC_INFO; @@ -1272,10 +1281,14 @@ int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size, arm11_common_t * arm11 = target->arch_info; - arm11_run_instr_data_prepare(arm11); + retval = arm11_run_instr_data_prepare(arm11); + if (retval != ERROR_OK) + return retval; /* MRC p14,0,r0,c0,c5,0 */ - arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); + retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); + if (retval != ERROR_OK) + return retval; switch (size) { @@ -1334,13 +1347,23 @@ int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size, } } - arm11_run_instr_data_finish(arm11); + return arm11_run_instr_data_finish(arm11); +} - return ERROR_OK; +int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +{ + return arm11_read_memory_inner(target, address, size, count, buffer, false); } -int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +/* +* arm11_config_memrw_no_increment - in the future we may want to be able +* to read/write a range of data to a "port". a "port" is an action on +* read memory address for some peripheral. +*/ +int arm11_write_memory_inner(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer, + bool arm11_config_memrw_no_increment) { + int retval; FNC_INFO; if (target->state != TARGET_HALTED) @@ -1353,10 +1376,23 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, arm11_common_t * arm11 = target->arch_info; - arm11_run_instr_data_prepare(arm11); + retval = arm11_run_instr_data_prepare(arm11); + if (retval != ERROR_OK) + return retval; /* MRC p14,0,r0,c0,c5,0 */ - arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); + retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); + if (retval != ERROR_OK) + return retval; + + /* burst writes are not used for single words as those may well be + * reset init script writes. + * + * The other advantage is that as burst writes are default, we'll + * now exercise both burst and non-burst code paths with the + * default settings, increasing code coverage. + */ + bool burst = arm11_config_memwrite_burst && (count > 1); switch (size) { @@ -1367,12 +1403,16 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, for (size_t i = 0; i < count; i++) { /* MRC p14,0,r1,c0,c5,0 */ - arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++); + retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++); + if (retval != ERROR_OK) + return retval; /* strb r1, [r0], #1 */ /* strb r1, [r0] */ - arm11_run_instr_no_data1(arm11, + retval = arm11_run_instr_no_data1(arm11, !arm11_config_memrw_no_increment ? 0xe4c01001 : 0xe5c01000); + if (retval != ERROR_OK) + return retval; } break; @@ -1388,12 +1428,16 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t)); /* MRC p14,0,r1,c0,c5,0 */ - arm11_run_instr_data_to_core1(arm11, 0xee101e15, value); + retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value); + if (retval != ERROR_OK) + return retval; /* strh r1, [r0], #2 */ /* strh r1, [r0] */ - arm11_run_instr_no_data1(arm11, + retval = arm11_run_instr_no_data1(arm11, !arm11_config_memrw_no_increment ? 0xe0c010b2 : 0xe1c010b0); + if (retval != ERROR_OK) + return retval; } break; @@ -1405,51 +1449,59 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */ uint32_t *words = (uint32_t*)buffer; - if (!arm11_config_memwrite_burst) + if (!burst) { /* STC p14,c5,[R0],#4 */ /* STC p14,c5,[R0]*/ - arm11_run_instr_data_to_core(arm11, instr, words, count); + retval = arm11_run_instr_data_to_core(arm11, instr, words, count); + if (retval != ERROR_OK) + return retval; } else { /* STC p14,c5,[R0],#4 */ /* STC p14,c5,[R0]*/ - arm11_run_instr_data_to_core_noack(arm11, instr, words, count); + retval = arm11_run_instr_data_to_core_noack(arm11, instr, words, count); + if (retval != ERROR_OK) + return retval; } break; } } -#if 1 /* r0 verification */ if (!arm11_config_memrw_no_increment) { uint32_t r0; /* MCR p14,0,R0,c0,c5,0 */ - arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1); + retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1); + if (retval != ERROR_OK) + return retval; if (address + size * count != r0) { - LOG_ERROR("Data transfer failed. Expected end address 0x%08x, got 0x%08x", - address + size * count, r0); + LOG_ERROR("Data transfer failed. Expected end " + "address 0x%08x, got 0x%08x", + (unsigned) (address + size * count), + (unsigned) r0); - if (arm11_config_memwrite_burst) + if (burst) LOG_ERROR("use 'arm11 memwrite burst disable' to disable fast burst mode"); if (arm11_config_memwrite_error_fatal) return ERROR_FAIL; } } -#endif - arm11_run_instr_data_finish(arm11); - - return ERROR_OK; + return arm11_run_instr_data_finish(arm11); } +int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +{ + return arm11_write_memory_inner(target, address, size, count, buffer, false); +} /* write target memory in multiples of 4 byte, optimized for writing large quantities of data */ int arm11_bulk_write_memory(struct target_s *target, uint32_t address, uint32_t count, uint8_t *buffer) @@ -1730,6 +1782,8 @@ int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target /* talk to the target and set things up */ int arm11_examine(struct target_s *target) { + int retval; + FNC_INFO; arm11_common_t * arm11 = target->arch_info; @@ -1797,7 +1851,9 @@ int arm11_examine(struct target_s *target) * as suggested by the spec. */ - arm11_check_init(arm11, NULL); + retval = arm11_check_init(arm11, NULL); + if (retval != ERROR_OK) + return retval; target_set_examined(target); @@ -1955,7 +2011,6 @@ int arm11_handle_bool_##name(struct command_context_s *cmd_ctx, char *cmd, char BOOL_WRAPPER(memwrite_burst, "memory write burst mode") BOOL_WRAPPER(memwrite_error_fatal, "fatal error mode for memory writes") -BOOL_WRAPPER(memrw_no_increment, "\"no increment\" mode for memory transfers") BOOL_WRAPPER(step_irq_enable, "IRQs while stepping") BOOL_WRAPPER(hardware_step, "hardware single step") @@ -2009,6 +2064,8 @@ arm11_common_t * arm11_find_target(const char * arg) int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, bool read) { + int retval; + if (argc != (read ? 6 : 7)) { LOG_ERROR("Invalid number of arguments."); @@ -2054,12 +2111,16 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar if (read) instr |= 0x00100000; - arm11_run_instr_data_prepare(arm11); + retval = arm11_run_instr_data_prepare(arm11); + if (retval != ERROR_OK) + return retval; if (read) { uint32_t result; - arm11_run_instr_data_from_core_via_r0(arm11, instr, &result); + retval = arm11_run_instr_data_from_core_via_r0(arm11, instr, &result); + if (retval != ERROR_OK) + return retval; LOG_INFO("MRC p%d, %d, R0, c%d, c%d, %d = 0x%08" PRIx32 " (%" PRId32 ")", (int)(values[0]), @@ -2070,7 +2131,9 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar } else { - arm11_run_instr_data_to_core_via_r0(arm11, instr, values[5]); + retval = arm11_run_instr_data_to_core_via_r0(arm11, instr, values[5]); + if (retval != ERROR_OK) + return retval; LOG_INFO("MRC p%d, %d, R0 (#0x%08" PRIx32 "), c%d, c%d, %d", (int)(values[0]), (int)(values[1]), @@ -2078,10 +2141,7 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar (int)(values[2]), (int)(values[3]), (int)(values[4])); } - arm11_run_instr_data_finish(arm11); - - - return ERROR_OK; + return arm11_run_instr_data_finish(arm11); } int arm11_handle_mrc(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) @@ -2130,10 +2190,6 @@ int arm11_register_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, top_cmd, "mrc", arm11_handle_mrc, COMMAND_ANY, "Read Coprocessor register. mrc . All parameters are numbers only."); - register_command(cmd_ctx, top_cmd, "no_increment", - arm11_handle_bool_memrw_no_increment, COMMAND_ANY, - "Don't increment address on multi-read/-write" - " (default: disabled)"); register_command(cmd_ctx, top_cmd, "step_irq_enable", arm11_handle_bool_step_irq_enable, COMMAND_ANY, "Enable interrupts while stepping"