diff options
author | Marek Vrbka <marek.vrbka@codasip.com> | 2023-07-04 11:56:42 +0200 |
---|---|---|
committer | Marek Vrbka <marek.vrbka@codasip.com> | 2023-07-04 12:04:02 +0200 |
commit | ea115917b934249c1e8dc9dc8eccb2f503953e5d (patch) | |
tree | d79220f3425aaf3fd6670a22253ec1a53122496f /src/target | |
parent | 92c03192612bd7c41f4562b5f130ac8e1907d591 (diff) | |
download | riscv-openocd-ea115917b934249c1e8dc9dc8eccb2f503953e5d.zip riscv-openocd-ea115917b934249c1e8dc9dc8eccb2f503953e5d.tar.gz riscv-openocd-ea115917b934249c1e8dc9dc8eccb2f503953e5d.tar.bz2 |
target/riscv: Fix the trigger writing sequence
According to section 5.6 in the RISC-V debug specification, the previous
way to set triggers was incorrect, as was discussed as part of
https://github.com/riscv/riscv-openocd/issues/870. This commit fixes the
sequence to be in line with the specification as well as adds some comments
to clarify for any future reader as to what is actually done.
Change-Id: Iffc5cc0f866a466a7aaa72a4c53ee95c9080ac9d
Signed-off-by: Marek Vrbka <marek.vrbka@codasip.com>
Diffstat (limited to 'src/target')
-rw-r--r-- | src/target/riscv/riscv.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 94fbb67..18d566e 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -572,33 +572,46 @@ static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdat riscv_reg_t tdata1_ignore_mask) { riscv_reg_t tdata1_rb, tdata2_rb; + // Select which trigger to use if (riscv_set_register(target, GDB_REGNO_TSELECT, idx) != ERROR_OK) return ERROR_FAIL; + + // Disable the trigger by writing 0 to it + if (riscv_set_register(target, GDB_REGNO_TDATA1, 0) != ERROR_OK) + return ERROR_FAIL; + + // Set trigger data for tdata2 (and tdata3 if it was supported) + if (riscv_set_register(target, GDB_REGNO_TDATA2, tdata2) != ERROR_OK) + return ERROR_FAIL; + + // Set trigger data for tdata1 if (riscv_set_register(target, GDB_REGNO_TDATA1, tdata1) != ERROR_OK) return ERROR_FAIL; + + // Read back tdata1, tdata2, (tdata3), and check if the configuration is supported if (riscv_get_register(target, &tdata1_rb, GDB_REGNO_TDATA1) != ERROR_OK) return ERROR_FAIL; - if ((tdata1 & ~tdata1_ignore_mask) != (tdata1_rb & ~tdata1_ignore_mask)) { - LOG_TARGET_DEBUG(target, - "Trigger %u doesn't support what we need; After writing 0x%" - PRIx64 " to tdata1 it contains 0x%" PRIx64 - "; tdata1_ignore_mask=0x%" PRIx64, - idx, tdata1, tdata1_rb, tdata1_ignore_mask); - riscv_set_register(target, GDB_REGNO_TDATA1, 0); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - if (riscv_set_register(target, GDB_REGNO_TDATA2, tdata2) != ERROR_OK) - return ERROR_FAIL; if (riscv_get_register(target, &tdata2_rb, GDB_REGNO_TDATA2) != ERROR_OK) return ERROR_FAIL; - if (tdata2 != tdata2_rb) { - LOG_TARGET_DEBUG(target, - "Trigger %u doesn't support what we need; wrote 0x%" - PRIx64 " to tdata2 but read back 0x%" PRIx64, - idx, tdata2, tdata2_rb); + bool tdata1_config_denied = (tdata1 & ~tdata1_ignore_mask) != (tdata1_rb & ~tdata1_ignore_mask); + bool tdata2_config_denied = tdata2 != tdata2_rb; + if (tdata1_config_denied || tdata2_config_denied) { + LOG_TARGET_DEBUG(target, "Trigger %u doesn't support what we need.", idx); + + if (tdata1_config_denied) + LOG_TARGET_DEBUG(target, + "After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64 "; tdata1_ignore_mask=0x%" PRIx64, + tdata1, tdata1_rb, tdata1_ignore_mask); + + if (tdata2_config_denied) + LOG_TARGET_DEBUG(target, + "wrote 0x%" PRIx64 " to tdata2 but read back 0x%" PRIx64, + tdata2, tdata2_rb); + riscv_set_register(target, GDB_REGNO_TDATA1, 0); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } + return ERROR_OK; } |