This is an automated email from Gerrit. "Evgeniy Naydanov <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9314
-- gerrit commit 199359b57854d5d83cc24a1fb153a2c1a16afc45 Author: Evgeniy Naydanov <[email protected]> Date: Fri Dec 12 14:17:53 2025 +0300 target/riscv: tcl/target: move the WA for GD32VF103 to Tcl The GD32VF103 has a perculiar reset procedure that does not fully comply with the RISC-V Debug Specification. Move the workaroung to the `deassert-reset-post` handler. Change-Id: I153c866a5b7e2dff2552cc92772ce6ed77ad606b Signed-off-by: Evgeniy Naydanov <[email protected]> diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 6fa5e025be..ff3a2446f1 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -3001,15 +3001,7 @@ static int deassert_reset(struct target *target) get_field(dmstatus, DM_DMSTATUS_ALLHAVERESET) ? "true" : "false"); return ERROR_TIMEOUT_REACHED; } - /* Certain debug modules, like the one in GD32VF103 - * MCUs, violate the specification's requirement that - * each hart is in "exactly one of four states" and, - * during reset, report harts as both unavailable and - * halted/running. To work around this, we check for - * the absence of the unavailable state rather than - * the presence of any other state. */ - } while (get_field(dmstatus, DM_DMSTATUS_ALLUNAVAIL) && - !get_field(dmstatus, DM_DMSTATUS_ALLHAVERESET)); + } while (!get_field(dmstatus, DM_DMSTATUS_ALLHAVERESET)); riscv_scan_set_delay(&info->learned_delays, RISCV_DELAY_BASE, orig_base_delay); diff --git a/tcl/target/gd32vf103.cfg b/tcl/target/gd32vf103.cfg index 54a74e8cc5..4a0be55672 100644 --- a/tcl/target/gd32vf103.cfg +++ b/tcl/target/gd32vf103.cfg @@ -107,6 +107,22 @@ $_TARGETNAME configure -event reset-assert { default_mem_access } +# On GD32VF103 the specification's requirement that each hart is in "exactly +# one of four states" is violated and, during reset, report harts as both +# unavailable and halted/running. To work around this, after the havereset is +# lowered in the main deassert_reset procedure, we wait for the absence of the +# unavailable state. +$_TARGETNAME configure -event reset-deassert-post { + set timeout_s 2 + set start [clock seconds] + # dmstatus address is 0x11, allunavail is the 12th bit + while {[riscv dmi_read 0x11] & 1 << 12} { + if {[clock seconds] - $start > $timeout_s} { + error {Timed out waiting for the hart to become available after a reset} + } + } +} + # Capture the mode of a given reset so that we can use it later in the # reset-assert handler. proc init_reset { mode } { --
