From: openocd-gerrit <ope...@us...> - 2025-06-07 10:06:16
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 6a40fe64d63568d307fdfbb4666784a848222787 (commit) from 2065bac3805102a37a2d10d374298b875d750392 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 6a40fe64d63568d307fdfbb4666784a848222787 Author: Marc Schink <de...@za...> Date: Sat Nov 23 14:43:51 2024 +0000 flash/nor/tcl: Add 'read_memory' command This command allows to read non-memory mapped flash content directly via Tcl script. The API is the same as for the 'read_memory' command for targets. Change-Id: I4a8d0d7ea2f778ac8f1501227b60b964c881cb84 Signed-off-by: Marc Schink <de...@za...> Reviewed-on: https://review.openocd.org/c/openocd/+/8634 Reviewed-by: Antonio Borneo <bor...@gm...> Tested-by: jenkins diff --git a/doc/openocd.texi b/doc/openocd.texi index 27ed46b92..c7d8c7d0d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5870,6 +5870,24 @@ The flash bank to use is inferred from the @var{address} of each block, and the specified length must stay within that bank. @end deffn +@deffn {Command} {flash read_memory} address width count +This function provides an efficient way to read flash memory from a Tcl script. +A Tcl list containing the requested memory elements is returned by this function. + +@itemize +@item @var{address} ... flash memory address +@item @var{width} ... memory access bit size, can be 8, 16, 32 or 64 +@item @var{count} ... number of elements to read +@end itemize + +For example, the following command reads two 32 bit words from the flash +memory at address 0x08000000: + +@example +flash read_memory 0x08000000 32 2 +@end example +@end deffn + @deffn {Command} {flash write_bank} num filename [offset] Write the binary @file{filename} to flash bank @var{num}, starting at @var{offset} bytes from the beginning of the bank. If @var{offset} diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index e21620934..0d41e49c8 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -727,6 +727,124 @@ COMMAND_HANDLER(handle_flash_md_command) return retval; } +COMMAND_HANDLER(handle_flash_read_memory_command) +{ + /* + * CMD_ARGV[0] = memory address + * CMD_ARGV[1] = desired element width in bits + * CMD_ARGV[2] = number of elements to read + */ + + if (CMD_ARGC != 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + /* Arg 1: Memory address. */ + target_addr_t addr; + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], addr); + + /* Arg 2: Bit width of one element. */ + unsigned int width_bits; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], width_bits); + + /* Arg 3: Number of elements to read. */ + unsigned int count; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count); + + switch (width_bits) { + case 8: + case 16: + case 32: + case 64: + break; + default: + command_print(CMD, "invalid width, must be 8, 16, 32 or 64"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + if (count > 65536) { + command_print(CMD, "too large read request, exceeds 64K elements"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + const unsigned int width = width_bits / 8; + /* -1 is needed to handle cases when (addr + count * width) results in zero + * due to overflow. + */ + if ((addr + count * width - 1) < addr) { + command_print(CMD, "memory region wraps over address zero"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + struct target *target = get_current_target(CMD_CTX); + struct flash_bank *bank; + int retval = get_flash_bank_by_addr(target, addr, true, &bank); + if (retval != ERROR_OK) + return retval; + + uint32_t offset = addr - bank->base; + uint32_t sizebytes = count * width_bits; + if (offset + sizebytes > bank->size) { + command_print(CMD, "cannot cross flash bank borders"); + return ERROR_FAIL; + } + + const size_t buffer_size = 4096; + uint8_t *buffer = malloc(buffer_size); + + if (!buffer) { + command_print(CMD, "failed to allocate memory"); + return ERROR_FAIL; + } + + char *separator = ""; + while (count > 0) { + const unsigned int max_chunk_len = buffer_size / width; + const size_t chunk_len = MIN(count, max_chunk_len); + + retval = flash_driver_read(bank, buffer, offset, chunk_len * width); + + if (retval != ERROR_OK) { + LOG_DEBUG("read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + addr, width_bits, chunk_len); + /* + * FIXME: we append the errmsg to the list of value already read. + * Add a way to flush and replace old output, but LOG_DEBUG() it + */ + command_print(CMD, "failed to read memory"); + free(buffer); + return retval; + } + + for (size_t i = 0; i < chunk_len ; i++) { + uint64_t v = 0; + + switch (width) { + case 8: + v = target_buffer_get_u64(target, &buffer[i * width]); + break; + case 4: + v = target_buffer_get_u32(target, &buffer[i * width]); + break; + case 2: + v = target_buffer_get_u16(target, &buffer[i * width]); + break; + case 1: + v = buffer[i]; + break; + } + + command_print_sameline(CMD, "%s0x%" PRIx64, separator, v); + separator = " "; + } + + count -= chunk_len; + offset += chunk_len * width; + } + + free(buffer); + + return ERROR_OK; +} COMMAND_HANDLER(handle_flash_write_bank_command) { @@ -1170,6 +1288,13 @@ static const struct command_registration flash_exec_command_handlers[] = { .usage = "address [count]", .help = "Display words from flash.", }, + { + .name = "read_memory", + .mode = COMMAND_EXEC, + .handler = handle_flash_read_memory_command, + .help = "Read Tcl list of 8/16/32/64 bit numbers from flash memory", + .usage = "address width count", + }, { .name = "write_bank", .handler = handle_flash_write_bank_command, ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 18 ++++++++ src/flash/nor/tcl.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) hooks/post-receive -- Main OpenOCD repository |