-
-
Save joba-1/02454d9d028b37b70be4e4bb4b1d0ce2 to your computer and use it in GitHub Desktop.
OpenOCD script for GD32VF103 with improved reset procedure without power cycle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 { } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
new openocd target config
add to platformio project file environment section