Is it possible to bypass RevB's J-Link OB and use FTDI + OpenOCD instead?

Hi folks,

I am developing a RISC-V based toolchain, and I am interested in buying the RevB board.

My main reason for getting one is to test my FTDI + OpenOCD toolchain with a working RISC-V debug module. My own setup will eventually include a different RISCV chip with a v0.13 debug module, and a JTAG interface through FTDI. I want to get my hands on a working debug module implementation first.

It is my understanding that the older board had an FTDI interface and the new one has a JLink OB. The older one is more similar to what I actually want to implement, but the fact that it uses v0.11 for its debug module worries me about potential version differences.

The docs for the G002 chip mention the ability to bypass the JLink OB and use an external JTAG header., as shown in:

Has anyone tried this to bypass the JLink and use FTDI with the RevB?

Would you recommend me to do this at all or should I just try to get my hands on one of the older boards, despite the debug module version difference?

If I were to proceed, would I need to desolder anything, or is this bypass simple?

Thanks,
Yunus

You can also use a LoFive R1 board with external FTDI adapter.

Thanks, and If I were to use REvB, is it possible?

I think it should be possible without any modifications to the board, although I haven’t tried it. According to the schematics, you can use the J1 connector to access JTAG signals and RESET. The board even has resistors between J-Link and these JTAG lines, so you probably will not damage anything if you use both JTAG connector and J-Link at the same time, but I’d recommend you to not connect to the J-Link interface after applying power to the board.

1 Like

Hi!
I use a few i/o lines on the Raspberry Pi with the ā€œbit-bangā€ adapter of OpenOCD and it works quite well. No need any JLink, USB, etc.
Two issues though: First, don’t use wiring too long or messy, and supply good thick grounds; in the bit-bang code there’s a teeny improvement to be made, putting a bit of delay between actuation of the TDO, TDI, and TCK signals–helps a lot; you will see weird jtag errors and attachment failures, and occasionally OpenOCD (yes, it’s buggy here) will hang freeze and need to be process-killed when signal noise and race conditions happen; annoying, but no biggee. Second, the fespi transport seems to do only 64K chunks at a time, nothing smaller, so code load is long and thus painfully slow; however, using RAM (0x80000000) as your target rather than flash (0x20000000) is significantly faster and really helps the spiral development process.

1 Like

Can confirm that it’s possible to use an FTDI-based probe with HiFive1 RevB. I used Bus Blaster v3c with the following config:

adapter_khz     1000

interface ftdi
ftdi_device_desc "Dual RS232-HS"
ftdi_vid_pid 0x0403 0x6010

ftdi_layout_init 0x0c08 0x0f1b
ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800

#Reset Stretcher logic on FE310 is ~1 second long
#This doesn't apply if you use
# ftdi_set_signal, but still good to document
#adapter_nsrst_delay 1500

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

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

flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME
init
#reset -- This type of reset is not implemented yet
if {[ info exists pulse_srst]} {
  ftdi_set_signal nSRST 0
  ftdi_set_signal nSRST z
  #Wait for the reset stretcher
  #It will work without this, but
  #will incur lots of delays for later commands.
  sleep 1500
}
halt
#flash protect 0 64 last off

I also used the latest openocd Linux build from SiFive.

1 Like

Yes, this will work just fine.
Also suggest for faster results of programming, put your code in SRAM rather than flash … changing the ā€œflash bankā€ command to use address 0x80000000 instead; helps a lot. Then, when all is good you can retarget back to flash.

1 Like

Hello

Just wanted to revive this conversation. I am trying to do the same thing with an older BBC Hifive Learner board. It has a layout similar to the RevB . I need some help getting openocd running.

I wish to bypass the JLINK-OB and use a tag-connect 10pin 2050 connector with a Olimex Arm-USB-TINY-H. This needs to work on a Windows OS. Using msys64.

  1. I can confirm that with the JLINK_OB I can connect fine with JLINK.exe and enter debug. Read and write some GPIOs and Memory above 8000_0000 fine.

  2. I tried openocd with JLINK driver swapped with WinUSB but it keeps saying no Jlink found . I checked the Jaylink discovery.c code and the proper IDs seem to be in there. I cannot explain why the thing does not get recognized. But I dont really want to use it this way so let’s move on.

  3. Tiny-USB. I think I have everything hooked up and cfgs seem to be correct from the info I got using JLink.exe


===============================================

#
# Olimex ARM-USB-TINY-H
#
# http://www.olimex.com/dev/arm-usb-tiny-h.html
#
adapter speed  4000
adapter driver ftdi
ftdi device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H"
ftdi vid_pid 0x15ba 0x002a

ftdi layout_init 0x0808 0x0a1b
ftdi layout_signal nSRST -oe 0x0200
ftdi layout_signal nTRST -data 0x0100 -oe 0x0100
ftdi layout_signal LED -data 0x0800

transport select jtag

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

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

flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME
init
#reset -- This type of reset is not implemented yet
if {[ info exists pulse_srst]} {
  ftdi_set_signal nSRST 0
  ftdi_set_signal nSRST z
  #Wait for the reset stretcher
  #It will work without this, but
  #will incur lots of delays for later commands.
  sleep 1500
}
halt
#flash protect 0 64 last off
================================================================

