# OpenOCD script for GD32VF103 with improved reset procedure # Invoke it like this. # for Digilent HS2 # 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" # for SiPEED USB-JTAG/TTL ( RV-Debugger ) # openocd -f interface/ftdi/minimodule.cfg -c "ftdi_device_desc {Dual RS232}" -f gd32vf103.cfg -c "init; reset run; exit" # for SiPEED RV-Debugger Lite # openocd -f interface/ftdi/minimodule.cfg -c "ftdi_device_desc {Sipeed-Debug}" -f gd32vf103.cfg -c "init; reset run; exit" # for SiPEED RV-Debugger Plus ( BL702 ) # openocd -f interface/ftdi/minimodule.cfg -c "ftdi_device_desc {JTAG Debugger}" -f gd32vf103.cfg -c "init; reset run; exit" #if [string equal [adapter name] ftdi] { # # Digilent HS2 can go upto 60MHz clock rate with this command enabled: "ftdi_tdo_sample_edge falling" # # ftdi_tdo_sample_edge falling # adapter speed 20000 #} else { # adapter speed 4000 #} #transport select jtag set _CHIPNAME riscv # True value of GD32VF103 core's IDCODE is 0x1000563d. But it could be masqueraded in some cases. jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1000563d -expected-id 0x1e200a6d jtag newtap gd32v tap -irlen 5 -expected-id 0x790007a3 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME riscv -chain-position $_TARGETNAME # Work-area is a space in RAM used for flash programming if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x5000 } $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 # Expose Nuclei self-defined CSRS range # # See https://github.com/riscv/riscv-gnu-toolchain/issues/319#issuecomment-358397306 # # Then user can view the csr register value in gdb using: info reg csr775 for CSR MTVT(0x307) riscv expose_csrs 770-800,835-850,1984-2032,2064-2070 $_TARGETNAME riscv set_reset_timeout_sec 1 set _FLASHNAME $_CHIPNAME.flash if {[catch {flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME}] != 0} { echo "** Maybe flash driver for gd32vf103 is not implemented in this version of OpenOCD **" echo "** You may still be able to debug target application already in the flash memory. **" } # 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 { }