X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farm11.c;h=f7265dac7c7f58e6625f2e01b17586d19538b82d;hb=23c629a85eea7b927a179626e8aa377f63734e46;hp=0f8faba33132b4f76a46d3411e767a6b06a0f57b;hpb=ed8fd94d7ca0fc0682de4020501afae89f31ccc3;p=openocd.git diff --git a/src/target/arm11.c b/src/target/arm11.c index 0f8faba331..f7265dac7c 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 */ @@ -594,35 +609,48 @@ int arm11_leave_debug_state(arm11_common_t * arm11) if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL)) { 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 */ @@ -768,12 +796,29 @@ int arm11_halt(struct target_s *target) uint32_t dscr; + int i = 0; while (1) { CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr)); if (dscr & ARM11_DSCR_CORE_HALTED) break; + + + long long then = 0; + if (i == 1000) + { + then = timeval_ms(); + } + if (i >= 1000) + { + if ((timeval_ms()-then) > 1000) + { + LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); + return ERROR_FAIL; + } + } + i++; } arm11_on_enter_debug_state(arm11); @@ -865,6 +910,7 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han CHECK_RETVAL(jtag_execute_queue()); + int i = 0; while (1) { uint32_t dscr; @@ -875,6 +921,22 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han if (dscr & ARM11_DSCR_CORE_RESTARTED) break; + + + long long then = 0; + if (i == 1000) + { + then = timeval_ms(); + } + if (i >= 1000) + { + if ((timeval_ms()-then) > 1000) + { + LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); + return ERROR_FAIL; + } + } + i++; } if (!debug_execution) @@ -1066,7 +1128,7 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl retval = arm11_simulate_step(target, &next_pc); if (retval != ERROR_OK) return retval; - + brp[0].value = next_pc; brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21); } @@ -1088,10 +1150,8 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl CHECK_RETVAL(jtag_execute_queue()); - /** \todo TODO: add a timeout */ - /* wait for halt */ - + int i = 0; while (1) { uint32_t dscr; @@ -1103,6 +1163,21 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl if ((dscr & (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) == (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) break; + + long long then = 0; + if (i == 1000) + { + then = timeval_ms(); + } + if (i >= 1000) + { + if ((timeval_ms()-then) > 1000) + { + LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); + return ERROR_FAIL; + } + } + i++; } /* clear breakpoint */ @@ -1208,10 +1283,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; @@ -1225,10 +1306,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) { @@ -1287,13 +1372,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) @@ -1309,7 +1404,18 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, arm11_run_instr_data_prepare(arm11); /* 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) { @@ -1320,12 +1426,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; @@ -1341,12 +1451,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; @@ -1358,50 +1472,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. (%d)", (int)((r0 - address) - size * count)); + 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) @@ -1905,22 +2028,8 @@ int arm11_handle_bool_##name(struct command_context_s *cmd_ctx, char *cmd, char return arm11_handle_bool(cmd_ctx, cmd, args, argc, &arm11_config_##name, print_name); \ } -#define RC_TOP(name, descr, more) \ -{ \ - command_t * new_cmd = register_command(cmd_ctx, top_cmd, name, NULL, COMMAND_ANY, descr); \ - command_t * top_cmd = new_cmd; \ - more \ -} - -#define RC_FINAL(name, descr, handler) \ - register_command(cmd_ctx, top_cmd, name, handler, COMMAND_ANY, descr); - -#define RC_FINAL_BOOL(name, descr, var) \ - register_command(cmd_ctx, top_cmd, name, arm11_handle_bool_##var, COMMAND_ANY, descr); - 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") @@ -1949,9 +2058,6 @@ const uint32_t arm11_coproc_instruction_limits[] = 0xFFFFFFFF, /* value */ }; -const char arm11_mrc_syntax[] = "Syntax: mrc . All parameters are numbers only."; -const char arm11_mcr_syntax[] = "Syntax: mcr <32bit value to write>. All parameters are numbers only."; - arm11_common_t * arm11_find_target(const char * arg) { jtag_tap_t * tap; @@ -1977,20 +2083,20 @@ 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. %s", read ? arm11_mrc_syntax : arm11_mcr_syntax); - return -1; + LOG_ERROR("Invalid number of arguments."); + return ERROR_COMMAND_SYNTAX_ERROR; } arm11_common_t * arm11 = arm11_find_target(args[0]); if (!arm11) { - LOG_ERROR("Parameter 1 is not a the JTAG chain position of an ARM11 device. %s", - read ? arm11_mrc_syntax : arm11_mcr_syntax); - - return -1; + LOG_ERROR("Parameter 1 is not a the JTAG chain position of an ARM11 device."); + return ERROR_COMMAND_SYNTAX_ERROR; } if (arm11->target->state != TARGET_HALTED) @@ -2007,11 +2113,10 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar if (values[i] > arm11_coproc_instruction_limits[i]) { - LOG_ERROR("Parameter %ld out of bounds (%" PRId32 " max). %s", + LOG_ERROR("Parameter %ld out of bounds (%" PRId32 " max).", (long)(i + 2), - arm11_coproc_instruction_limits[i], - read ? arm11_mrc_syntax : arm11_mcr_syntax); - return -1; + arm11_coproc_instruction_limits[i]); + return ERROR_COMMAND_SYNTAX_ERROR; } } @@ -2025,12 +2130,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]), @@ -2041,7 +2150,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]), @@ -2049,10 +2160,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) @@ -2069,36 +2177,45 @@ int arm11_register_commands(struct command_context_s *cmd_ctx) { FNC_INFO; - command_t * top_cmd = NULL; - - RC_TOP("arm11", "arm11 specific commands", + command_t *top_cmd, *mw_cmd; - RC_TOP("memwrite", "Control memory write transfer mode", + top_cmd = register_command(cmd_ctx, NULL, "arm11", + NULL, COMMAND_ANY, NULL); - RC_FINAL_BOOL("burst", "Enable/Disable non-standard but fast burst mode (default: enabled)", - memwrite_burst) - - RC_FINAL_BOOL("error_fatal", "Terminate program if transfer error was found (default: enabled)", - memwrite_error_fatal) -) /* memwrite */ - - RC_FINAL_BOOL("no_increment", "Don't increment address on multi-read/-write (default: disabled)", - memrw_no_increment) - -RC_FINAL_BOOL("step_irq_enable", "Enable interrupts while stepping (default: disabled)", - step_irq_enable) -RC_FINAL_BOOL("hardware_step", "hardware single stepping. By default use simulate + breakpoint. This command is only here to check if simulate + breakpoint implementation is broken.", - hardware_step) - - RC_FINAL("vcr", "Control (Interrupt) Vector Catch Register", - arm11_handle_vcr) - - RC_FINAL("mrc", "Read Coprocessor register", - arm11_handle_mrc) - - RC_FINAL("mcr", "Write Coprocessor register", - arm11_handle_mcr) -) /* arm11 */ + /* "hardware_step" is only here to check if the default + * simulate + breakpoint implementation is broken. + * TEMPORARY! NOT DOCUMENTED! + */ + register_command(cmd_ctx, top_cmd, "hardware_step", + arm11_handle_bool_hardware_step, COMMAND_ANY, + "DEBUG ONLY - Hardware single stepping" + " (default: disabled)"); + + register_command(cmd_ctx, top_cmd, "mcr", + arm11_handle_mcr, COMMAND_ANY, + "Write Coprocessor register. mcr <32bit value to write>. All parameters are numbers only."); + + mw_cmd = register_command(cmd_ctx, top_cmd, "memwrite", + NULL, COMMAND_ANY, NULL); + register_command(cmd_ctx, mw_cmd, "burst", + arm11_handle_bool_memwrite_burst, COMMAND_ANY, + "Enable/Disable non-standard but fast burst mode" + " (default: enabled)"); + register_command(cmd_ctx, mw_cmd, "error_fatal", + arm11_handle_bool_memwrite_error_fatal, COMMAND_ANY, + "Terminate program if transfer error was found" + " (default: enabled)"); + + 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, "step_irq_enable", + arm11_handle_bool_step_irq_enable, COMMAND_ANY, + "Enable interrupts while stepping" + " (default: disabled)"); + register_command(cmd_ctx, top_cmd, "vcr", + arm11_handle_vcr, COMMAND_ANY, + "Control (Interrupt) Vector Catch Register"); return ERROR_OK; }