Running openocd gives

jtag
Info : clock speed 4000 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway…
Error: riscv.cpu: IR capture error; saw 0x1f not 0x01
Warn : Bypassing JTAG setup events due to errors
Error: Unsupported DTM version: 15
Warn : target riscv.cpu.0 examination failed
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
Error: Target not examined yet

Error: Unsupported DTM version: 15

1 Like

@cdickinson66 it will work fine. I’ve seen this response many times, it usually means wiring is wrong, device is missing, or a completely different and non-existent device has been selected.

First, make sure your olimax and tag-connect wiring is correct. You only need six wires, including power and ground. Below are some handy pinout diagrams. If your wires are longer than about 6in, a series RC filter (~50 Ohm, 1000 pF) on the TCK line to GND is necessary to eliminate stray pulses and signal reflections and, thus, erratic JTAG state machine behavior and even more strange and cryptic error messages from OpenOCD.


Second, for best results on MS Windows use the Zadig tool and install the libusbK driver to at least the ā€˜0’ instance of the Olimex device. You can leave the’1’ instance for FTDI’s VCP (Virtual COM Port) driver if you wish to hook up a UART terminal). Zadig is open source, freely available, and a very good device driver management tool for Windows systems.

Third, here is the most brief script you’d need:

ftdi vid_pid 0x15ba 0x002a ;# olimex arm-usb-tiny-h`
ftdi layout_init 0x0b08 0x0b1b ;# handle olimex glitch problem
adapter speed 500 ;# start slow, for now
reset_config none ;# IMPORTANT: dont use nSRST or nTRST
transport select jtag
jtag newtap riscv cpu -irlen 5 -ircapture 0x1 -irmask 0xf
target create riscv.cpu.0 riscv -chain-position riscv.cpu -coreid 0
riscv set_reset_timeout_sec 120 ;# IMPORTANT: time for hart to come out of reset -- 1.5 min, min
riscv set_command_timeout_sec 2 ;# num secs for hart to process command -- 2 sec, typ
riscv reset_delays 5 ;# num run-test-idle cycles between scans
riscv.cpu.0 configure -work-area-phys 0x80000000 -work-area-size 0x400 -work-area-backup 0
flash bank onboard_spi_flash fespi 0x20000000 0 0 0 riscv.cpu.0 0x10014000
init
halt

At this point you’re all set, target should be stopped, and you can either load/run program from RAM …

load_image <my-ram-pgm.bin> 0x80000000 bin
verify_image <my-ram-pgm.bin> 0x80000000 bin
resume 0x80000000

… or you can load/run program from Flash/ROM (ā€˜N’ is number of flash blocks your program occupies, rounded up–in case of your board, the ISSI flash block size is 0x1000) …

flash protect 0 0 N off
flash erase_sector 0 0 N
flash write_bank 0 <my-rom-pgm.bin>
flash verify_bank 0 <my-rom-pgm.bin>
flash protect 0 0 N on
resume 0x20000000

… or you can simply quit gracefully

shutdown
exit

Of course, make sure the RAM or ROM program you load has been linked to the appropriate address – 0x80000000 or 0x20000000, respectively.

To determine the number ’N’ of Flash/ROM blocks dynamically you can do so from within your OpenOCD tcl configuration file like

set secsz [expr 0x1000] ;# 4K sectors issi is25lp128d, typ. most NOR flash
set len [file size my-rom-pgm.bin]
set endsec [expr (${len}/${secsz})+((${len}-(${len}/${secsz})*${secsz})>0)-1]

In /bin/bash script, for use in makefiles on Linux or Mac machines:

$(eval SECSZ=$(shell echo "ibase=16; 1000" | bc))
$(eval LEN=$(shell <my-rom-pgm.bin wc -c))
$(eval ENDSEC=$(shell echo "(${LEN}/${SECSZ})+((${LEN}-(${LEN}/${SECSZ})*${SECSZ})>0)-1" | bc))

In msdos script, for use in makefiles on an MS Windows machine:

$(eval SECSZ=$(shell for /f "tokens=*" %%A in ('set /a "(0x1000)"') do echo %%A ))
$(eval LEN=$(shell forfiles /m my-rom-pgm.bin /c "cmd /c echo @fsize"))
$(eval ENDSEC=$(shell for /f "tokens=*" %%A in ('set /a "(${LEN}/${SECSZ})"') do echo %%A ))
#$(eval REM=$(shell for /f "tokens=*" %%A in ('set /a "(${LEN} %% ${SECSZ})"') do echo %%A ))
$(eval REM=$(shell for /f "tokens=*" %%A in ('set /a "(${LEN}-(${LEN}/${SECSZ})*${SECSZ})"') do echo %%A ))
$(eval ENDSEC=$(shell for /f "tokens=*" %%A in ('if ${REM} gtr 0 set /a "(${ENDSEC} + 1)"') do echo %%A ))
$(eval ENDSEC=$(shell for /f "tokens=*" %%A in ('set /a "(${ENDSEC} - 1)"') do echo %%A ))

Then you can simply replace the ’N’ with ${endsec} in the protect and erase steps of the flash commands above.

1 Like