aboutsummaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
authorMarek Vrbka <marek.vrbka@codasip.com>2023-07-04 11:56:42 +0200
committerMarek Vrbka <marek.vrbka@codasip.com>2023-07-04 12:04:02 +0200
commitea115917b934249c1e8dc9dc8eccb2f503953e5d (patch)
treed79220f3425aaf3fd6670a22253ec1a53122496f /src/target
parent92c03192612bd7c41f4562b5f130ac8e1907d591 (diff)
downloadriscv-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.c45
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;
}