Skip to content

Instantly share code, notes, and snippets.

@joba-1
Forked from elfmimi/gd32vf103.cfg
Last active October 11, 2020 09:28
Show Gist options
  • Save joba-1/02454d9d028b37b70be4e4bb4b1d0ce2 to your computer and use it in GitHub Desktop.
Save joba-1/02454d9d028b37b70be4e4bb4b1d0ce2 to your computer and use it in GitHub Desktop.
OpenOCD script for GD32VF103 with improved reset procedure without power cycle
# Invoke it like this.
# openocd -f interface/ftdi/digilent-hs2.cfg -c "ftdi_device_desc {Digilent USB Device}" -f gd32vf103.cfg -c "program binary.elf verify reset exit"
# openocd -f interface/ftdi/digilent-hs2.cfg -c "ftdi_device_desc {Digilent USB Device}" -f gd32vf103.cfg -c "program binary.bin 0x08000000 verify reset exit"
# openocd -f interface/ftdi/digilent-hs2.cfg -c "ftdi_device_desc {Digilent USB Device}" -f gd32vf103.cfg -c "init; reset run; exit"
# Sure, you may also use other JTAG interfaces.
#
# For platformio copy this file to the openocd target directory
# cd ~/.platformio/packages/tool-openocd-gd32v/share/openocd/scripts/target
# wget -O gd32vf103-elfmimi.cfg https://gist.github.com/joba-1/02454d9d028b37b70be4e4bb4b1d0ce2/raw/gd32vf103.cfg
# Then use these entries in your platformio.ini project file for use with a sipeed usb-jtag adapter:
# upload_protocol = custom
# upload_flags =
# -s
# /share/openocd/scripts
# -f
# interface/ftdi/sipeed-rv-debugger.cfg
# -f
# target/gd32vf103-elfmimi.cfg
# -c
# "adapter_khz
# 1000"
# -c
# "init;
# halt;"
# -c
# "program $PROG_PATH
# verify
# reset
# exit"
# upload_command = openocd $UPLOAD_FLAGS
if [string equal [adapter_name] ftdi] {
ftdi_tdo_sample_edge falling
adapter_khz 60000
} else {
adapter_khz 4000
}
# transport select jtag
set _CHIPNAME riscv
# True value of GD32VF103 core's IDCODE is 0x1000563d. Sometimes it's being masqueraded with 0x1e200a6d.
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1000563d
jtag newtap gd32v tap -irlen 5 -expected-id 0x790007a3
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1
$_TARGETNAME riscv set_reset_timeout_sec 1
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME gd32vf103 0x08000000 0 0 0 $_TARGETNAME
# riscv expose_csrs 3040-3071
proc SystemReset {} {
global _TARGETNAME
if {[catch {init}] != 0} {
echo "** OpenOCD init failed **"
shutdown error
}
if ![string equal halted [$_TARGETNAME curstate]] {
halt
}
# See gd32vf103_eclic.c for eclic_system_reset() .
# void eclic_system_reset(void) {
# REG32(REG_DBGMCU2EN) = 0x4b5a6978;
# REG32(REG_DBGMCU2) = 0x1;
# }
mww 0xe004200c 0x4b5a6978
mww 0xe0042008 0x01
# resume
# set dmcontrol [dmi_read 0x10]
# dmi_write 0x10 [expr ${dmcontrol} | 0x40000000]
# sleep 100
# set dmstatus [dmi_read 0x11]
# echo [format "dmstatus %08X" ${dmstatus}]
shutdown
}
proc dmi_read {reg} {
global _TARGETNAME
# You don't need this treatment if you are using latest openocd
set value [capture {$_TARGETNAME riscv dmi_read ${reg}}]
string trimright ${value} \n
}
proc dmi_write {reg value} {
global _TARGETNAME
$_TARGETNAME riscv dmi_write ${reg} ${value}
}
proc dmi_write_register {regno data0} {
dmi_write 0x04 ${data0}
set command [expr 0x00230000 | ${regno}]
dmi_write 0x17 ${command}
set abstractcs [dmi_read 0x16]
# echo [format "abstractcs %08X" ${abstractcs}]
if {(${abstractcs} & 0x0700) == 0} {
# echo [format "register write OK: %04X %08X" ${regno} ${data0}]
} else {
echo [format "register write NG: %04X %08X" ${regno} ${data0}]
shutdown
}
}
proc dmi_read_register {regno} {
set command [expr 0x00220000 | ${regno}]
dmi_write 0x17 ${command}
set abstractcs [dmi_read 0x16]
# echo [format "abstractcs %08X" ${abstractcs}]
if {(${abstractcs} & 0x0700) == 0} {
set data0 [dmi_read 0x04]
# echo [format "register read OK: %04X %08X" ${regno} ${data0}]
} else {
echo [format "register read NG: %04X" ${regno}]
#shutdown
exit
}
return ${data0}
}
proc clear_interrupt_level_by_dmi {} {
# progbuf0 = auipc a0, 0x0 (0x00000517)
dmi_write 0x20 0x00000517
# progbuf1 = ebreak (0x00100073)
dmi_write 0x21 0x00100073
# command = postexec
dmi_write 0x17 0x00040000
set abstractcs [dmi_read 0x16]
if {(${abstractcs} & 0x0700) == 0} {
# echo [format "Debug : exec auipc OK"]
} else {
echo [format "Debug : exec auipc NG"]
echo [format "Debug : abstractcs %08X" ${abstractcs}]
exit
}
# a0 has been loaded with address of progbuf0
set a0 [dmi_read_register 0x100A]
# mepc = &progbuf1
dmi_write_register 0x0341 [expr ${a0} + 4]
# progbuf0 = mret (0x30200073)
dmi_write 0x20 0x30200073
# command = postexec
dmi_write 0x17 0x00040000
set abstractcs [dmi_read 0x16]
if {(${abstractcs} & 0x0700) == 0} {
# echo [format "Debug : exec mret OK"]
} else {
echo [format "Debug : exec mret NG"]
echo [format "Debug : abstractcs %08X" ${abstractcs}]
exit
}
}
proc reset_by_dmi {args} {
global _TARGETNAME
set curstate [$_TARGETNAME curstate]
# echo [format "curstate = %s" ${curstate}]
if ![string equal ${curstate} halted] {
halt
}
# Reset all peripherals
# RCU_APB1RST
mww 0x40021010 0xFFFFFFFF
mww 0x40021010 0x00000000
# RCU_APB2RST
mww 0x4002100C 0xFFFFFFFF
mww 0x4002100C 0x00000000
# RCU_AHBRST (USBFSRST)
mww 0x40021028 0xFFFFFFFF
mww 0x40021028 0x00000000
# RCU_CFG0
# echo [format "RCU_CFG0 %08X" [mrw 0x40021004]]
mwb 0x40021004 0x00
# echo [format "RCU_CFG0 %08X" [mrw 0x40021004]]
# What should we do with EXTI and ECLIC ?
set dmstatus [dmi_read 0x11]
set impebreak [expr (${dmstatus} & 0x00400000) >> 22]
# echo [format "dmstatus(DMI(0x11)) = %08X" ${dmstatus}]
set abstractcs [dmi_read 0x16]
set datacount [expr (${abstractcs} & 0x0000000F)]
set progbufsize [expr (${abstractcs} & 0x1F000000) >> 24]
# echo [format "Info : datacount=%d progbufsize=%d impebreak=%d" ${datacount} ${progbufsize} ${impebreak}]
if {(${progbufsize} < 2) && !${impebreak}} {
exit
}
# echo [format "abstractcs(DMI(0x16)) = %08X" ${abstractcs}]
# echo [format "mstatus(0x300) = %08X" [dmi_read_register 0x0300]]
# echo [format "mie(0x304) = %08X" [dmi_read_register 0x0304]]
# echo [format "mepc(0x341) = %08X" [dmi_read_register 0x0341]]
# echo [format "mcause(0x342) = %08X" [dmi_read_register 0x342]]
set mintstatus [dmi_read_register 0x0346]
# echo [format "Debug : mintstatus(0x346)=%08X" ${mintstatus}]
# echo [format "msubm(0x7c4) = %08X" [dmi_read_register 0x07c4]]
# echo [format "dcsr = %08X" [dmi_read_register 0x07B0]]
# echo [format "dpc = %08X" [dmi_read_register 0x07B1]]
# mstatus
dmi_write_register 0x0300 0x00001800
# msubm
dmi_write_register 0x07C4 0x00000000
#if {(${mintstatus} & 0xFF000000) != 0} {
# echo [format "a0(0x100A) = %08X" [dmi_read_register 0x100A]]
clear_interrupt_level_by_dmi
# echo [format "a0(0x100A) = %08X" [dmi_read_register 0x100A]]
# echo [format "Debug : mintstatus(0x346)=%08X" [dmi_read_register 0x0346]]
#}
#echo [format "mepc(0x341) = %08X" [dmi_read_register 0x0341]]
# dcsr
dmi_write_register 0x07B0 0x00000003
# dpc
dmi_write_register 0x07B1 0x08000000
# mcountinhibit
dmi_write_register 0x0320 0x00000000
foreach arg $args {
if [string equal [string tolower $arg] run] {
set run 1
}
if [string equal [string tolower $arg] halt] {
set halt 1
}
if [string equal [string tolower $arg] init] {
set halt 1
}
}
if [info exists run] {
resume
} elseif [info exists halt] {
} elseif [string equal ${curstate} running] {
resume
}
}
rename init original_init
proc init {} {
rename init {}
rename original_init init
init
# rename reset original_reset
rename reset {}
proc reset {args} {
reset_by_dmi $args
}
}
# this will suppress value of the last expression getting printed
if 0 { }
@joba-1
Copy link
Author

joba-1 commented Oct 10, 2020

new openocd target config

cd ~/.platformio/packages/tool-openocd-gd32v/share/openocd/scripts/target
wget -O gd32vf103-elfmimi.cfg https://gist.github.com/joba-1/02454d9d028b37b70be4e4bb4b1d0ce2/raw/gd32vf103.cfg

add to platformio project file environment section

upload_protocol = custom
upload_flags = 
  -s
  /share/openocd/scripts
  -f
  interface/ftdi/sipeed-rv-debugger.cfg
  -f
  target/gd32vf103-elfmimi.cfg
  -c
  "adapter_khz
  1000"
  -c
  "init;
  halt;"
  -c
  "program
  $PROG_PATH
  verify
  reset
  exit"
upload_command = openocd $UPLOAD_FLAGS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment