From e8e62c5aca494fa17a5e543831b8eef3740c9b1d Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 4 Jun 2021 15:05:17 +0200 Subject: [PATCH] target/tcl: Add get_reg function Change-Id: Id1be9554d1df2c07cec3161a0fd3a586fdf18246 Signed-off-by: Marc Schink Reviewed-on: https://review.openocd.org/c/openocd/+/5312 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 36 ++++++++++++++++ src/target/target.c | 101 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index c0df9c9ac..2bfa0deae 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5018,6 +5018,24 @@ set_reg @{pc 0 sp 0x1000@} @end example @end deffn +@deffn {Command} {$target_name get_reg} [-force] list +Get register values from the target and return them as Tcl dictionary with pairs +of register names and values. +If option "-force" is set, the register values are read directly from the +target, bypassing any caching. + +@itemize +@item @var{list} ... List of register names +@end itemize + +For example, the following command retrieves the values from the program +counter (pc) and stack pointer (sp) register: + +@example +get_reg @{pc sp@} +@end example +@end deffn + @deffn {Command} {$target_name cget} queryparm Each configuration parameter accepted by @command{$target_name configure} @@ -8521,6 +8539,24 @@ set_reg @{pc 0 sp 0x1000@} @end example @end deffn +@deffn {Command} {get_reg} [-force] list +Get register values from the target and return them as Tcl dictionary with pairs +of register names and values. +If option "-force" is set, the register values are read directly from the +target, bypassing any caching. + +@itemize +@item @var{list} ... List of register names +@end itemize + +For example, the following command retrieves the values from the program +counter (pc) and stack pointer (sp) register: + +@example +get_reg @{pc sp@} +@end example +@end deffn + @deffn {Command} {halt} [ms] @deffnx {Command} {wait_halt} [ms] The @command{halt} command first sends a halt request to the target, diff --git a/src/target/target.c b/src/target/target.c index 1d26cb91c..b72dc53e3 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4863,6 +4863,93 @@ void target_handle_event(struct target *target, enum target_event e) } } +static int target_jim_get_reg(Jim_Interp *interp, int argc, + Jim_Obj * const *argv) +{ + bool force = false; + + if (argc == 3) { + const char *option = Jim_GetString(argv[1], NULL); + + if (!strcmp(option, "-force")) { + argc--; + argv++; + force = true; + } else { + Jim_SetResultFormatted(interp, "invalid option '%s'", option); + return JIM_ERR; + } + } + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "[-force] list"); + return JIM_ERR; + } + + const int length = Jim_ListLength(interp, argv[1]); + + Jim_Obj *result_dict = Jim_NewDictObj(interp, NULL, 0); + + if (!result_dict) + return JIM_ERR; + + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx != NULL); + const struct target *target = get_current_target(cmd_ctx); + + for (int i = 0; i < length; i++) { + Jim_Obj *elem = Jim_ListGetIndex(interp, argv[1], i); + + if (!elem) + return JIM_ERR; + + const char *reg_name = Jim_String(elem); + + struct reg *reg = register_get_by_name(target->reg_cache, reg_name, + false); + + if (!reg || !reg->exist) { + Jim_SetResultFormatted(interp, "unknown register '%s'", reg_name); + return JIM_ERR; + } + + if (force) { + int retval = reg->type->get(reg); + + if (retval != ERROR_OK) { + Jim_SetResultFormatted(interp, "failed to read register '%s'", + reg_name); + return JIM_ERR; + } + } + + char *reg_value = buf_to_hex_str(reg->value, reg->size); + + if (!reg_value) { + LOG_ERROR("Failed to allocate memory"); + return JIM_ERR; + } + + char *tmp = alloc_printf("0x%s", reg_value); + + free(reg_value); + + if (!tmp) { + LOG_ERROR("Failed to allocate memory"); + return JIM_ERR; + } + + Jim_DictAddElement(interp, result_dict, elem, + Jim_NewStringObj(interp, tmp, -1)); + + free(tmp); + } + + Jim_SetResult(interp, result_dict); + + return JIM_OK; +} + static int target_jim_set_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { @@ -5696,6 +5783,13 @@ static const struct command_registration target_instance_command_handlers[] = { "from target memory", .usage = "arrayname bitwidth address count", }, + { + .name = "get_reg", + .mode = COMMAND_EXEC, + .jim_handler = target_jim_get_reg, + .help = "Get register values from the target", + .usage = "list", + }, { .name = "set_reg", .mode = COMMAND_EXEC, @@ -6785,6 +6879,13 @@ static const struct command_registration target_exec_command_handlers[] = { "and write the 8/16/32 bit values", .usage = "arrayname bitwidth address count", }, + { + .name = "get_reg", + .mode = COMMAND_EXEC, + .jim_handler = target_jim_get_reg, + .help = "Get register values from the target", + .usage = "list", + }, { .name = "set_reg", .mode = COMMAND_EXEC,