X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=2522408382e31e695c7af9f76da6278cb950ceac;hb=91e3268737b578a182cb661d60551657f799ab3c;hp=ebddbba823d2fca74574169ff33a6640f0caaa23;hpb=646ce814b4fb678b7d8d341afe0694c266112426;p=openocd.git diff --git a/src/target/target.c b/src/target/target.c index ebddbba823..2522408382 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -45,8 +45,10 @@ #include "image.h" -static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv); -static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv); +static int target_array2mem(Jim_Interp *interp, struct target *target, + int argc, Jim_Obj *const *argv); +static int target_mem2array(Jim_Interp *interp, struct target *target, + int argc, Jim_Obj *const *argv); /* targets */ extern struct target_type arm7tdmi_target; @@ -475,6 +477,11 @@ int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode /* We want any events to be processed before the prompt */ retval = target_call_timer_callbacks_now(); + struct target *target; + for (target = all_targets; target; target = target->next) { + target->type->check_reset(target); + } + return retval; } @@ -497,6 +504,12 @@ static int default_examine(struct target *target) return ERROR_OK; } +/* no check by default */ +static int default_check_reset(struct target *target) +{ + return ERROR_OK; +} + int target_examine_one(struct target *target) { return target->type->examine(target); @@ -706,6 +719,9 @@ static int target_init_one(struct command_context *cmd_ctx, if (type->examine == NULL) type->examine = default_examine; + if (type->check_reset== NULL) + type->check_reset = default_check_reset; + int retval = type->init_target(cmd_ctx, target); if (ERROR_OK != retval) { @@ -1723,15 +1739,6 @@ static int sense_handler(void) return ERROR_OK; } -static void target_call_event_callbacks_all(enum target_event e) { - struct target *target; - target = all_targets; - while (target) { - target_call_event_callbacks(target, e); - target = target->next; - } -} - /* process target state changes */ static int handle_target(void *priv) { @@ -1751,7 +1758,7 @@ static int handle_target(void *priv) int did_something = 0; if (runSrstAsserted) { - target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT); + LOG_INFO("srst asserted detected, running srst_asserted proc."); Jim_Eval(interp, "srst_asserted"); did_something = 1; } @@ -1762,7 +1769,7 @@ static int handle_target(void *priv) } if (runPowerDropout) { - target_call_event_callbacks_all(TARGET_EVENT_GDB_HALT); + LOG_INFO("Power dropout detected, running power_dropout proc."); Jim_Eval(interp, "power_dropout"); did_something = 1; } @@ -1804,6 +1811,14 @@ static int handle_target(void *priv) /* polling may fail silently until the target has been examined */ if ((retval = target_poll(target)) != ERROR_OK) { + /* FIX!!!!! If we add a LOG_INFO() here to output a line in GDB + * *why* we are aborting GDB, then we'll spam telnet when the + * poll is failing persistently. + * + * If we could implement an event that detected the + * target going from non-pollable to pollable, we could issue + * an error only upon the transition. + */ target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); return retval; } @@ -2154,7 +2169,7 @@ static void handle_md_output(struct command_context *cmd_ctx, const char *value_fmt; switch (size) { case 4: value_fmt = "%8.8x "; break; - case 2: value_fmt = "%4.2x "; break; + case 2: value_fmt = "%4.4x "; break; case 1: value_fmt = "%2.2x "; break; default: /* "can't happen", caller checked */ @@ -2488,7 +2503,7 @@ COMMAND_HANDLER(handle_dump_image_command) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, - "dumped %zu bytes in %fs (%0.3f kb/s)", fileio.size, + "dumped %ld bytes in %fs (%0.3f kb/s)", (long)fileio.size, duration_elapsed(&bench), duration_kbps(&bench, fileio.size)); } @@ -2960,7 +2975,8 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam fclose(f); } -/* profiling samples the CPU PC as quickly as OpenOCD is able, which will be used as a random sampling of PC */ +/* profiling samples the CPU PC as quickly as OpenOCD is able, + * which will be used as a random sampling of PC */ COMMAND_HANDLER(handle_profile_command) { struct target *target = get_current_target(CMD_CTX); @@ -2976,6 +2992,12 @@ COMMAND_HANDLER(handle_profile_command) timeval_add_time(&timeout, offset, 0); + /** + * @todo: Some cores let us sample the PC without the + * annoying halt/resume step; for example, ARMv7 PCSR. + * Provide a way to use that more efficient mechanism. + */ + command_print(CMD_CTX, "Starting profiling. Halting and resuming the target as often as we can..."); static const int maxSample = 10000; @@ -3287,7 +3309,9 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return target_array2mem(interp,target, argc-1, argv + 1); } -static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) + +static int target_array2mem(Jim_Interp *interp, struct target *target, + int argc, Jim_Obj *const *argv) { long l; uint32_t width; @@ -3789,11 +3813,13 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) return JIM_OK; } -static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +static int +jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = strcmp(Jim_GetString(argv[0], NULL), "configure") == 0; + goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); int need_args = 1 + goi.isconfigure; if (goi.argc < need_args) { @@ -3988,13 +4014,15 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_OK; } -static int jim_target_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +static int jim_target_mem2array(Jim_Interp *interp, + int argc, Jim_Obj *const *argv) { struct target *target = Jim_CmdPrivData(interp); return target_mem2array(interp, target, argc - 1, argv + 1); } -static int jim_target_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +static int jim_target_array2mem(Jim_Interp *interp, + int argc, Jim_Obj *const *argv) { struct target *target = Jim_CmdPrivData(interp); return target_array2mem(interp, target, argc - 1, argv + 1); @@ -4026,6 +4054,21 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv return JIM_OK; } +static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) + { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + + if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) + return JIM_ERR; + + return JIM_OK; +} + static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) @@ -4079,6 +4122,11 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) struct target *target = Jim_CmdPrivData(goi.interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); + if (!(target_was_examined(target))) + { + LOG_ERROR("Target not examined yet"); + return ERROR_TARGET_NOT_EXAMINED; + } if (!target->type->assert_reset || !target->type->deassert_reset) { Jim_SetResult_sprintf(interp, @@ -4214,108 +4262,129 @@ static const struct command_registration target_instance_command_handlers[] = { { .name = "configure", .mode = COMMAND_CONFIG, - .jim_handler = &jim_target_configure, - .usage = "[ ...]", + .jim_handler = jim_target_configure, .help = "configure a new target for use", + .usage = "[target_attribute ...]", }, { .name = "cget", .mode = COMMAND_ANY, - .jim_handler = &jim_target_configure, - .usage = " [ ...]", - .help = "configure a new target for use", + .jim_handler = jim_target_configure, + .help = "returns the specified target attribute", + .usage = "target_attribute", }, { .name = "mww", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_mw, - .usage = "
[]", + .jim_handler = jim_target_mw, .help = "Write 32-bit word(s) to target memory", + .usage = "address data [count]", }, { .name = "mwh", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_mw, - .usage = "
[]", + .jim_handler = jim_target_mw, .help = "Write 16-bit half-word(s) to target memory", + .usage = "address data [count]", }, { .name = "mwb", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_mw, - .usage = "
[]", + .jim_handler = jim_target_mw, .help = "Write byte(s) to target memory", + .usage = "address data [count]", }, { .name = "mdw", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_md, - .usage = "
[]", + .jim_handler = jim_target_md, .help = "Display target memory as 32-bit words", + .usage = "address [count]", }, { .name = "mdh", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_md, - .usage = "
[]", + .jim_handler = jim_target_md, .help = "Display target memory as 16-bit half-words", + .usage = "address [count]", }, { .name = "mdb", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_md, - .usage = "
[]", + .jim_handler = jim_target_md, .help = "Display target memory as 8-bit bytes", + .usage = "address [count]", }, { .name = "array2mem", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_array2mem, + .jim_handler = jim_target_array2mem, + .help = "Writes Tcl array of 8/16/32 bit numbers " + "to target memory", + .usage = "arrayname bitwidth address count", }, { .name = "mem2array", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_mem2array, + .jim_handler = jim_target_mem2array, + .help = "Loads Tcl array of 8/16/32 bit numbers " + "from target memory", + .usage = "arrayname bitwidth address count", }, { .name = "eventlist", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_event_list, + .jim_handler = jim_target_event_list, + .help = "displays a table of events defined for this target", }, { .name = "curstate", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_current_state, + .jim_handler = jim_target_current_state, + .help = "displays the current state of this target", }, { .name = "arp_examine", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_examine, + .jim_handler = jim_target_examine, + .help = "used internally for reset processing", + }, + { + .name = "arp_halt_gdb", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_halt_gdb, + .help = "used internally for reset processing to halt GDB", }, { .name = "arp_poll", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_poll, + .jim_handler = jim_target_poll, + .help = "used internally for reset processing", }, { .name = "arp_reset", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_reset, + .jim_handler = jim_target_reset, + .help = "used internally for reset processing", }, { .name = "arp_halt", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_halt, + .jim_handler = jim_target_halt, + .help = "used internally for reset processing", }, { .name = "arp_waitstate", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_wait_state, + .jim_handler = jim_target_wait_state, + .help = "used internally for reset processing", }, { .name = "invoke-event", .mode = COMMAND_EXEC, - .jim_handler = &jim_target_invoke_event, + .jim_handler = jim_target_invoke_event, + .help = "invoke handler for specified event", + .usage = "event_name", }, COMMAND_REGISTRATION_DONE }; @@ -4467,7 +4536,7 @@ static int target_create(Jim_GetOptInfo *goi) } *tpp = target; } - + /* now - create the new target name command */ const const struct command_registration target_subcommands[] = { { @@ -4610,51 +4679,54 @@ static const struct command_registration target_subcommand_handlers[] = { { .name = "init", .mode = COMMAND_CONFIG, - .handler = &handle_target_init_command, + .handler = handle_target_init_command, .help = "initialize targets", }, { .name = "create", + /* REVISIT this should be COMMAND_CONFIG ... */ .mode = COMMAND_ANY, - .jim_handler = &jim_target_create, - .usage = " ...", - .help = "Returns the currently selected target", + .jim_handler = jim_target_create, + .usage = "name type '-chain-position' name [options ...]", + .help = "Creates and selects a new target", }, { .name = "current", .mode = COMMAND_ANY, - .jim_handler = &jim_target_current, + .jim_handler = jim_target_current, .help = "Returns the currently selected target", }, { .name = "types", .mode = COMMAND_ANY, - .jim_handler = &jim_target_types, - .help = "Returns the available target types as a list of strings", + .jim_handler = jim_target_types, + .help = "Returns the available target types as " + "a list of strings", }, { .name = "names", .mode = COMMAND_ANY, - .jim_handler = &jim_target_names, + .jim_handler = jim_target_names, .help = "Returns the names of all targets as a list of strings", }, { .name = "number", .mode = COMMAND_ANY, - .jim_handler = &jim_target_number, - .usage = "", - .help = "Returns the name of target ", + .jim_handler = jim_target_number, + .usage = "number", + .help = "Returns the name of the numbered target " + "(DEPRECATED)", }, { .name = "count", .mode = COMMAND_ANY, - .jim_handler = &jim_target_count, - .help = "Returns the number of targets as an integer", + .jim_handler = jim_target_count, + .help = "Returns the number of targets as an integer " + "(DEPRECATED)", }, COMMAND_REGISTRATION_DONE }; - struct FastLoad { uint32_t address; @@ -4828,11 +4900,11 @@ COMMAND_HANDLER(handle_fast_load_command) static const struct command_registration target_command_handlers[] = { { .name = "targets", - .handler = &handle_targets_command, + .handler = handle_targets_command, .mode = COMMAND_ANY, - .help = "change current command line target (one parameter) " - "or list targets (no parameters)", - .usage = "[]", + .help = "change current default target (one parameter) " + "or prints table of all targets (no parameters)", + .usage = "[target]", }, { .name = "target", @@ -4849,72 +4921,92 @@ int target_register_commands(struct command_context *cmd_ctx) return register_commands(cmd_ctx, NULL, target_command_handlers); } +static bool target_reset_nag = true; + +bool get_target_reset_nag(void) +{ + return target_reset_nag; +} + +COMMAND_HANDLER(handle_target_reset_nag) +{ + return CALL_COMMAND_HANDLER(handle_command_parse_bool, + &target_reset_nag, "Nag after each reset about options to improve " + "performance"); +} + static const struct command_registration target_exec_command_handlers[] = { { .name = "fast_load_image", - .handler = &handle_fast_load_image_command, + .handler = handle_fast_load_image_command, .mode = COMMAND_ANY, - .help = "Load image into memory, mainly for profiling purposes", - .usage = "
['bin'|'ihex'|'elf'|'s19'] " - "[min_address] [max_length]", + .help = "Load image into server memory for later use by " + "fast_load; primarily for profiling", + .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " + "[min_address [max_length]]", }, { .name = "fast_load", - .handler = &handle_fast_load_command, - .mode = COMMAND_ANY, + .handler = handle_fast_load_command, + .mode = COMMAND_EXEC, .help = "loads active fast load image to current target " "- mainly for profiling purposes", }, { .name = "profile", - .handler = &handle_profile_command, + .handler = handle_profile_command, .mode = COMMAND_EXEC, .help = "profiling samples the CPU PC", }, /** @todo don't register virt2phys() unless target supports it */ { .name = "virt2phys", - .handler = &handle_virt2phys_command, + .handler = handle_virt2phys_command, .mode = COMMAND_ANY, .help = "translate a virtual address into a physical address", + .usage = "virtual_address", }, - { .name = "reg", - .handler = &handle_reg_command, + .handler = handle_reg_command, .mode = COMMAND_EXEC, - .help = "display or set a register", + .help = "display or set a register; with no arguments, " + "displays all registers and their values", + .usage = "[(register_name|register_number) [value]]", }, - { .name = "poll", - .handler = &handle_poll_command, + .handler = handle_poll_command, .mode = COMMAND_EXEC, - .help = "poll target state", + .help = "poll target state; or reconfigure background polling", + .usage = "['on'|'off']", }, { .name = "wait_halt", - .handler = &handle_wait_halt_command, + .handler = handle_wait_halt_command, .mode = COMMAND_EXEC, - .help = "wait for target halt", - .usage = "[time (s)]", + .help = "wait up to the specified number of milliseconds " + "(default 5) for a previously requested halt", + .usage = "[milliseconds]", }, { .name = "halt", - .handler = &handle_halt_command, + .handler = handle_halt_command, .mode = COMMAND_EXEC, - .help = "halt target", + .help = "request target to halt, then wait up to the specified" + "number of milliseconds (default 5) for it to complete", + .usage = "[milliseconds]", }, { .name = "resume", - .handler = &handle_resume_command, + .handler = handle_resume_command, .mode = COMMAND_EXEC, - .help = "resume target", - .usage = "[
]", + .help = "resume target execution from current PC or address", + .usage = "[address]", }, { .name = "reset", - .handler = &handle_reset_command, + .handler = handle_reset_command, .mode = COMMAND_EXEC, .usage = "[run|halt|init]", .help = "Reset all targets into the specified mode." @@ -4922,133 +5014,135 @@ static const struct command_registration target_exec_command_handlers[] = { }, { .name = "soft_reset_halt", - .handler = &handle_soft_reset_halt_command, + .handler = handle_soft_reset_halt_command, .mode = COMMAND_EXEC, .help = "halt the target and do a soft reset", }, { - .name = "step", - .handler = &handle_step_command, + .handler = handle_step_command, .mode = COMMAND_EXEC, - .help = "step one instruction from current PC or [addr]", - .usage = "[
]", + .help = "step one instruction from current PC or address", + .usage = "[address]", }, { - .name = "mdw", - .handler = &handle_md_command, + .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory words", - .usage = "[phys] [count]", + .usage = "['phys'] address [count]", }, { .name = "mdh", - .handler = &handle_md_command, + .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory half-words", - .usage = "[phys] [count]", + .usage = "['phys'] address [count]", }, { .name = "mdb", - .handler = &handle_md_command, + .handler = handle_md_command, .mode = COMMAND_EXEC, .help = "display memory bytes", - .usage = "[phys] [count]", + .usage = "['phys'] address [count]", }, { - .name = "mww", - .handler = &handle_mw_command, + .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory word", - .usage = "[phys] [count]", + .usage = "['phys'] address value [count]", }, { .name = "mwh", - .handler = &handle_mw_command, + .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory half-word", - .usage = "[phys] [count]", + .usage = "['phys'] address value [count]", }, { .name = "mwb", - .handler = &handle_mw_command, + .handler = handle_mw_command, .mode = COMMAND_EXEC, .help = "write memory byte", - .usage = "[phys] [count]", + .usage = "['phys'] address value [count]", }, { - .name = "bp", - .handler = &handle_bp_command, + .handler = handle_bp_command, .mode = COMMAND_EXEC, - .help = "list or set breakpoint", - .usage = "[
[hw]]", + .help = "list or set hardware or software breakpoint", + .usage = "[address length ['hw']]", }, { .name = "rbp", - .handler = &handle_rbp_command, + .handler = handle_rbp_command, .mode = COMMAND_EXEC, .help = "remove breakpoint", - .usage = "
", + .usage = "address", }, { - .name = "wp", - .handler = &handle_wp_command, + .handler = handle_wp_command, .mode = COMMAND_EXEC, - .help = "list or set watchpoint", - .usage = "[
[value] [mask]]", + .help = "list (no params) or create watchpoints", + .usage = "[address length [('r'|'w'|'a') value [mask]]]", }, { .name = "rwp", - .handler = &handle_rwp_command, + .handler = handle_rwp_command, .mode = COMMAND_EXEC, .help = "remove watchpoint", - .usage = "
", - + .usage = "address", }, { .name = "load_image", - .handler = &handle_load_image_command, + .handler = handle_load_image_command, .mode = COMMAND_EXEC, - .usage = "
['bin'|'ihex'|'elf'|'s19'] " + .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " "[min_address] [max_length]", }, { .name = "dump_image", - .handler = &handle_dump_image_command, + .handler = handle_dump_image_command, .mode = COMMAND_EXEC, - .usage = "
", + .usage = "filename address size", }, { .name = "verify_image", - .handler = &handle_verify_image_command, + .handler = handle_verify_image_command, .mode = COMMAND_EXEC, - .usage = " [offset] [type]", + .usage = "filename [offset [type]]", }, { .name = "test_image", - .handler = &handle_test_image_command, + .handler = handle_test_image_command, .mode = COMMAND_EXEC, - .usage = " [offset] [type]", + .usage = "filename [offset [type]]", }, { .name = "ocd_mem2array", .mode = COMMAND_EXEC, - .jim_handler = &jim_mem2array, - .help = "read memory and return as a TCL array " + .jim_handler = jim_mem2array, + .help = "read 8/16/32 bit memory and return as a TCL array " "for script processing", - .usage = "
", + .usage = "arrayname bitwidth address count", }, { .name = "ocd_array2mem", .mode = COMMAND_EXEC, - .jim_handler = &jim_array2mem, + .jim_handler = jim_array2mem, .help = "convert a TCL array to memory locations " - "and write the values", - .usage = "
", + "and write the 8/16/32 bit values", + .usage = "arrayname bitwidth address count", + }, + { + .name = "reset_nag", + .handler = handle_target_reset_nag, + .mode = COMMAND_ANY, + .help = "Nag after each reset about options that could have been " + "enabled to improve performance. ", + .usage = "['enable'|'disable']", }, COMMAND_REGISTRATION_DONE };