Progress getting OpenOCD usable with RevB

I’ve been working on seeing if I can get OpenOCD to work with the Rev B (since OpenOCD should have J-link OB support since 0.10). I have made some progress, but have hit a roadblock that is stumping me.

First up, it seems OpenOCD can’t connect because the J-Link OB uses a new PID that libjaylink is not aware of–by patching libjaylink in openocd I can actually get the USB device to be opened

diff --git a/src/jtag/drivers/libjaylink/libjaylink/discovery_usb.c b/src/jtag/drivers/libjaylink/libjaylink/discovery_usb.c
index 48d532292..9d979013c 100644
--- a/src/jtag/drivers/libjaylink/libjaylink/discovery_usb.c
+++ b/src/jtag/drivers/libjaylink/libjaylink/discovery_usb.c
@@ -59,7 +59,8 @@ static const uint16_t pids[][2] = {
        {0x1015, 0},
        {0x1016, 0},
        {0x1017, 0},
-       {0x1018, 0}
+       {0x1018, 0},
+       {0x1051, 0},
 };

Then, from there I’ve been working on getting an openocd.cfg that can work with the RevB. So far, I have this:

interface jlink
transport select jtag

adapter_khz 4000

set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000913

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1

flash bank spi0 fespi 0x20000000 0 0 0 $_TARGETNAME.0 0x10014000

And with this, I can start openocd and connect to it from riscv-gdb after loading an example elf and connect with target extended-remote localhost:3333 and gdb will connect and print the current execution

0x200152ae in __metal_driver_sifive_uart0_getc (uart=0x2, c=0x80000fe4)
    at freedom-e-sdk/freedom-metal/src/drivers/sifive_uart0.c:71
71	      *c = ch & 0x0ff;

Whoo! This was fantastic! But, this is where I’m stuck. If I try to run the rest of the commands to turn off flash protect, halt the processor, then load the elf, things…do not work. There’s lots of errors that occur (small snippet)

(gdb) monitor reset halt
JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2)
Failed to send data to device: LIBUSB_ERROR_TIMEOUT.
Failed to send data to device: LIBUSB_ERROR_TIMEOUT.
Sending data to device timed out.
transport_write() failed: timeout occurred.
jaylink_jtag_io() failed: timeout occurred.
dmi_scan failed jtag scan
Failed read (NOP) at 0x11; value=0x0, status=2
Last read operation left 68 bytes.
Failed to send data to device: LIBUSB_ERROR_TIMEOUT.
Failed to send data to device: LIBUSB_ERROR_TIMEOUT.
Sending data to device timed out.
transport_write() failed: timeout occurred.
jaylink_jtag_io() failed: timeout occurred.
dmi_scan failed jtag scan
failed read at 0x11, status=2
(gdb) monitor flash protect 0 64 last off
Last read operation left 281 bytes.
Failed to send data to device: LIBUSB_ERROR_TIMEOUT.
Failed to send data to device: LIBUSB_ERROR_TIMEOUT.
Sending data to device timed out.
transport_write() failed: timeout occurred.
jaylink_jtag_io() failed: timeout occurred.
dmi_scan failed jtag scan
failed read at 0x11, status=2
Last read operation left 281 bytes.
Failed to send data to device: LIBUSB_ERROR_TIMEOUT.
Failed to send data to device: LIBUSB_ERROR_TIMEOUT.
Sending data to device timed out.
transport_write() failed: timeout occurred.
jaylink_jtag_io() failed: timeout occurred.
dmi_scan failed jtag scan
Failed read (NOP) at 0x11; value=0x0, status=2
ERROR: first sector must be <= last

The last line seemed to be from flash protect, and if I add the following to my openocd.cfg

init
halt
flash protect 0 64 last off

Then I don’t see any timeouts, but I do see the flash error

Open On-Chip Debugger 0.10.0+dev-00841-g1449af5bd (2020-03-03-20:03)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : J-Link OB-K22-SiFive compiled Feb 28 2019 12:46:23
Info : Hardware version: 1.00
Info : VTarget = 3.300 V
Info : clock speed 4000 kHz
Info : JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2)
Info : datacount=1 progbufsize=16
Info : Disabling abstract command reads from CSRs.
Info : Examined RISC-V core; found 1 harts
Info :  hart 0: XLEN=32, misa=0x40101105
Info : Listening on port 3333 for gdb connections
Info : Found flash device 'issi is25lp032' (ID 0x0016609d)
ERROR: first sector must be <= last

…and this still happens even if I specify a size in the flash bank portion (and if I specify size for flash protect instead of last, then I see ERROR: last sector must be <= 63)

This all seems to me that the flash bank is not being properly setup. It does seem it is getting detected by openocd through jlink/jtag, but not sure what’s going wrong (also, flash banks isn’t printing on my build… but can debug that on my own at least).

I have been able to flash the board using USB mass storage, so I at least know the cable is good ;D

Any ideas?

1 Like

Argh, still can’t figure out why when I build openocd it does not enable the command_print function. But, did make some progress regardless

I had thought the jlink driver autosets if it’s “v2” or “v3”, but apparently not, and it defaults to v2. If I update the config with jlink jtag 3 then it doesn’t timeout when halting the core. Whoo! …it still complains about flash protect, and further it seems to stall when loading the elf and hangs after a “warning” that it couldn’t allocate the work area

