2022-06-12 16:42:27 -05:00
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
2020-07-08 08:36:29 -05:00
|
|
|
#
|
|
|
|
# GigaDevice GD32VF103 target
|
|
|
|
#
|
|
|
|
# https://www.gigadevice.com/products/microcontrollers/gd32/risc-v/
|
|
|
|
#
|
|
|
|
|
Update gd32vf103.cfg (#640)
After compiling OpenOCD from source (commit: 6edf98db7), OpenOCD could not connect with the target board which is a GD32VF103T_START development board,
when I used the command: openocd -f "interface/cmsis-dap.cfg" -f "target/gd32vf103.cfg"
Issue 1: The clock speed hasn't been set, the error message given is:
Error: CMSIS-DAP command CMD_DAP_SWJ_CLOCK failed.
Which can be solved by adding a clock speed setting to the gd32vf103.cfg file:
adapter speed 1000
Issue 2: The default transport is not set to jtag, which it requires, the error shown is:
Open On-Chip Debugger 0.11.0+dev-01861-g6edf98db7-dirty (2021-08-25-10:18)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
embedded:startup.tcl:128: Error: session transport is "swd" but your config requires JTAG
in procedure 'script'
at file "embedded:startup.tcl", line 26
in procedure 'jtag' called at file "/home/user/riscv-openocd-tool/usr/local/bin/../share/openocd/scripts/target/gd32vf103.cfg", line 9
in procedure 'default_to_jtag' called at file "embedded:startup.tcl", line 133
at file "embedded:startup.tcl", line 128
This issue can be solved by adding the line:
transport select jtag
After adding these two lines, OpenOCD could connect to the development board successfully. Programming the flash also works.
2021-08-26 12:09:04 -05:00
|
|
|
adapter speed 1000
|
2021-11-17 10:33:29 -06:00
|
|
|
source [find mem_helper.tcl]
|
|
|
|
|
Update gd32vf103.cfg (#640)
After compiling OpenOCD from source (commit: 6edf98db7), OpenOCD could not connect with the target board which is a GD32VF103T_START development board,
when I used the command: openocd -f "interface/cmsis-dap.cfg" -f "target/gd32vf103.cfg"
Issue 1: The clock speed hasn't been set, the error message given is:
Error: CMSIS-DAP command CMD_DAP_SWJ_CLOCK failed.
Which can be solved by adding a clock speed setting to the gd32vf103.cfg file:
adapter speed 1000
Issue 2: The default transport is not set to jtag, which it requires, the error shown is:
Open On-Chip Debugger 0.11.0+dev-01861-g6edf98db7-dirty (2021-08-25-10:18)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
embedded:startup.tcl:128: Error: session transport is "swd" but your config requires JTAG
in procedure 'script'
at file "embedded:startup.tcl", line 26
in procedure 'jtag' called at file "/home/user/riscv-openocd-tool/usr/local/bin/../share/openocd/scripts/target/gd32vf103.cfg", line 9
in procedure 'default_to_jtag' called at file "embedded:startup.tcl", line 133
at file "embedded:startup.tcl", line 128
This issue can be solved by adding the line:
transport select jtag
After adding these two lines, OpenOCD could connect to the development board successfully. Programming the flash also works.
2021-08-26 12:09:04 -05:00
|
|
|
transport select jtag
|
|
|
|
|
Improve support for GD32VF103 MCU (#538)
* riscv: work around buggy hart states during reset in some DMs
As described in the comment this change adds, the GD32VF103 DM reports
that the hart is in more than one state while it is resetting. Because
of this, the current code acknowledges resets before they actually
complete. This sometimes prevents havereset from getting cleared as
intended, leading to a spurious "Hart 0 unexpectedly reset!" message the
next time riscv_is_halted() gets called.
To work around this, check for the absence of the unavailable state
rather than the presence of the running or halted states. This behavior
is also arguably more true to the spec than what exists now: Section 3.2
states that "The system may take an arbitrarily long time to come out of
reset, as reported by allunavail, anyunavail."
Change-Id: I34e90a16233125608bce8e4c2414dbead637600e
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* riscv: support custom reset-assert scripts
The reset-assert event is used, if present, to override the default
reset logic for ARM and MIPS cores. Do the same for RISC-V so that
devices with buggy ndmreset functionality (like GD32VF103) or
nonstandard reset sequences can specify the appropriate logic in Tcl.
Change-Id: I5e12077d67509853edb8ef3ad3f037f293a5fbb6
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* tcl/target: support GD32VF103 RISC-V MCU
The GD32VF103 is a low-cost 32-bit RISC-V microcontroller with
peripherals that are more-or-less compatible with the STM32F103 ARM
microcontroller. It is available on several low-cost dev boards, such as
the Sipeed Longan Nano, which is what I am testing on.
Add initial support for this chip, including a workaround for a buggy
ndmreset line (i.e. one that doesn't actually trigger a reset) in its
integrated debug module. Use the existing GD32VF103 flash driver that
was ported from the vendor's code in commit 48e40f351325 ("Add support
for GD32VF103 flash").
Change-Id: Iadac47ceb5437b8e18f3d35901388f10fef9f876
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* tcl/target/gd32vf103: add main flash alias
The GD32VF103 creates an alias to either main flash or the bootloader at
0x0, depending on how it was booted. As such, we want to indicate to
debuggers that the memory at 0x0 is flash and so cannot support software
breakpoints. To do this, add an alias to the main flash in the config.
This isn't strictly accurate in the case where we're running the
bootloader, but it still suits our purpose of fixing breakpoint
behavior.
Change-Id: I9eb8462d354f096eee231c0e5e2bffa538a5903e
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
2020-10-01 13:06:11 -05:00
|
|
|
reset_config srst_nogate
|
|
|
|
|
2021-11-17 10:33:29 -06:00
|
|
|
# The smallest RAM size 6kB (GD32VF103C4/T4/R4)
|
2020-07-08 08:36:29 -05:00
|
|
|
if { [info exists WORKAREASIZE] } {
|
|
|
|
set _WORKAREASIZE $WORKAREASIZE
|
|
|
|
} else {
|
2021-11-17 10:33:29 -06:00
|
|
|
set _WORKAREASIZE 0x1800
|
2020-07-08 08:36:29 -05:00
|
|
|
}
|
|
|
|
|
Improve support for GD32VF103 MCU (#538)
* riscv: work around buggy hart states during reset in some DMs
As described in the comment this change adds, the GD32VF103 DM reports
that the hart is in more than one state while it is resetting. Because
of this, the current code acknowledges resets before they actually
complete. This sometimes prevents havereset from getting cleared as
intended, leading to a spurious "Hart 0 unexpectedly reset!" message the
next time riscv_is_halted() gets called.
To work around this, check for the absence of the unavailable state
rather than the presence of the running or halted states. This behavior
is also arguably more true to the spec than what exists now: Section 3.2
states that "The system may take an arbitrarily long time to come out of
reset, as reported by allunavail, anyunavail."
Change-Id: I34e90a16233125608bce8e4c2414dbead637600e
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* riscv: support custom reset-assert scripts
The reset-assert event is used, if present, to override the default
reset logic for ARM and MIPS cores. Do the same for RISC-V so that
devices with buggy ndmreset functionality (like GD32VF103) or
nonstandard reset sequences can specify the appropriate logic in Tcl.
Change-Id: I5e12077d67509853edb8ef3ad3f037f293a5fbb6
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* tcl/target: support GD32VF103 RISC-V MCU
The GD32VF103 is a low-cost 32-bit RISC-V microcontroller with
peripherals that are more-or-less compatible with the STM32F103 ARM
microcontroller. It is available on several low-cost dev boards, such as
the Sipeed Longan Nano, which is what I am testing on.
Add initial support for this chip, including a workaround for a buggy
ndmreset line (i.e. one that doesn't actually trigger a reset) in its
integrated debug module. Use the existing GD32VF103 flash driver that
was ported from the vendor's code in commit 48e40f351325 ("Add support
for GD32VF103 flash").
Change-Id: Iadac47ceb5437b8e18f3d35901388f10fef9f876
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* tcl/target/gd32vf103: add main flash alias
The GD32VF103 creates an alias to either main flash or the bootloader at
0x0, depending on how it was booted. As such, we want to indicate to
debuggers that the memory at 0x0 is flash and so cannot support software
breakpoints. To do this, add an alias to the main flash in the config.
This isn't strictly accurate in the case where we're running the
bootloader, but it still suits our purpose of fixing breakpoint
behavior.
Change-Id: I9eb8462d354f096eee231c0e5e2bffa538a5903e
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
2020-10-01 13:06:11 -05:00
|
|
|
set _CHIPNAME gd32vf103
|
|
|
|
# The vendor's configuration expects an ID of 0x1e200a6d, but this one is what
|
|
|
|
# I have on my board (Sipeed Longan Nano, GD32VF103CBT6).
|
|
|
|
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1000563d
|
|
|
|
jtag newtap $_CHIPNAME bs -irlen 5 -expected-id 0x790007a3
|
|
|
|
|
|
|
|
set _TARGETNAME $_CHIPNAME.cpu
|
|
|
|
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
|
|
|
|
$_TARGETNAME riscv set_enable_virt2phys off
|
|
|
|
|
|
|
|
proc default_mem_access {} {
|
|
|
|
riscv set_mem_access progbuf
|
|
|
|
}
|
|
|
|
|
|
|
|
default_mem_access
|
|
|
|
|
2020-07-08 08:36:29 -05:00
|
|
|
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
Improve support for GD32VF103 MCU (#538)
* riscv: work around buggy hart states during reset in some DMs
As described in the comment this change adds, the GD32VF103 DM reports
that the hart is in more than one state while it is resetting. Because
of this, the current code acknowledges resets before they actually
complete. This sometimes prevents havereset from getting cleared as
intended, leading to a spurious "Hart 0 unexpectedly reset!" message the
next time riscv_is_halted() gets called.
To work around this, check for the absence of the unavailable state
rather than the presence of the running or halted states. This behavior
is also arguably more true to the spec than what exists now: Section 3.2
states that "The system may take an arbitrarily long time to come out of
reset, as reported by allunavail, anyunavail."
Change-Id: I34e90a16233125608bce8e4c2414dbead637600e
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* riscv: support custom reset-assert scripts
The reset-assert event is used, if present, to override the default
reset logic for ARM and MIPS cores. Do the same for RISC-V so that
devices with buggy ndmreset functionality (like GD32VF103) or
nonstandard reset sequences can specify the appropriate logic in Tcl.
Change-Id: I5e12077d67509853edb8ef3ad3f037f293a5fbb6
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* tcl/target: support GD32VF103 RISC-V MCU
The GD32VF103 is a low-cost 32-bit RISC-V microcontroller with
peripherals that are more-or-less compatible with the STM32F103 ARM
microcontroller. It is available on several low-cost dev boards, such as
the Sipeed Longan Nano, which is what I am testing on.
Add initial support for this chip, including a workaround for a buggy
ndmreset line (i.e. one that doesn't actually trigger a reset) in its
integrated debug module. Use the existing GD32VF103 flash driver that
was ported from the vendor's code in commit 48e40f351325 ("Add support
for GD32VF103 flash").
Change-Id: Iadac47ceb5437b8e18f3d35901388f10fef9f876
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* tcl/target/gd32vf103: add main flash alias
The GD32VF103 creates an alias to either main flash or the bootloader at
0x0, depending on how it was booted. As such, we want to indicate to
debuggers that the memory at 0x0 is flash and so cannot support software
breakpoints. To do this, add an alias to the main flash in the config.
This isn't strictly accurate in the case where we're running the
bootloader, but it still suits our purpose of fixing breakpoint
behavior.
Change-Id: I9eb8462d354f096eee231c0e5e2bffa538a5903e
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
2020-10-01 13:06:11 -05:00
|
|
|
|
|
|
|
set _FLASHNAME $_CHIPNAME.flash
|
2021-11-17 10:33:29 -06:00
|
|
|
flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME
|
Improve support for GD32VF103 MCU (#538)
* riscv: work around buggy hart states during reset in some DMs
As described in the comment this change adds, the GD32VF103 DM reports
that the hart is in more than one state while it is resetting. Because
of this, the current code acknowledges resets before they actually
complete. This sometimes prevents havereset from getting cleared as
intended, leading to a spurious "Hart 0 unexpectedly reset!" message the
next time riscv_is_halted() gets called.
To work around this, check for the absence of the unavailable state
rather than the presence of the running or halted states. This behavior
is also arguably more true to the spec than what exists now: Section 3.2
states that "The system may take an arbitrarily long time to come out of
reset, as reported by allunavail, anyunavail."
Change-Id: I34e90a16233125608bce8e4c2414dbead637600e
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* riscv: support custom reset-assert scripts
The reset-assert event is used, if present, to override the default
reset logic for ARM and MIPS cores. Do the same for RISC-V so that
devices with buggy ndmreset functionality (like GD32VF103) or
nonstandard reset sequences can specify the appropriate logic in Tcl.
Change-Id: I5e12077d67509853edb8ef3ad3f037f293a5fbb6
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* tcl/target: support GD32VF103 RISC-V MCU
The GD32VF103 is a low-cost 32-bit RISC-V microcontroller with
peripherals that are more-or-less compatible with the STM32F103 ARM
microcontroller. It is available on several low-cost dev boards, such as
the Sipeed Longan Nano, which is what I am testing on.
Add initial support for this chip, including a workaround for a buggy
ndmreset line (i.e. one that doesn't actually trigger a reset) in its
integrated debug module. Use the existing GD32VF103 flash driver that
was ported from the vendor's code in commit 48e40f351325 ("Add support
for GD32VF103 flash").
Change-Id: Iadac47ceb5437b8e18f3d35901388f10fef9f876
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
* tcl/target/gd32vf103: add main flash alias
The GD32VF103 creates an alias to either main flash or the bootloader at
0x0, depending on how it was booted. As such, we want to indicate to
debuggers that the memory at 0x0 is flash and so cannot support software
breakpoints. To do this, add an alias to the main flash in the config.
This isn't strictly accurate in the case where we're running the
bootloader, but it still suits our purpose of fixing breakpoint
behavior.
Change-Id: I9eb8462d354f096eee231c0e5e2bffa538a5903e
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
2020-10-01 13:06:11 -05:00
|
|
|
|
|
|
|
# Address 0 is only aliased to main flash when the chip is not running its
|
|
|
|
# built-in bootloader. When it is, it's instead aliased to a read only section
|
|
|
|
# of flash at 0x1fffb000. However, we can't detect or dynamically switch this,
|
|
|
|
# so just pretend it's always aliased to main flash. We need to tell OpenOCD
|
|
|
|
# about this alias because otherwise we'll try to use software breakpoints on
|
|
|
|
# code in flash, which don't work because flash mappings are read-only.
|
|
|
|
flash bank $_CHIPNAME.flashalias virtual 0x0 0 0 0 $_TARGETNAME $_FLASHNAME
|
|
|
|
|
|
|
|
# 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_haltreq [expr 1 << 31]
|
|
|
|
|
|
|
|
global _RESETMODE
|
|
|
|
global _TARGETNAME
|
|
|
|
|
|
|
|
# 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,
|
|
|
|
# and psoc6.cfg already uses the same trick. (reset_deassert(), which
|
|
|
|
# does run, also does this, but at that point it may be too late: the
|
|
|
|
# reset has already been triggered, so there's a race between it and
|
|
|
|
# the haltreq write.)
|
|
|
|
#
|
|
|
|
# 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]
|
|
|
|
}
|
|
|
|
$_TARGETNAME riscv dmi_write $dmcontrol $val
|
|
|
|
|
|
|
|
# Unlock 0xe0042008 so that the next write triggers a reset
|
|
|
|
$_TARGETNAME 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!
|
|
|
|
$_TARGETNAME 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
|
|
|
|
}
|
|
|
|
}
|
2022-04-30 00:17:18 -05:00
|
|
|
|
|
|
|
# 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
|
|
|
|
}
|
|
|
|
}
|