This is an automated email from Gerrit. "Bernhard Rosenkraenzer <b...@baylibre.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8259
-- gerrit commit d6f647fb487f68de29832e8880872f22d08dea88 Author: Bernhard Rosenkränzer <b...@baylibre.com> Date: Thu May 9 16:07:47 2024 +0200 Create the `riscv repeat_read` command This is based on Tim Newsome <t...@sifive.com>'s work on the openocd-riscv fork, merged into one commit and modified to work on top of current master. Change-Id: Ic1d750d329b2ab5136eb4b45d1f70f96ccac1b90 Signed-off-by: Tim Newsome <t...@sifive.com> Signed-off-by: Bernhard Rosenkränzer <b...@baylibre.com> diff --git a/doc/openocd.texi b/doc/openocd.texi index 55e6e76808..f23618b721 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11217,6 +11217,12 @@ encountering the target being busy. This command resets those learned values after `wait` scans. It's only useful for testing OpenOCD itself. @end deffn +@deffn {Command} {riscv repeat_read} count address [size=4] +Quickly read count words of the given size from address. This can be useful +to read out a buffer that's memory-mapped to be accessed through a single +address, or to sample a changing value in a memory-mapped device. +@end deffn + @deffn {Command} {riscv set_command_timeout_sec} [seconds] Set the wall-clock timeout (in seconds) for individual commands. The default should work fine for all but the slowest targets (eg. simulators). diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 720fb60a1b..1c4e154e5c 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -720,7 +720,8 @@ COMMAND_HANDLER(handle_flash_md_command) retval = flash_driver_read(bank, buffer, offset, sizebytes); if (retval == ERROR_OK) - target_handle_md_output(CMD, target, address, wordsize, count, buffer); + target_handle_md_output(CMD, target, address, wordsize, count, + buffer, true); free(buffer); diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 80cca1ed50..1e7180318a 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -2146,7 +2146,8 @@ COMMAND_HANDLER(dsp563xx_mem_command) err = dsp563xx_read_memory(target, mem_type, address, sizeof(uint32_t), count, buffer); if (err == ERROR_OK) - target_handle_md_output(CMD, target, address, sizeof(uint32_t), count, buffer); + target_handle_md_output(CMD, target, address, sizeof(uint32_t), + count, buffer, true); } else { b = buffer; diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 9cd4922d20..ac253566bc 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -2861,7 +2861,53 @@ COMMAND_HANDLER(handle_info) return 0; } +COMMAND_HANDLER(handle_repeat_read) +{ + struct target *target = get_current_target(CMD_CTX); + RISCV_INFO(r); + + if (CMD_ARGC < 2) { + LOG_ERROR("Command requires at least count and address arguments."); + return ERROR_COMMAND_SYNTAX_ERROR; + } + if (CMD_ARGC > 3) { + LOG_ERROR("Command takes at most 3 arguments."); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + uint32_t count; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], count); + target_addr_t address; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], address); + uint32_t size = 4; + if (CMD_ARGC > 2) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size); + + if (count == 0) + return ERROR_OK; + + uint8_t *buffer = malloc(size * count); + if (!buffer) { + LOG_ERROR("malloc failed"); + return ERROR_FAIL; + } + int result = r->read_memory(target, address, size, count, buffer, 0); + if (result == ERROR_OK) { + target_handle_md_output(cmd, target, address, size, count, buffer, + false); + } + free(buffer); + return result; +} + static const struct command_registration riscv_exec_command_handlers[] = { + { + .name = "repeat_read", + .handler = handle_repeat_read, + .mode = COMMAND_ANY, + .usage = "riscv repeat_read count address [size=4]", + .help = "Repeatedly read the value at address." + }, { .name = "info", .handler = handle_info, diff --git a/src/target/target.c b/src/target/target.c index 5168305dee..9f8373c7a3 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3338,7 +3338,7 @@ COMMAND_HANDLER(handle_step_command) void target_handle_md_output(struct command_invocation *cmd, struct target *target, target_addr_t address, unsigned size, - unsigned count, const uint8_t *buffer) + unsigned count, const uint8_t *buffer, bool include_address) { const unsigned line_bytecnt = 32; unsigned line_modulo = line_bytecnt / size; @@ -3367,7 +3367,7 @@ void target_handle_md_output(struct command_invocation *cmd, } for (unsigned i = 0; i < count; i++) { - if (i % line_modulo == 0) { + if (include_address && (i % line_modulo == 0)) { output_len += snprintf(output + output_len, sizeof(output) - output_len, TARGET_ADDR_FMT ": ", @@ -3451,7 +3451,7 @@ COMMAND_HANDLER(handle_md_command) struct target *target = get_current_target(CMD_CTX); int retval = fn(target, address, size, count, buffer); if (retval == ERROR_OK) - target_handle_md_output(CMD, target, address, size, count, buffer); + target_handle_md_output(CMD, target, address, size, count, buffer, true); free(buffer); diff --git a/src/target/target.h b/src/target/target.h index d5c0e0e8c7..57dc2e5f37 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -779,7 +779,7 @@ void target_handle_event(struct target *t, enum target_event e); void target_handle_md_output(struct command_invocation *cmd, struct target *target, target_addr_t address, unsigned size, - unsigned count, const uint8_t *buffer); + unsigned count, const uint8_t *buffer, bool include_address); int target_profiling_default(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); --