X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=114832783b4427960d450df0089ae6507f53b320;hb=da2bbc90fc8b1a44fe466e6f168882b65381df3e;hp=f9d957d69e0927b561c727b8e1d60b398fe93e00;hpb=e27696f6b04459e935a0a5f65f7f668cb02970dd;p=openocd.git diff --git a/src/target/target.c b/src/target/target.c index f9d957d69e..114832783b 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -253,11 +253,28 @@ int target_process_reset(struct command_context_s *cmd_ctx) { int retval = ERROR_OK; target_t *target; + struct timeval timeout, now; /* prepare reset_halt where necessary */ target = targets; while (target) { + if (jtag_reset_config & RESET_SRST_PULLS_TRST) + { + switch (target->reset_mode) + { + case RESET_HALT: + command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_HALT"); + target->reset_mode = RESET_RUN_AND_HALT; + break; + case RESET_INIT: + command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_INIT"); + target->reset_mode = RESET_RUN_AND_INIT; + break; + default: + break; + } + } switch (target->reset_mode) { case RESET_HALT: @@ -316,6 +333,42 @@ int target_process_reset(struct command_context_s *cmd_ctx) target = target->next; } jtag_execute_queue(); + + /* Wait for reset to complete, maximum 5 seconds. */ + gettimeofday(&timeout, NULL); + timeval_add_time(&timeout, 5, 0); + for(;;) + { + gettimeofday(&now, NULL); + + target_call_timer_callbacks(); + + target = targets; + while (target) + { + target->type->poll(target); + if ((target->reset_mode == RESET_RUN_AND_INIT) || (target->reset_mode == RESET_RUN_AND_HALT)) + { + if (target->state != TARGET_HALTED) + { + if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) + { + command_print(cmd_ctx, "Timed out waiting for reset"); + goto done; + } + usleep(100*1000); /* Do not eat all cpu */ + goto again; + } + } + target = target->next; + } + /* All targets we're waiting for are halted */ + break; + + again:; + } + done: + return retval; } @@ -340,6 +393,11 @@ int target_init(struct command_context_s *cmd_ctx) target_register_timer_callback(handle_target, 100, 1, NULL); } + return ERROR_OK; +} + +int target_init_reset(struct command_context_s *cmd_ctx) +{ if (startup_mode == DAEMON_RESET) target_process_reset(cmd_ctx); @@ -764,6 +822,11 @@ int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { buffer = malloc(size); + if (buffer == NULL) + { + ERROR("error allocating buffer for section (%d bytes)", size); + return ERROR_OK; + } target_read_buffer(target, address, size, buffer); /* convert to target endianess */ @@ -1023,6 +1086,7 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a (*last_target_p)->reset_script = NULL; (*last_target_p)->post_halt_script = NULL; (*last_target_p)->pre_resume_script = NULL; + (*last_target_p)->gdb_program_script = NULL; (*last_target_p)->working_area = 0x0; (*last_target_p)->working_area_size = 0x0; @@ -1047,7 +1111,8 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a (*last_target_p)->trace_info->trace_history_overflowed = 0; (*last_target_p)->dbgmsg = NULL; - + (*last_target_p)->dbg_msg_enabled = 0; + (*last_target_p)->type->target_command(cmd_ctx, cmd, args, argc, *last_target_p); found = 1; @@ -1103,6 +1168,12 @@ int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, c free(target->pre_resume_script); target->pre_resume_script = strdup(args[2]); } + else if (strcmp(args[1], "gdb_program_config") == 0) + { + if (target->gdb_program_script) + free(target->gdb_program_script); + target->gdb_program_script = strdup(args[2]); + } else { ERROR("unknown event type: '%s", args[1]); @@ -1188,8 +1259,7 @@ int handle_target(void *priv) if (target_continous_poll) if ((retval = target->type->poll(target)) < 0) { - ERROR("couldn't poll target, exiting"); - exit(-1); + ERROR("couldn't poll target. It's due for a reset."); } } @@ -1346,6 +1416,10 @@ int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **arg { target_continous_poll = 0; } + else + { + command_print(cmd_ctx, "arg is \"on\" or \"off\""); + } } @@ -1411,10 +1485,10 @@ int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **arg break; case ERROR_TARGET_TIMEOUT: command_print(cmd_ctx, "target timed out... shutting down"); - exit(-1); + return retval; default: command_print(cmd_ctx, "unknown error... shutting down"); - exit(-1); + return retval; } } @@ -1470,7 +1544,8 @@ int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { target_t *target = get_current_target(cmd_ctx); - enum target_reset_mode reset_mode = RESET_RUN; + enum target_reset_mode reset_mode = target->reset_mode; + enum target_reset_mode save = target->reset_mode; DEBUG("-"); @@ -1503,11 +1578,17 @@ int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **ar command_print(cmd_ctx, "usage: reset ['run', 'halt', 'init', 'run_and_halt', 'run_and_init]"); return ERROR_OK; } - target->reset_mode = reset_mode; } + /* temporarily modify mode of current reset target */ + target->reset_mode = reset_mode; + + /* reset *all* targets */ target_process_reset(cmd_ctx); + /* Restore default reset mode for this target */ + target->reset_mode = save; + return ERROR_OK; } @@ -1561,9 +1642,11 @@ int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **arg int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { + const int line_bytecnt = 32; int count = 1; int size = 4; u32 address = 0; + int line_modulo; int i; char output[128]; @@ -1586,20 +1669,21 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, switch (cmd[2]) { case 'w': - size = 4; + size = 4; line_modulo = line_bytecnt / 4; break; case 'h': - size = 2; + size = 2; line_modulo = line_bytecnt / 2; break; case 'b': - size = 1; + size = 1; line_modulo = line_bytecnt / 1; break; default: return ERROR_OK; } buffer = calloc(count, size); - if ((retval = target->type->read_memory(target, address, size, count, buffer)) != ERROR_OK) + retval = target->type->read_memory(target, address, size, count, buffer); + if (retval != ERROR_OK) { switch (retval) { @@ -1623,7 +1707,7 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, for (i = 0; i < count; i++) { - if (i%8 == 0) + if (i%line_modulo == 0) output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8x: ", address + (i*size)); switch (size) @@ -1639,7 +1723,7 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, break; } - if ((i%8 == 7) || (i == count - 1)) + if ((i%line_modulo == line_modulo-1) || (i == count - 1)) { command_print(cmd_ctx, output); output_len = 0; @@ -1751,6 +1835,11 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char for (i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); + if (buffer==NULL) + { + command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size); + break; + } if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK) { ERROR("image_read_section failed with error code: %i", retval); @@ -1783,6 +1872,7 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char u32 address; u32 size; u8 buffer[560]; + int retval; duration_t duration; char *duration_text; @@ -1817,7 +1907,13 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char u32 size_written; u32 this_run_size = (size > 560) ? 560 : size; - target->type->read_memory(target, address, 4, this_run_size / 4, buffer); + retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer); + if (retval != ERROR_OK) + { + command_print(cmd_ctx, "Reading memory failed %d", retval); + break; + } + fileio_write(&fileio, this_run_size, buffer, &size_written); size -= this_run_size; @@ -1831,7 +1927,6 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char free(duration_text); return ERROR_OK; - } int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) @@ -1875,7 +1970,7 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch image.base_address_set = 0; image.base_address = 0x0; } - + image.start_address_set = 0; if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK) @@ -1888,6 +1983,11 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch for (i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); + if (buffer == NULL) + { + command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size); + break; + } if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK) { ERROR("image_read_section failed with error code: %i", retval); @@ -1899,27 +1999,59 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch /* calculate checksum of image */ image_calculate_checksum( buffer, buf_cnt, &checksum ); - free(buffer); retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum); if( retval != ERROR_OK ) { command_print(cmd_ctx, "image verify failed, verify aborted"); + free(buffer); image_close(&image); return ERROR_OK; } if( checksum != mem_checksum ) { - command_print(cmd_ctx, "image verify failed, verify aborted"); - image_close(&image); - return ERROR_OK; - } + /* failed crc checksum, fall back to a binary compare */ + u8 *data; + + command_print(cmd_ctx, "image verify checksum failed - attempting binary compare"); + + data = (u8*)malloc(buf_cnt); + + /* Can we use 32bit word accesses? */ + int size = 1; + int count = buf_cnt; + if ((count % 4) == 0) + { + size *= 4; + count /= 4; + } + retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data); + + if (retval == ERROR_OK) + { + int t; + for (t = 0; t < buf_cnt; t++) + { + if (data[t] != buffer[t]) + { + command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]); + free(data); + free(buffer); + image_close(&image); + return ERROR_OK; + } + } + } + free(data); + } + + free(buffer); image_size += buf_cnt; } - + duration_stop_measure(&duration, &duration_text); command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text); free(duration_text); @@ -2084,4 +2216,3 @@ int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args return ERROR_OK; } -