Warn : keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (1976). Workaround: increase "set remotetimeout" in GDB
keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (1976). Workaround: increase "set remotetimeout" in GDB
ERROR: first sector must be <= last
ERROR: first sector must be <= last
Info : JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2)
Warn : keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (2243). Workaround: increase "set remotetimeout" in GDB
Loading section .init, size 0x194 lma 0x20010000
Loading section .text, size 0x5144 lma 0x20010200
Loading section .rodata, size 0xb54 lma 0x20015344
Loading section .init_array, size 0xc lma 0x20015e98
Loading section .data, size 0xad0 lma 0x20015ea8
Info : Padding image section 0 at 0x20010194 with 108 bytes
Info : Padding image section 1 at 0x20015ea4 with 4 bytes
Warn : Couldn't allocate 796-byte working area.

…and it hangs there until I kill it. It must be doing something though as my board appears to hang itself on boot, and I need to reflash the hello example onto it via USB mass storage to get it to work again.

Fun find–it’s not that my command_prints don’t work, but they only get sent to the GDB connection, so I need to run those info commands via the GDB prompt :sweat_smile: This wasn’t the case when I didn’t build from source, so maybe something here has changed?

Executing flash info 0 showed that the flash bank already had protection turned off, hence that command not working.

Further, after parsing the debug logs I could see OpenOCD writing the program binary to flash, but it was doing it extremely slowly (around 24 kB over ~15 minutes). It was doing so apparently because I could start the flashing for different programs, and see that initial portion of data if I dump the flash spi via gdb and compared to the corresponding section in the elf.

…which made me suspect that it was the inability to allocate work area. I dug into this and found I had apparently cloned the riscv/riscv-openocd instead of sifive/riscv-openocd. The former has more changes and seems to be more active, but also now by default assumes the chip will be using virtual addressing and tries to detect the MMU (which fails here). By adding riscv set_enable_virt2phys off to my openocd.cfg, I can successfully connect via gdb and flash and debug my program!

Whoo!

…that being said I think I’ve broken something else along the way. If I had a serial terminal connected, I can see the results print from the different example programs after I load; monitor resume …but if I try to reset my board in any way (monitor reset, hitting reset button on board, or unplugging and replugging my board), then nothing happens, and if I connect gdb and bt, I see it’s stuck at #0 _enter () at /home/tincman/coding/freedom-e-sdk/freedom-metal/src/entry.S:24

…and not amount of monitor resume monitor halt; monitor step will change this.

Which, I must have broken something else because now I cannot even flash a hex file via USB mass storage (shows the same issue, and no FAIL.txt shows up in the usb drive either).

Is it possible I overwrote some bootcode? I thought that was in OTP and always jumped to 0x20000000?

…which maybe that is it? I see from the elf that nothing is written to 0x20000000?

(gdb) load
Loading section .init, size 0x194 lma 0x20010000
Loading section .text, size 0x5dc6 lma 0x20010200
Loading section .rodata, size 0x10d8 lma 0x20015fc8
Loading section .init_array, size 0xc lma 0x200170a0
Loading section .data, size 0xae8 lma 0x200170b0
Start address 0x20010000, load size 31526
Transfer rate: 5 KB/sec, 5254 bytes/write.

And I also just remembered the getting started guide mentioned on boot the board will turn off radios, and I remember previously seeing those AT commands print to serial.

…luckily I had a backup board I was able to pull those first 64kb off of and reflash it to the other board (thanks to OpenOCD working :D), and that seems to have fixed the problem! Now I can reset/reboot as I please.

I do wonder, is the source code for that boot procedure located anywhere? Mostly thinking of a recover procedure in case someone else ends up in a similar situation.

…just for fun as well as I am now able to restore the previous behavior. I also have a Sparkfun Red-V (like a revB, but has no ESP32) and I didn’t need the startup routine AFAIK, so I tried changing the linker scripts to use flash starting at 0x2000_0000 and that worked as well :smiley:

I’m fairly confident this is working now, but I’m going to give it some more testing before I get this cleaned up and see about getting it merged if there’s interest in it.

Very good insights here.
I also encountered similar behavior and was able to resolve it using riscv set_reset_timeout_sec 5, as well as doing sleep 5 after reset init
Seems that the FE310 takes a long time to come up out of reset.
Provided your code is small enough, do you notice any difference in performance if you load and run your code entirely from the ram at 0x80000000? Yes, the fespi loader is painfully slow, seems to be doing huge blocks of 64K at a time, and nothing smaller.

Ah ha, that makes sense: the original HiFive1 had a sleep routine after init, and that may explain why I can’t get openocd to connect for a period after powering on the board. I’ll be sure to add that in :]

Actually, making sure openocd can allocate and use a work area made a huge difference in speed. Apologies if that got lost in my posts.

From my impressions, the work area is a portion of ram openocd will use to store data and execute instructions to speed up operations. My guess is when the work area wasn’t enabled that the adapter was doing this a byte at a time over the jtag link vs the work area where it copies chunks and likely loops over it on the CPU itself.

The 64k makes sense as I think that’s the sector size flash info 0 reports.

Hmm, but execution from 0x80000000 could be interesting for other reasons. I’ll have to give that a try as well.

Note for others and future me (since I apparently forgot a detail and have been banging my head trying to reflash this image).

  1. flash protect 0 1 last off “works”–it looks like the numbers here are not some size, but sectors? (It doesn’t error, but also seems unnecessary since all my boards already have unprotected memory)
  2. In order to flash raw images, you must use flash write_image and you must use the erase flag: monitor flash write_image erase rom.bin 0x20000000 bin