Add JTAG documentation

This is old and tried docs from my RPi debugging setup with JTAG,
the next chapter with probe.rs is to be written.
This commit is contained in:
Berkus Decker 2020-10-27 23:22:16 +02:00
parent ec27898830
commit 1fedc95d42
6 changed files with 389 additions and 0 deletions

View File

@ -83,6 +83,8 @@ Based on [Raspi3 tutorials by Andre Richter](https://github.com/rust-embedded/ru
which are in turn based on [Raspi3 tutorials by bzt](https://github.com/bztsrc/raspi3-tutorial/).
Various references from [OSDev Wiki](https://wiki.osdev.org/Raspberry_Pi_Bare_Bones) and [RaspberryPi.org manuals](https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf).
[Debug with JTAG](doc/rpi3_jtag.md).
## Badges
[![Built with cargo-make](https://sagiegurari.github.io/cargo-make/assets/badges/cargo-make.svg)](https://sagiegurari.github.io/cargo-make)

View File

@ -0,0 +1,19 @@
# Broadcom 2835 on Raspberry Pi as JTAG host
interface bcm2835gpio
bcm2835gpio_peripheral_base 0x3F000000
# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET
# These depend on system clock, calibrated for stock 700MHz
# bcm2835gpio_speed SPEED_COEFF SPEED_OFFSET
bcm2835gpio_speed_coeffs 194938 48
# Each of the JTAG lines need a gpio number set: tck tms tdi tdo
# Header pin numbers: 23 22 19 21
bcm2835gpio_jtag_nums 11 25 10 9
# If you define trst or srst, use appropriate reset_config
# Header pin numbers: TRST - 26, SRST - 12
bcm2835gpio_trst_num 7

View File

@ -0,0 +1,51 @@
# Broadcom 2837 on Raspberry Pi 3 as JTAG target
# From https://www.suse.com/c/debugging-raspberry-pi-3-with-jtag/
telnet_port 4444
gdb_port 5555
transport select jtag
# we need to enable srst even though we don't connect it
reset_config trst_and_srst
adapter_khz 4000
jtag_ntrst_delay 500
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME rpi3
}
#
# Main DAP
#
if { [info exists DAP_TAPID] } {
set _DAP_TAPID $DAP_TAPID
} else {
set _DAP_TAPID 0x4ba00477
}
jtag newtap $_CHIPNAME tap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -enable
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap
set _TARGETNAME $_CHIPNAME.a53
set _CTINAME $_CHIPNAME.cti
set DBGBASE {0x80010000 0x80012000 0x80014000 0x80016000}
set CTIBASE {0x80018000 0x80019000 0x8001a000 0x8001b000}
set _cores 4
for { set _core 0 } { $_core < $_cores } { incr _core } {
cti create $_CTINAME.$_core -dap $_CHIPNAME.dap -ap-num 0 \
-ctibase [lindex $CTIBASE $_core]
target create $_TARGETNAME.$_core aarch64 \
-dap $_CHIPNAME.dap -coreid $_core \
-dbgbase [lindex $DBGBASE $_core] -cti $_CTINAME.$_core
$_TARGETNAME.$_core configure -event reset-assert-post "aarch64 dbginit"
$_TARGETNAME.$_core configure -event gdb-attach { halt }
}

16
doc/rpi3_config.txt Normal file
View File

@ -0,0 +1,16 @@
# This is a config.txt file that should be on RPi SD boot partition
cec_osd_name=Jellyfish
# Keep rainbow splash screen on boot
# Helps in debugging boot problems.
disable_splash=0
# Set jtag debug pins to alt4, uses GPIO26 for TDI
gpio=22-27=a4
# Start with 128Mb of GPU memory
start_x=1
# Don't fill kernel ATAGs
disable_commandline_tags=1

269
doc/rpi3_jtag.md Normal file
View File

@ -0,0 +1,269 @@
# Connecting RPi3 JTAG
Possible JTAG boards:
* RasPi3
* Segger J-Link V9
* TinCanTools Flyswatter
* OpenMoko DebugBoard_v3 - [this is the version have](http://wiki.openmoko.org/wiki/Debug_Board_v3)
## RPi3 to RPi3 JTAG
Helpful RPi3 GPIO header pinouts from element14 [for Model B](https://www.element14.com/community/docs/DOC-73950/l/raspberry-pi-3-model-b-gpio-40-pin-block-pinout) and [here for Model B+](https://www.element14.com/community/docs/DOC-88824/l/raspberry-pi-3-model-b-gpio-40-pin-block-poe-header-pinout) (they are the same).
### Host configuration:
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.
[Source](https://movr0.com/2016/09/02/use-raspberry-pi-23-as-a-jtagswd-adapter/)
### Target configuration:
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)](https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf)
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
```
### Wire Connection between boards
```
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
```
### OpenOCD configuration on the host
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](./rpi2rpi_jtag/rpi3_interface.cfg)
[Source](https://movr0.com/2016/09/02/use-raspberry-pi-23-as-a-jtagswd-adapter/), [source #2 - rpi3 speed_coeffs](https://forum.doozan.com/read.php?3,21789)
Target configuration: [rpi3_target.cfg](./rpi2rpi_jtag/rpi3_target.cfg)
[Source #1](https://electronics.stackexchange.com/questions/249008/how-to-use-rpi-2-to-debug-rpi-model-b-via-jtag-with-openocd/419724#419724), [source #2](https://sysprogs.com/tutorials/preparing-raspberry-pi-for-jtag-debugging/), [source #3](http://openocd.org/doc/html/Reset-Configuration.html), [source #4](http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ka3854.html), [source #5](https://www.raspberrypi.org/forums/viewtopic.php?p=1013802), [source #6 - proper rpi3 ocd config](https://www.suse.com/c/debugging-raspberry-pi-3-with-jtag/), [source #7 - simpler rpi3 ocd config](https://github.com/daniel-k/openocd/blob/armv8/tcl/target/rpi3.cfg), [source #8 - explanations about SRST](https://catch22.eu/baremetal/openocd_sysfs_stm32/), [source #9 - example RPi target config](https://github.com/OP-TEE/build/blob/master/rpi3/debugger/pi3.cfg), [source #10 - some JTAG debug hints on rpi](https://www.raspberrypi.org/forums/viewtopic.php?p=1013802), [source #11 - jtag vs swd and CoreSight info links](https://electronics.stackexchange.com/questions/53571/jtag-vs-swd-debugging?rq=1)
> 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.
### Run OpenOCD, GDB and attach to target
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.
[Source](https://sysprogs.com/tutorials/preparing-raspberry-pi-for-jtag-debugging/)
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](https://sysprogs.com/tutorials/preparing-raspberry-pi-for-jtag-debugging/), [source #2](https://www.op-tee.org/docs/rpi3/#6-openocd-and-jtag), [source #3 - monitor reset halt](http://www.openstm32.org/forumthread823)
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.
## J-Link to RPi3 JTAG
> https://www.segger.com/downloads/jlink/
> https://habr.com/ru/post/259205/
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:
<table>
<thead>
<tr>
<th>Pin</th>
<th>Signal</th>
<th>Direction</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>VTref</td>
<td>Input</td>
<td>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.</td>
</tr>
<tr>
<td>2</td>
<td>NC</td>
<td>Not connected</td>
<td>This pin is not connected in J-Link.</td>
</tr>
<tr>
<td>3</td>
<td>nTRST</td>
<td>Output</td>
<td>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.</td>
</tr>
<tr>
<td>4, 6, 8, 10, 12</td>
<td>GND</td>
<td>Ground</td>
<td>Pins connected to GND in J-Link. They should also be connected to GND in the target system.</td>
</tr>
<tr>
<td>5</td>
<td>TDI</td>
<td>Output</td>
<td>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.</td>
</tr>
<tr>
<td>7</td>
<td>TMS</td>
<td>Output</td>
<td>JTAG mode set input of target CPU. This pin should be pulled up on the target. Typically connected to TMS of the target CPU.</td>
</tr>
<tr>
<td>9</td>
<td>TCK</td>
<td>Output</td>
<td>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.</td>
</tr>
<tr>
<td>11</td>
<td>RTCK</td>
<td>Input</td>
<td>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, <b>otherwise to GND.</b></td>
</tr>
<tr>
<td>13</td>
<td>TDO</td>
<td>Input</td>
<td>JTAG data output from target CPU. Typically connected to TDO of the target CPU.</td>
</tr>
<tr>
<td>15</td>
<td>nRESET</td>
<td>I/O</td>
<td>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.</td>
</tr>
<tr>
<td>17</td>
<td>DBGRQ</td>
<td>Not connected</td>
<td>This pin is not connected in J-Link</td>
</tr>
<tr>
<td>19</td>
<td>5V-Supply</td>
<td>Output</td>
<td>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.</td>
</tr>
</tbody>
</table>
### J-Link wire connection with RPi3
```
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 | |
```
[Useful article](https://www.suse.com/c/debugging-raspberry-pi-3-with-jtag/).
### Run with OpenOCD
Rebuild openocd from git and voila, it works with
`openocd -f interface/jlink.cfg -f rpi3_jtag.cfg`
### Run with probe-rs
To be written when probe-rs starts supporting RPi3/4.
## Andre Richter's tutorials
Andre Richter has created an entry in his excellent RPi tutorials dedicated exactly to [JTAG debugging](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/tree/master/09_hw_debug_JTAG).
So debugging is a lot easier now - just drop [specifically-built JTAG enabler](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/tree/master/X1_JTAG_boot) binary to sdcard, connect over JTAG via openocd and gdb and go load your kernel!

32
doc/rpi3_serial.md Normal file
View File

@ -0,0 +1,32 @@
# Connecting RPi3 UART
## Using cp2104 usb-to-ttl converter
Download drivers from [SiLabs driver page](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers).
Install `minicom`: `brew install minicom`
Configure minicom to use `/dev/tty.SLAB_USBtoUART` port. On macOS Big Sur it might be `/dev/tty.usbserial-019586E3` or similar depending on the serial number of the adapter.
Connect RPi wires to cp2014:
_NB:_ Swap the TXD and RXD wires. I.e. RXD pin of CP2104 should go to TXD pin on RPi and vice versa.
```
UART0
RPi Func | RPi GPIO | PIN # | MODE | CP2104 Pin | Wire color
----------+------------+---------+--------+------------+------------
RXD0 | GPIO15 | 10 | Alt0 | TXD | Red
TXD0 | GPIO14 | 8 | Alt0 | RXD | Brown
```
```
MiniUart (UART1)
RPi Func | RPi GPIO | PIN # | MODE | CP2104 Pin | Wire color
----------+------------+---------+--------+------------+------------
RXD1 | GPIO15 | 10 | Alt5 | TXD | Red
TXD1 | GPIO14 | 8 | Alt5 | RXD | Brown
GND | GND | 6 | | GND | Green
```