how to use jtag to debug raspiberry 4B via arceos
Introduction
This article describes a way to debug jtags via openocd, gdb, jlink debugger.
Requirement
Resources
-
Authors using H-JLINK v9 type c Universal ARM Downloader, but theoretically, you can use whatever you want.
-
Some Female to Female Dupont Wire
-
A laptop
Preliminary preparation
-
Connect CH304 from bcm2711 pin 8,10,12 (Rx to Tx, Tx to Rx, GND to GND). By the ways, power indicator closest to 1.
-
Connect H-JLINK based on the picture below:
This static site builder theme is relatively poorly supported with html, please move to rust-raspberrypi-OS-tutorials to know how to connect.
/*
GPIO # | Name | JTAG # | Note | Diagram |
---|---|---|---|---|
VTREF | 1 | to 3.3V | ![]() |
|
GND | 4 | to GND | ||
22 | TRST | 3 | ||
26 | TDI | 5 | ||
27 | TMS | 7 | ||
25 | TCK | 9 | ||
23 | RTCK | 11 | ||
24 | TDO | 13 |
-
Try to test whether chainboot works properly
- go to tools/raspi4/chainloader
- run
make clean && make
, it should generate a kernel8.img under this directory. if everything right, the image file should be 8576 vials -al
. - move this image into your sd card.
- check if your sd card has contians following file start4.elf, fixup4.dat, bcm2711-rpi-4-b.dtb
- just run
make A=apps/helloworld PLATFORM=aarch64-raspi4 chainboot
, then should display this image.
Minipush 1.0
[MP] ⏳ Waiting for /dev/ttyUSB0[MP] ✅ Serial connected
[MP] Please power the target nowThis means that CH340 is not connected or connected in some other way connection is successful maybe /dev/ttyUSB1 or something else After power up the board:
__ __ _ _ _ _ | \/ (_)_ _ (_) | ___ __ _ __| | | |\/| | | ' \| | |__/ _ \/ _` / _` | |_| |_|_|_||_|_|____\___/\__,_\__,_| Raspberry Pi 4 [ML] Requesting binary [MP] ⏩ Pushing 36 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 [ML] Loaded! Executing the payload now @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ You're using chainboot image . @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ d8888 .d88888b. .d8888b. d88888 d88P" "Y88b d88P Y88b d88P888 888 888 Y88b. d88P 888 888d888 .d8888b .d88b. 888 888 "Y888b. d88P 888 888P" d88P" d8P Y8b 888 888 "Y88b. d88P 888 888 888 88888888 888 888 "888 d8888888888 888 Y88b. Y8b. Y88b. .d88P Y88b d88P d88P 888 888 "Y8888P "Y8888 "Y88888P" "Y8888P" arch = aarch64 platform = aarch64-raspi4 target = aarch64-unknown-none-softfloat smp = 1 build_mode = release log_level = warn Hello, world!
Run
Preliminary preparation
1. go to tools/raspi4/chainloader
2. run `make clean && make JTAG=y`, it should generate a kernel8.img under this directory.
if everything right, the image file should be 8576 via `ls -al`.
3. move this image into your sd card.
4. check if your sd card has contians following file
[start4.elf](https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/start4.elf),
[fixup4.dat](https://github.com/raspberrypi/firmware/raw/master/boot/fixup4.dat),
[bcm2711-rpi-4-b.dtb](https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/bcm2711-rpi-4-b.dtb)
Start Debugging
1. just run `make A=apps/helloworld PLATFORM=aarch64-raspi4 chainboot` and Power up the board., then should display this image.
```
Minipush 1.0
[MP] ✅ Serial connected
[MP] 🔌 Please power the target now
__ __ _ _ _ _
| \/ (_)_ _ (_) | ___ __ _ __| |
| |\/| | | ' \| | |__/ _ \/ _` / _` |
|_| |_|_|_||_|_|____\___/\__,_\__,_|
Raspberry Pi 4
[ML] Requesting binary
[MP] ⏩ Pushing 36 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ You're using a JTAG debug image. @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ 1. open openocd, gdb @
@ 2. target extended-remote :3333; @
@ 3. set $pc=0x80000 @
@ 4. break rust_entry/others @
@ 5. break $previous_addr @
@ 6. delete 1 @
@ 7. load @
@ 8. continue @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
```
*the following guidelines is basically like previous datasheets, In fact, if you're a senior developer, skip the following. XD*
3. My personal suggestions is using zellij, but you could choice what ever you want.
4. A: Keeping this miniload running (just don't terminate it) in terminal A.
5. B: run `make A=apps/helloworld PLATFORM=aarch64-raspi4 openocd`,
the windows should display following, but it doesn't matter, we don't need to care about this.
```
$ make A=apps/helloworld PLATFORM=aarch64-raspi4 openocd
Launching OpenOCD
[sudo] password for jacky:
Open On-Chip Debugger 0.11.0+dev-g1ad6ed3 (2021-12-02-20:10)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
DEPRECATED! use 'adapter speed' not 'adapter_khz'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Warn : DEPRECATED! use '-baseaddr' not '-ctibase'
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link V9 compiled May 7 2021 16:26:12
Info : Hardware version: 9.60
Info : VTarget = 3.311 V
Info : clock speed 1000 kHz
Info : JTAG tap: rpi4.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : rpi4.core0: hardware has 6 breakpoints, 4 watchpoints
Info : rpi4.core1: hardware has 6 breakpoints, 4 watchpoints
Info : rpi4.core2: hardware has 6 breakpoints, 4 watchpoints
Info : rpi4.core3: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for rpi4.core0 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for rpi4.core1 on 3334
Info : Listening on port 3334 for gdb connections
Info : starting gdb server for rpi4.core2 on 3335
Info : Listening on port 3335 for gdb connections
Info : starting gdb server for rpi4.core3 on 3336
Info : Listening on port 3336 for gdb connections
```
6. C: run `make A=apps/helloworld PLATFORM=aarch64-raspi4 gdb` in terminal C.
7. You are now in GDB, but just don't start your debug immediately.
Because the use of minipush script, we could simple push our image to board before power up the board.
Like a double-edged sword. It also constrains our behavior,
which it's incapable for us to power up the board then use some kinds like halt command to halt the CPU.
(I think it can be done through script modification, but now there is no time to study and change ruby for a trivial upgrade.)
So we add a dead loop at the end of the image we generate lastest.
```gdb
(gdb) target extended-remote :3333 // connect to openocd gdb serve
// you should see $pc=0x2080db4
(gdb) set $pc=0x80000 // The following behavior is unnecessary and can be debugged normally.
(gdb) monitor poll // MMU disable
(gdb) break rust_entry // Start debug module/axhal/ ... the location is VADDR will case error,
// you should use b *0x81a90 (manally remove 0xffff ... from output)
(gdb) b *0x81a90
(gdb) break rust_main // as previous
(gdb) b *0x82888
(gdb) delete 1 3
(gdb) continue // first stop at rust_entry
(gdb) continue // second stop at rust_main
(gdb) monitor poll // MMU enable (in rust_entry)
```
Reference
- rust-embedded/rust-raspberrypi-OS-tutorials
- Raspberry Pi 4をJTAGデバッグしてみる(FTDI C232HM-DDHSL-0使用)
- Rust Raspberry Pi OS tutorials 08 HW debug JTAG by hikalium 2021-09-20
- my record
- openocd docs, bcm2711 docs, gdb docs ... etc.
Read more