diff options
author | Antonio Borneo <borneo.antonio@gmail.com> | 2021-04-29 10:49:50 +0200 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2021-06-03 23:27:13 +0100 |
commit | 0c64bb2583a67b551a482ddc13a08dc71a143da3 (patch) | |
tree | d6b82603574c80731c0f9ce6a5965599614530c7 | |
parent | ffaef5809c68d81359de5573d3971a4b6bb521c3 (diff) | |
download | riscv-openocd-0c64bb2583a67b551a482ddc13a08dc71a143da3.zip riscv-openocd-0c64bb2583a67b551a482ddc13a08dc71a143da3.tar.gz riscv-openocd-0c64bb2583a67b551a482ddc13a08dc71a143da3.tar.bz2 |
target/cortex_a: add support for watchpoint length of 1, 2 and 4 bytes
Use byte address select for 1 and 2 bytes length.
Use normal mode for 4 bytes length.
Change-Id: I28d182f25145d0635de64d0361d456f1ad96640e
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/6197
Tested-by: jenkins
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
-rw-r--r-- | src/target/cortex_a.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 78daed3..9a48cc8 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -61,6 +61,7 @@ #include "jtag/interface.h" #include "transport/transport.h" #include "smp.h" +#include <helper/bits.h> #include <helper/time_support.h> static int cortex_a_poll(struct target *target); @@ -1686,8 +1687,9 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *wat int retval = ERROR_OK; int wrp_i = 0; uint32_t control; - uint8_t address_mask = ilog2(watchpoint->length); - uint8_t byte_address_select = 0xFF; + uint32_t address; + uint8_t address_mask; + uint8_t byte_address_select; uint8_t load_store_access_control = 0x3; struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; @@ -1707,18 +1709,52 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *wat return ERROR_FAIL; } - if (address_mask == 0x1 || address_mask == 0x2) { - LOG_WARNING("length must be a power of 2 and different than 2 and 4"); + if (watchpoint->length == 0 || watchpoint->length > 0x80000000U || + (watchpoint->length & (watchpoint->length - 1))) { + LOG_WARNING("watchpoint length must be a power of 2"); return ERROR_FAIL; } + if (watchpoint->address & (watchpoint->length - 1)) { + LOG_WARNING("watchpoint address must be aligned at length"); + return ERROR_FAIL; + } + + /* FIXME: ARM DDI 0406C: address_mask is optional. What to do if it's missing? */ + /* handle wp length 1 and 2 through byte select */ + switch (watchpoint->length) { + case 1: + byte_address_select = BIT(watchpoint->address & 0x3); + address = watchpoint->address & ~0x3; + address_mask = 0; + break; + + case 2: + byte_address_select = 0x03 << (watchpoint->address & 0x2); + address = watchpoint->address & ~0x3; + address_mask = 0; + break; + + case 4: + byte_address_select = 0x0f; + address = watchpoint->address; + address_mask = 0; + break; + + default: + byte_address_select = 0xff; + address = watchpoint->address; + address_mask = ilog2(watchpoint->length); + break; + } + watchpoint->set = wrp_i + 1; control = (address_mask << 24) | (byte_address_select << 5) | (load_store_access_control << 3) | (0x3 << 1) | 1; wrp_list[wrp_i].used = 1; - wrp_list[wrp_i].value = (watchpoint->address & 0xFFFFFFFC); + wrp_list[wrp_i].value = address; wrp_list[wrp_i].control = control; retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base |