Possible JTAG boards:
- RasPi3
- Segger J-Link V9
- TinCanTools Flyswatter
- OpenMoko DebugBoard_v3 - this is the version have
Helpful RPi3 GPIO header pinouts from element14 for Model B and here for Model B+ (they are the same).
These are regular GPIO functions, which we specify in OpenOCD interface configuration to enable driving JTAG interface. We should be able to choose pretty much any available pins.
FUNC | GPIO | PIN #
------+--------+-------
TCK | GPIO11 | 23
TMS | GPIO25 | 22
TDI | GPIO10 | 19
TDO | GPIO9 | 21
TRST* | GPIO7 | 26
GND | GND | 20
RPi doesn't expose SRST so we ignore it.
These are real JTAG pins of bcm2837, enabled on target RPi via config.txt options (see below).
FUNC | GPIO | PIN # | MODE
------+--------+---------+------
TCK | GPIO25 | 22 | Alt4
TMS | GPIO27 | 13 | Alt4
TDI | GPIO26 | 37 | Alt4
TDO | GPIO24 | 18 | Alt4
TRST | GPIO22 | 15 | Alt4
RTCK | GPIO23 | 16 | Alt4
GND | GND | 20 |
Connecting TDI to pin 7 (GPIO4) did not work!
Source (section 6.2 Alternative Function Assignments)
In config.txt:
# Set GPIO pins for JTAG debugger connection on rpi3
gpio=22-27=a4
Alternatively, just specify this: (@todo verify this works with all alt4 pins)
enable_jtag_gpio=1
Func | Host Pin | Wire color | Target pin
-----+----------+------------+-----------
TCK | 23 | yellow | 22
TMS | 22 | brown | 13
TDI | 19 | green | 37
TDO | 21 | orange | 18
TRST | 26 | red | 15
GND | 20 | black | 20
You need two files: interface file for driving the host GPIO correctly, and target file for detecting the JTAG circuitry on the target RPi.
Interface configuration: rpi3_interface.cfg
Source, source #2 - rpi3 speed_coeffs
Target configuration: rpi3_target.cfg
Source #1, source #2, source #3, source #4, source #5, source #6 - proper rpi3 ocd config, source #7 - simpler rpi3 ocd config, source #8 - explanations about SRST, source #9 - example RPi target config, source #10 - some JTAG debug hints on rpi, source #11 - jtag vs swd and CoreSight info links
If a SoC provides a JTAG debug interface and contains any CoreSight debug components (including any Cortex processor) you should expect to see the standard JTAG IDCODE of a single CoreSight SWJ-DP as one TAP on the JTAG chain.
Need to verify if the following bug is still valid:
There is a bug in OpenOCD that will prevent Raspberry PI from continuing correctly after a stop unless the initialization is done twice. Close OpenOCD with Ctrl-C and re-run it again. Now the debugging will be usable.
Run openocd -f rpi3_interface.cfg -f rpi3_target.cfg
Run gdb kernel.elf
and connect to device:
target remote :5555
x/10i $pc
stepi
x/2i $pc
If stepi
command causes CPU to make one instruction step, everything is working.
Source, source #2, source #3 - monitor reset halt
I got RPi3-to-RPi3 JTAG working and even debugged a bit directly on the CPU, but a few things make it not an ideal experience:
- RPi is a bit too slow for bitbanging and oftentimes opening a browser window, or running some other command caused OpenOCD to spew JTAG synchronization errors.
- To properly debug my kernel from RPi I would need to compile it locally (otherwise all the paths in the debug info are wrong and GDB will not find the source files, I did not want to mess around with symlinks). Compiling rust on rpi3 is slow.
Fortunately, at this point a Segger J-Link 9 arrived and I went to use it.
JTAG pinout on JLink is in UM08001_JLink.pdf distributed with the J-Link software kit, in section 18.1.1 Pinout for JTAG
.
Reproduced here in ASCII:
+-----------------+
VTRef | 1 * * 2 | NC
nTRST | 3 * * 4 | GND
TDI | 5 * * 6 | GND
TMS | 7 * * 8 | GND
TCK || 9 * * 10 | GND
RTCK || 11 * * 12 | GND
TDO | 13 * * 14 | *
RESET | 15 * * 16 | *
DBGRQ | 17 * * 18 | *
+5V | 19 * * 20 | *
+-----------------+
This adds VTref for target voltage detection. Additionally, with this pinout J-Link is able to power and boot up RPi3 board itself!
Explanation of pins from J-Link manual:
Pin | Signal | Direction | Description |
---|---|---|---|
1 | VTref | Input | This is the target reference voltage. It is used to check if the target has power, to create the logic-level reference for the input comparators and to control the output logic levels to the target. It is normally fed from VDD of the target board and must not have a series resistor. |
2 | NC | Not connected | This pin is not connected in J-Link. |
3 | nTRST | Output | JTAG Reset. Output from J-Link to the Reset signal of the target JTAG port. Typically connected to nTRST of the target CPU. This pin is normally pulled HIGH on the target to avoid unintentional resets when there is no connection. |
4, 6, 8, 10, 12 | GND | Ground | Pins connected to GND in J-Link. They should also be connected to GND in the target system. |
5 | TDI | Output | JTAG data input of target CPU. It is recommended that this pin is pulled to a defined state on the target board. Typically connected to TDI of the target CPU. |
7 | TMS | Output | JTAG mode set input of target CPU. This pin should be pulled up on the target. Typically connected to TMS of the target CPU. |
9 | TCK | Output | JTAG clock signal to target CPU. It is recommended that this pin is pulled to a defined state of the target board. Typically connected to TCK of the target CPU. |
11 | RTCK | Input | Return test clock signal from the target. Some targets must synchronize the JTAG inputs to internal clocks. To assist in meeting this requirement, you can use a returned, and re-timed, TCK to dynamically control the TCK rate. J-Link supports adaptive clocking, which waits for TCK changes to be echoed correctly before making further changes. Connect to RTCK if available, otherwise to GND. |
13 | TDO | Input | JTAG data output from target CPU. Typically connected to TDO of the target CPU. |
15 | nRESET | I/O | Target CPU reset signal. Typically connected to the RESET pin of the target CPU, which is typically called “nRST”, “nRESET” or “RESET”. This signal is an active low signal. |
17 | DBGRQ | Not connected | This pin is not connected in J-Link |
19 | 5V-Supply | Output | This pin can be used to supply power to the target hardware. Older J-Links may not be able to supply power on this pin. |
Func | J-Link Pin | Wire color | Target pin | Target GPIO | Target Func
------+--------------+-------------+------------+-------------+-------------
VTref | 1 | white | 1 | |
nTRST | 3 | red | 15 | GPIO22 | Alt4
TDI | 5 | green | 37 | GPIO26 | Alt4
TMS | 7 | brown | 13 | GPIO27 | Alt4
TCK | 9 | yellow | 22 | GPIO25 | Alt4
RTCK | 11 | magenta | 16 | GPIO23 | Alt4
TDO | 13 | orange | 18 | GPIO24 | Alt4
GND | 4 | black | 20, 14 | |
Rebuild openocd from git and voila, it works with
openocd -f interface/jlink.cfg -f rpi3_jtag.cfg
probe-rs info
shall detect J-Link and the RasPi
probe-rs --chip RaspberryPi4B
Andre Richter has created an entry in his excellent RPi tutorials dedicated exactly to JTAG debugging.
So debugging is a lot easier now - just drop specifically-built JTAG enabler binary to sdcard, connect over JTAG via openocd and gdb and go load your kernel!