From: openocd-gerrit <ope...@us...> - 2023-11-30 14:32:35
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 7ac389cf47463cc35667659804d939015a4815e5 (commit) from 1b0b07baab2b23318ddc484a58d66214f0c2a0d2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7ac389cf47463cc35667659804d939015a4815e5 Author: Thomas Hebb <tom...@gm...> Date: Fri Apr 29 22:17:18 2022 -0700 tcl/target/gd32vf103: work around broken ndmreset On this chip, the ndmreset bit in the RISC-V debug module doesn't trigger a system reset like it should. To work around this, add a custom "reset-assert" handler in its config file that resets the system by writing to memory-mapped registers. I've tested this workaround on a Sipeed Longan Nano dev board with a GD32VF103CBT6 chip. It works correctly for both "reset run" and "reset halt" (halting at pc=0 for the latter). I originally submitted[1] this workaround to the riscv-openocd fork of OpenOCD. That fork's maintainers accepted it, but have not upstreamed it like they have several other of my changes. [1] https://github.com/riscv/riscv-openocd/pull/538 Change-Id: I7482990755b300fcbe4963c9a599d599bc02684d Signed-off-by: Thomas Hebb <tom...@gm...> Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: https://review.openocd.org/c/openocd/+/6957 Tested-by: jenkins Reviewed-by: zapb <de...@za...> diff --git a/tcl/target/gd32vf103.cfg b/tcl/target/gd32vf103.cfg index 068124334..54a74e8cc 100644 --- a/tcl/target/gd32vf103.cfg +++ b/tcl/target/gd32vf103.cfg @@ -28,6 +28,12 @@ jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1000563d set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME riscv -chain-position $_TARGETNAME +proc default_mem_access {} { + riscv set_mem_access progbuf +} + +default_mem_access + $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash @@ -40,3 +46,74 @@ $_TARGETNAME configure -event reset-init { # DBGMCU_CR |= DBG_WWDG_STOP | DBG_IWDG_STOP mmw 0xE0042004 0x00000300 0 } + +# On this chip, ndmreset (the debug module bit that triggers a software reset) +# doesn't work. So for JTAG connections without an SRST, we need to trigger a +# reset manually. This is an undocumented reset sequence that's used by the +# JTAG flashing script in the vendor-supplied GD32VF103 PlatformIO plugin: +# +# https://github.com/sipeed/platform-gd32v/commit/f9cbb44819bc05dd2010cc815c32be0486800cc2 +# +$_TARGETNAME configure -event reset-assert { + set dmcontrol 0x10 + set dmcontrol_dmactive [expr {1 << 0}] + set dmcontrol_ackhavereset [expr {1 << 28}] + set dmcontrol_haltreq [expr {1 << 31}] + + global _RESETMODE + + # If hardware NRST signal is connected and configured (reset_config srst_only) + # the device has been recently reset in 'jtag arp_init-reset', therefore + # DM_DMSTATUS_ANYHAVERESET reads 1. + # The following 'halt' command checks this status bit + # and shows 'Hart 0 unexpectedly reset!' if set. + # Prevent this message by sending an acknowledge first. + set val [expr {$dmcontrol_dmactive | $dmcontrol_ackhavereset}] + riscv dmi_write $dmcontrol $val + + # Halt the core so that we can write to memory. We do this first so + # that it doesn't clobber our dmcontrol configuration. + halt + + # Set haltreq appropriately for the type of reset we're doing. This + # replicates what the generic RISC-V reset_assert() function would + # do if we weren't overriding it. The $_RESETMODE hack sucks, but + # it's the least invasive way to determine whether we need to halt. + # + # If we didn't override the generic handler, we'd actually still have + # to do this: the default handler sets ndmreset, which prevents memory + # access even though it doesn't actually trigger a reset on this chip. + # So we'd need to unset it here, which involves a write to dmcontrol, + # Since haltreq is write-only and there's no way to leave it unchanged, + # we'd have to figure out its proper value anyway. + set val $dmcontrol_dmactive + if {$_RESETMODE ne "run"} { + set val [expr {$val | $dmcontrol_haltreq}] + } + riscv dmi_write $dmcontrol $val + + # Unlock 0xe0042008 so that the next write triggers a reset + mww 0xe004200c 0x4b5a6978 + + # We need to trigger the reset using abstract memory access, since + # progbuf access tries to read a status code out of a core register + # after the write happens, which fails when the core is in reset. + riscv set_mem_access abstract + + # Go! + mww 0xe0042008 0x1 + + # Put the memory access mode back to what it was. + default_mem_access +} + +# Capture the mode of a given reset so that we can use it later in the +# reset-assert handler. +proc init_reset { mode } { + global _RESETMODE + set _RESETMODE $mode + + if {[using_jtag]} { + jtag arp_init-reset + } +} ----------------------------------------------------------------------- Summary of changes: tcl/target/gd32vf103.cfg | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) hooks/post-receive -- Main OpenOCD repository |