X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=d768fda7ea1b03b42d36fae21bc46fc62d7eac78;hp=1778a5aa3d31c30e5b18a945cc2f3c02d5413459;hb=5d80b365526537d2e8705e8bf4de1485b4bb6be6;hpb=908ee4dc9641bd3df2eb00264575501867da539d diff --git a/src/target/target.c b/src/target/target.c index 1778a5aa3d..d768fda7ea 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -87,7 +87,7 @@ extern struct target_type dsp563xx_target; extern struct target_type dsp5680xx_target; extern struct target_type testee_target; extern struct target_type avr32_ap7k_target; -extern struct target_type stm32_stlink_target; +extern struct target_type hla_target; static struct target_type *target_types[] = { &arm7tdmi_target, @@ -110,7 +110,7 @@ static struct target_type *target_types[] = { &dsp5680xx_target, &testee_target, &avr32_ap7k_target, - &stm32_stlink_target, + &hla_target, NULL, }; @@ -156,8 +156,6 @@ static const char *target_strerror_safe(int err) } static const Jim_Nvp nvp_target_event[] = { - { .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" }, - { .value = TARGET_EVENT_OLD_pre_resume , .name = "old-pre_resume" }, { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" }, { .value = TARGET_EVENT_HALTED, .name = "halted" }, @@ -168,10 +166,7 @@ static const Jim_Nvp nvp_target_event[] = { { .name = "gdb-start", .value = TARGET_EVENT_GDB_START }, { .name = "gdb-end", .value = TARGET_EVENT_GDB_END }, - /* historical name */ - - { .value = TARGET_EVENT_RESET_START, .name = "reset-start" }, - + { .value = TARGET_EVENT_RESET_START, .name = "reset-start" }, { .value = TARGET_EVENT_RESET_ASSERT_PRE, .name = "reset-assert-pre" }, { .value = TARGET_EVENT_RESET_ASSERT, .name = "reset-assert" }, { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" }, @@ -199,10 +194,6 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" }, { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" }, - { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" }, - { .value = TARGET_EVENT_RESUMED , .name = "resume-ok" }, - { .value = TARGET_EVENT_RESUME_END , .name = "resume-end" }, - { .name = NULL, .value = -1 } }; @@ -527,6 +518,8 @@ int target_resume(struct target *target, int current, uint32_t address, int hand return ERROR_FAIL; } + target_call_event_callbacks(target, TARGET_EVENT_RESUME_START); + /* note that resume *must* be asynchronous. The CPU can halt before * we poll. The CPU can even halt at the current PC as a result of * a software breakpoint being inserted by (a bug?) the application. @@ -535,6 +528,8 @@ int target_resume(struct target *target, int current, uint32_t address, int hand if (retval != ERROR_OK) return retval; + target_call_event_callbacks(target, TARGET_EVENT_RESUME_END); + return retval; } @@ -616,9 +611,17 @@ static int jtag_enable_callback(enum jtag_event event, void *priv) return ERROR_OK; jtag_unregister_event_callback(jtag_enable_callback, target); - return target_examine_one(target); -} + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); + + int retval = target_examine_one(target); + if (retval != ERROR_OK) + return retval; + + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); + + return retval; +} /* Targets that correctly implement init + examine, i.e. * no communication with target during init: @@ -637,12 +640,18 @@ int target_examine(void) target); continue; } + + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); + retval = target_examine_one(target); if (retval != ERROR_OK) return retval; + + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); } return retval; } + const char *target_type_name(struct target *target) { return target->type->name; @@ -813,6 +822,7 @@ int target_run_flash_async_algorithm(struct target *target, uint32_t entry_point, uint32_t exit_point, void *arch_info) { int retval; + int timeout = 0; /* Set up working area. First word is write pointer, second word is read pointer, * rest is fifo data area. */ @@ -884,9 +894,19 @@ int target_run_flash_async_algorithm(struct target *target, * less than buffer size / flash speed. This is very unlikely to * run when using high latency connections such as USB. */ alive_sleep(10); + + /* to stop an infinite loop on some targets check and increment a timeout + * this issue was observed on a stellaris using the new ICDI interface */ + if (timeout++ >= 500) { + LOG_ERROR("timeout waiting for algorithm, a target reset is recommended"); + return ERROR_FLASH_OPERATION_FAILED; + } continue; } + /* reset our timeout */ + timeout = 0; + /* Limit to the amount of data we actually want to write */ if (thisrun_bytes > count * block_size) thisrun_bytes = count * block_size; @@ -2144,9 +2164,6 @@ static int sense_handler(void) return ERROR_OK; } -static int backoff_times; -static int backoff_count; - /* process target state changes */ static int handle_target(void *priv) { @@ -2202,13 +2219,6 @@ static int handle_target(void *priv) recursive = 0; } - if (backoff_times > backoff_count) { - /* do not poll this time as we failed previously */ - backoff_count++; - return ERROR_OK; - } - backoff_count = 0; - /* Poll targets for state changes unless that's globally disabled. * Skip targets that are currently disabled. */ @@ -2218,18 +2228,26 @@ static int handle_target(void *priv) if (!target->tap->enabled) continue; + if (target->backoff.times > target->backoff.count) { + /* do not poll this time as we failed previously */ + target->backoff.count++; + continue; + } + target->backoff.count = 0; + /* only poll target if we've got power and srst isn't asserted */ if (!powerDropout && !srstAsserted) { /* polling may fail silently until the target has been examined */ retval = target_poll(target); if (retval != ERROR_OK) { /* 100ms polling interval. Increase interval between polling up to 5000ms */ - if (backoff_times * polling_interval < 5000) { - backoff_times *= 2; - backoff_times++; + if (target->backoff.times * polling_interval < 5000) { + target->backoff.times *= 2; + target->backoff.times++; } - LOG_USER("Polling target failed, GDB will be halted. Polling again in %dms", - backoff_times * polling_interval); + LOG_USER("Polling target %s failed, GDB will be halted. Polling again in %dms", + target_name(target), + target->backoff.times * polling_interval); /* Tell GDB to halt the debugger. This allows the user to * run monitor commands to handle the situation. @@ -2238,9 +2256,9 @@ static int handle_target(void *priv) return retval; } /* Since we succeeded, we reset backoff count */ - if (backoff_times > 0) - LOG_USER("Polling succeeded again"); - backoff_times = 0; + if (target->backoff.times > 0) + LOG_USER("Polling target %s succeeded again", target_name(target)); + target->backoff.times = 0; } } @@ -2511,7 +2529,6 @@ COMMAND_HANDLER(handle_resume_command) return ERROR_COMMAND_SYNTAX_ERROR; struct target *target = get_current_target(CMD_CTX); - target_handle_event(target, TARGET_EVENT_OLD_pre_resume); /* with no CMD_ARGV, resume from current pc, addr = 0, * with one arguments, addr = CMD_ARGV[0], @@ -4335,6 +4352,34 @@ static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR; } +/** +* @brief Reads an array of words/halfwords/bytes from target memory starting at specified address. +* +* Usage: mdw [phys]
[] - for 32 bit reads +* mdh [phys]
[] - for 16 bit reads +* mdb [phys]
[] - for 8 bit reads +* +* Count defaults to 1. +* +* Calls target_read_memory or target_read_phys_memory depending on +* the presence of the "phys" argument +* Reads the target memory in blocks of max. 32 bytes, and returns an array of ints formatted +* to int representation in base16. +* Also outputs read data in a human readable form using command_print +* +* @param phys if present target_read_phys_memory will be used instead of target_read_memory +* @param address address where to start the read. May be specified in decimal or hex using the standard "0x" prefix +* @param count optional count parameter to read an array of values. If not specified, defaults to 1. +* @returns: JIM_ERR on error or JIM_OK on success and sets the result string to an array of ascii formatted numbers +* on success, with [] number of elements. +* +* In case of little endian target: +* Example1: "mdw 0x00000000" returns "10123456" +* Exmaple2: "mdh 0x00000000 1" returns "3456" +* Example3: "mdb 0x00000000" returns "56" +* Example4: "mdh 0x00000000 2" returns "3456 1012" +* Example5: "mdb 0x00000000 3" returns "56 34 12" +**/ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { const char *cmd_name = Jim_GetString(argv[0], NULL); @@ -4363,78 +4408,80 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) fn = target_read_phys_memory; } - jim_wide a; - e = Jim_GetOpt_Wide(&goi, &a); + /* Read address parameter */ + jim_wide addr; + e = Jim_GetOpt_Wide(&goi, &addr); if (e != JIM_OK) return JIM_ERR; - jim_wide c; + + /* If next parameter exists, read it out as the count parameter, if not, set it to 1 (default) */ + jim_wide count; if (goi.argc == 1) { - e = Jim_GetOpt_Wide(&goi, &c); + e = Jim_GetOpt_Wide(&goi, &count); if (e != JIM_OK) return JIM_ERR; } else - c = 1; + count = 1; /* all args must be consumed */ if (goi.argc != 0) return JIM_ERR; - jim_wide b = 1; /* shut up gcc */ + jim_wide dwidth = 1; /* shut up gcc */ if (strcasecmp(cmd_name, "mdw") == 0) - b = 4; + dwidth = 4; else if (strcasecmp(cmd_name, "mdh") == 0) - b = 2; + dwidth = 2; else if (strcasecmp(cmd_name, "mdb") == 0) - b = 1; + dwidth = 1; else { LOG_ERROR("command '%s' unknown: ", cmd_name); return JIM_ERR; } /* convert count to "bytes" */ - c = c * b; + int bytes = count * dwidth; struct target *target = Jim_CmdPrivData(goi.interp); uint8_t target_buf[32]; jim_wide x, y, z; - while (c > 0) { - y = c; - if (y > 16) - y = 16; - e = fn(target, a, b, y / b, target_buf); + while (bytes > 0) { + y = (bytes < 16) ? bytes : 16; /* y = min(bytes, 16); */ + + /* Try to read out next block */ + e = fn(target, addr, dwidth, y / dwidth, target_buf); + if (e != ERROR_OK) { - char tmp[10]; - snprintf(tmp, sizeof(tmp), "%08lx", (long)a); - Jim_SetResultFormatted(interp, "error reading target @ 0x%s", tmp); + Jim_SetResultFormatted(interp, "error reading target @ 0x%08lx", (long)addr); return JIM_ERR; } - command_print(NULL, "0x%08x ", (int)(a)); - switch (b) { + command_print_sameline(NULL, "0x%08x ", (int)(addr)); + switch (dwidth) { case 4: for (x = 0; x < 16 && x < y; x += 4) { z = target_buffer_get_u32(target, &(target_buf[x])); - command_print(NULL, "%08x ", (int)(z)); + command_print_sameline(NULL, "%08x ", (int)(z)); } for (; (x < 16) ; x += 4) - command_print(NULL, " "); + command_print_sameline(NULL, " "); break; case 2: for (x = 0; x < 16 && x < y; x += 2) { z = target_buffer_get_u16(target, &(target_buf[x])); - command_print(NULL, "%04x ", (int)(z)); + command_print_sameline(NULL, "%04x ", (int)(z)); } for (; (x < 16) ; x += 2) - command_print(NULL, " "); + command_print_sameline(NULL, " "); break; case 1: default: for (x = 0 ; (x < 16) && (x < y) ; x += 1) { z = target_buffer_get_u8(target, &(target_buf[x])); - command_print(NULL, "%02x ", (int)(z)); + command_print_sameline(NULL, "%02x ", (int)(z)); } for (; (x < 16) ; x += 1) - command_print(NULL, " "); + command_print_sameline(NULL, " "); break; } /* ascii-ify the bytes */ @@ -4455,10 +4502,10 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* terminate */ target_buf[16] = 0; /* print - with a newline */ - command_print(NULL, "%s\n", target_buf); + command_print_sameline(NULL, "%s\n", target_buf); /* NEXT... */ - c -= 16; - a += 16; + bytes -= 16; + addr += 16; } return JIM_OK; } @@ -4860,6 +4907,15 @@ static int target_create(Jim_GetOptInfo *goi) /* found */ break; } + + /* check for deprecated name */ + if (target_types[x]->deprecated_name) { + if (0 == strcmp(cp, target_types[x]->deprecated_name)) { + /* found */ + LOG_WARNING("target name is deprecated use: \'%s\'", target_types[x]->name); + break; + } + } } if (target_types[x] == NULL) { Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); @@ -5093,8 +5149,10 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) target->head = head; curr = curr->next; } - if (target->rtos) + + if (target && target->rtos) retval = rtos_smp_init(head->target); + return retval; }