OpenOCD for RISC-V chip cannot handle 'reset run' command

I believe the OpenOCD for RISC-V cannot properly handle the 'reset run' command. I’ll go into more details after picturing the context.

1. Setup

I open two Windows consoles: one for OpenOCD and another for GDB. In the first console, I launch OpenOCD with the right arguments such that it connects to the GD32VF103C-START board:

> openocd -f ../config/openocd_probe.cfg -f ../config/openocd_chip.cfg -c "init; reset halt"

xPack OpenOCD, x86_64 Open On-Chip Debugger 0.10.0+dev-dirty (2020-10-26-06:00)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
jtag
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (JTAG)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : cmsis-dap JTAG TLR_RESET
Info : cmsis-dap JTAG TLR_RESET
Info : JTAG tap: riscv.cpu tap/device found: 0x1000563d (mfg: 0x31e (Andes Technology Corporation), part: 0x0005, ver: 0x1)
Info : JTAG tap: auto0.tap tap/device found: 0x790007a3 (mfg: 0x3d1 (GigaDevice Semiconductor (Beijing)), part: 0x9000, ver: 0x7)
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 5 -expected-id 0x790007a3"
Info : datacount=4 progbufsize=2
Info : Examined RISC-V core; found 1 harts
Info :  hart 0: XLEN=32, misa=0x40901105
Info : starting gdb server for riscv.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : cmsis-dap JTAG TLR_RESET
Info : cmsis-dap JTAG TLR_RESET
Info : cmsis-dap JTAG TLR_RESET
Info : JTAG tap: riscv.cpu tap/device found: 0x1000563d (mfg: 0x31e (Andes Technology Corporation), part: 0x0005, ver: 0x1)
Info : JTAG tap: auto0.tap tap/device found: 0x790007a3 (mfg: 0x3d1 (GigaDevice Semiconductor (Beijing)), part: 0x9000, ver: 0x7)
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

Then I launch GDB in the second console and hook it into OpenOCD:

> riscv64-unknown-elf-gdb

GNU gdb (SiFive GDB 8.3.0-2020.04.0) 8.3
Copyright (C) 2019 Free Software Foundation, Inc.
[..]

(gdb) file application.elf
Reading symbols from application.elf...

(gdb) target extended-remote localhost:3333
Remote debugging using localhost:3333
0x080013d0 in __floatunsidf (i=108000000) at ../../../../../riscv-gcc/libgcc/soft-fp/floatunsidf.c:41
41      ../../../../../riscv-gcc/libgcc/soft-fp/floatunsidf.c: No such file or directory.

(gdb) monitor init

2. The problem

Once GDB is hooked into OpenOCD, I send the reset run command to OpenOCD (the keyword monitor ensures that the command goes straight to OpenOCD):

(gdb) monitor reset run
cmsis-dap JTAG TLR_RESET
cmsis-dap JTAG TLR_RESET
cmsis-dap JTAG TLR_RESET
JTAG tap: riscv.cpu tap/device found: 0x1000563d (mfg: 0x31e (Andes Technology Corporation), part: 0x0005, ver: 0x1)
JTAG tap: auto0.tap tap/device found: 0x790007a3 (mfg: 0x3d1 (GigaDevice Semiconductor (Beijing)), part: 0x9000, ver: 0x7)
Hart 0 didn't run coming out of reset in 2s; dmstatus=0x4f03a2; Increase the timeout with riscv set_reset_timeout_sec.
keep_alive() was not invoked in the 1000 ms timelimit. GDB alive packet not sent! (2133 ms). Workaround: increase "set remotetimeout" in GDB

Hart 0 unexpectedly reset!

The chip reset actually fails. I can see that my board is not starting the firmware (the LED is not blinking). The proposed workaround to increase the 'set remotetimeout' in GDB doesn’t help. The only way to get it working is to repeat the same command:

(gdb) monitor reset run
cmsis-dap JTAG TLR_RESET
cmsis-dap JTAG TLR_RESET
cmsis-dap JTAG TLR_RESET
JTAG tap: riscv.cpu tap/device found: 0x1000563d (mfg: 0x31e (Andes Technology Corporation), part: 0x0005, ver: 0x1)
JTAG tap: auto0.tap tap/device found: 0x790007a3 (mfg: 0x3d1 (GigaDevice Semiconductor (Beijing)), part: 0x9000, ver: 0x7)

Now the chip resets properly. I can see the firmware starting and the LED blinks.

Note:
In my initial experiments, I thought that the proposed workaround to increase the 'set remotetimeout' in GDB actually worked. But it only looks that way, because it’s natural to repeat the 'monitor reset run' command after increasing the remote timeout.
The only reason it works is because I issued the 'monitor reset run' a second time. It doesn’t matter if you increase the remote timeout.

3. Why it's important

In Embeetle, we use the gdb load command to flash the firmware:

(gdb) load
Loading section .init, size 0x236 lma 0x8000000
Loading section .text, size 0x161c lma 0x8000240
Loading section .sdata2._global_impure_ptr, size 0x4 lma 0x800185c
Loading section .data, size 0x68 lma 0x8001860
Start address 0x800015c, load size 6334
Transfer rate: 717 bytes/sec, 1583 bytes/write.

After that, we reset the chip and run the firmware:

(gdb) monitor reset run
[...]

This way, the user can immediately see the result of the flash.