[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openocd-development
Subject:    [PATCH]: d6f647fb48 Create the `riscv repeat_read` command
From:       gerrit () openocd ! org
Date:       2024-05-09 16:49:13
Message-ID: 20240509164913.29942D7 () openocd ! org
[Download RAW message or body]

This is an automated email from Gerrit.

"Bernhard Rosenkraenzer <bero@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 <bero@baylibre.com>
Date:   Thu May 9 16:07:47 2024 +0200

    Create the `riscv repeat_read` command
    
    This is based on Tim Newsome <tim@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 <tim@sifive.com>
    Signed-off-by: Bernhard Rosenkränzer <bero@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);

-- 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic