aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Vanek <vanekt@fbl.cz>2015-04-24 07:33:50 +0200
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>2016-07-17 23:30:09 +0100
commitf4496b25e3040e29b9bc78dd5bf8ac8128c09a1e (patch)
tree68a139b78b74cef0d18ed5a3ba5f06e4441c8693
parent7a0473bbb6cd4d83ce43fc4b722083b315b80a98 (diff)
arm_adi_v5: add dap apreg command for AP register read/write
A developer tool: Direct access to AP registers can be useful for handling vendor specific AP like Freescale Kinetis MDM or Atmel SMAP. Change-Id: Ie2c7160fc6b2e398513eb23e1e52cbb52b88d9bd Signed-off-by: Tomas Vanek <vanekt@fbl.cz> Reviewed-on: http://openocd.zylin.com/2777 Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com> Tested-by: jenkins
-rw-r--r--doc/openocd.texi6
-rw-r--r--src/target/arm_adi_v5.c47
2 files changed, 53 insertions, 0 deletions
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 1d517213..983ce3ca 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -7836,6 +7836,12 @@ Displays ID register from AP @var{num},
defaulting to the currently selected AP.
@end deffn
+@deffn Command {dap apreg} ap_num reg [value]
+Displays content of a register @var{reg} from AP @var{ap_num}
+or set a new value @var{value}.
+@var{reg} is byte address of a word register, 0, 4, 8 ... 0xfc.
+@end deffn
+
@deffn Command {dap apsel} [num]
Select AP @var{num}, defaulting to 0.
@end deffn
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index eb3392bf..f58afdc0 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -1556,6 +1556,45 @@ COMMAND_HANDLER(dap_apid_command)
return retval;
}
+COMMAND_HANDLER(dap_apreg_command)
+{
+ struct target *target = get_current_target(CMD_CTX);
+ struct arm *arm = target_to_arm(target);
+ struct adiv5_dap *dap = arm->dap;
+
+ uint32_t apsel, reg, value;
+ int retval;
+
+ if (CMD_ARGC < 2 || CMD_ARGC > 3)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
+ /* AP address is in bits 31:24 of DP_SELECT */
+ if (apsel >= 256)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg);
+ if (reg >= 256 || (reg & 3))
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (CMD_ARGC == 3) {
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
+ retval = dap_queue_ap_write(dap_ap(dap, apsel), reg, value);
+ } else {
+ retval = dap_queue_ap_read(dap_ap(dap, apsel), reg, &value);
+ }
+ if (retval == ERROR_OK)
+ retval = dap_run(dap);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (CMD_ARGC == 2)
+ command_print(CMD_CTX, "0x%08" PRIx32, value);
+
+ return retval;
+}
+
COMMAND_HANDLER(dap_ti_be_32_quirks_command)
{
struct target *target = get_current_target(CMD_CTX);
@@ -1616,6 +1655,14 @@ static const struct command_registration dap_commands[] = {
.usage = "[ap_num]",
},
{
+ .name = "apreg",
+ .handler = dap_apreg_command,
+ .mode = COMMAND_EXEC,
+ .help = "read/write a register from AP "
+ "(reg is byte address of a word register, like 0 4 8...)",
+ .usage = "ap_num reg [value]",
+ },
+ {
.name = "baseaddr",
.handler = dap_baseaddr_command,
.mode = COMMAND_EXEC,