carloscn/blog

Starting with JLink debugger or QEMU

carloscn opened this issue · 3 comments

Starting with JLink debugger or QEMU (ARMv8)

  • Debugger: JLink V11
  • Target Hardware: raspiberry 4b
  • Host: Ubuntu 20.04-amd64

Note, the openocd installed by sudo apt-get install openocd is not work on ubuntu 20.04. The error prompted Error: invalid command name "dap". So you shall compile the openocd by yourself. Please refer to the link https://hackaday.io/page/4991-compiling-openocd-from-source-on-ubuntu-1604. (Though it is targetting for ubuntu 16.04, the 20.04 still follow these build steps.)

1. JLink Brief

We should use the three command terminals to launch the Jlink debugger. They are openocd/telnet/gbd-multiarch separately.

40-pin gpio connect

gpio22-27 Alternative Function Assignments all are ALT4.

connect following gpio pin to jlink pin.

PIN NAME GPIO Function ALT
GPIO22 ARM_TRST
GPIO23 ARM_RTCK
GPIO24 ARM_TDO
GPIO25 ARM_TCK
GPIO26 ARM_TDI
GPIO27 ARM_TMS
3.3v Vref
GPIO09 GND

image-20220305204437337

On the openocd command line, should type the cmd is:

sudo openocd -f jlink.cfg -f raspi4.cfg

On the telnet command line, should type the cmds are:

telnet localhost 4444
> halt
> load_image /home/carlos/work/uncleben/armv8_trainning/lab01/benos.bin 0x80000
> step 0x80000

On the gdb command line, should ytpe the cmds are:

gdb-multiarch --tui benos.elf
> target remote localhost:3333
> b ldr_start
> c
> n
> layout regs

2. QEMU Brief

The QEMU is more simple and more quicker than the JLink debugger env.

On the QEMU side, just type the qemu-system-aarch64 -machine raspi4 -nographic -kernel benos.bin -S -s to launch the QEMU. For the gdb-multiarch side, gdb-multiarch --tui benos.elf

image-20220306124845392

gdb-multiarch --tui benos.elf, the localhost port is 1234.

gdb-multiarch --tui benos.elf
> target remote localhost:1234
> b ldr_start
> c
> n
> layout regs

For the config files, you can get them by https://gist.github.com/carloscn/538d57d36b828e52bf8f88d6362b1528

gdb-multiarch --tui benos.elf
gdb> file benos.elf
gdb> target remote localhost:1234
gdb> b ldr_test // 设定断点
gdb> c
gdb> n
gdb> next //下一步
gdb> info register // 查看所有寄存器
gdb> info x1 x2 x3 // 查看x1/x2/x3寄存器
gdb> x 0x80000 // 读取内存0x80000值 32位
gdb> x/xg 0x80000 // 读取内存0x80000值64位
gdb> layout src
gdb> layout regs
gdb> layout split

config.txt

# BenOS for JLINK debug
# for option pls see:https://www.raspberrypi.org/documentation/configuration/config-txt/boot.md
# 

[pi4]
kernel=loop.bin

[pi3]
kernel=loop.bin

[all]
arm_64bit=1  #enable 64bit image
enable_uart=1  #enable pl uart
uart_2ndstage=1   #enable FW debug info

enable_jtag_gpio=1
gpio=22-27=a4
init_uart_clock=48000000
init_uart_baud=115200


#kernel_old=1 # if we set it, the image will be load at 0x0, otherwise the 64bit image will be load on 0x80000
#disable_commandline_tags=1 #Fix me, when set it, the image will be load on 0x0

jlink.cfg

#
# SEGGER J-Link
#
# http://www.segger.com/jlink.html
#

interface jlink

# The serial number can be used to select a specific device in case more than
# one is connected to the host.
#
# Example: Select J-Link with serial number 123456789
#
# jlink serial 123456789

raspi4.cfg

set _CHIPNAME bcm2711
set _DAP_TAPID 0x4ba00477

adapter_khz 1000

transport select jtag
reset_config trst_and_srst

telnet_port 4444

# create tap
jtag newtap auto0 tap -irlen 4 -expected-id $_DAP_TAPID

# create dap
dap create auto0.dap -chain-position auto0.tap

set CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000}
set DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000}

set _cores 4

set _TARGETNAME $_CHIPNAME.a72
set _CTINAME $_CHIPNAME.cti
set _smp_command ""

for {set _core 0} {$_core < $_cores} { incr _core} {
    cti create $_CTINAME.$_core -dap auto0.dap -ap-num 0 -ctibase [lindex $CTIBASE $_core]

    set _command "target create ${_TARGETNAME}.$_core aarch64 \
                    -dap auto0.dap  -dbgbase [lindex $DBGBASE $_core] \
                    -coreid $_core -cti $_CTINAME.$_core"
    if {$_core != 0} {
        set _smp_command "$_smp_command $_TARGETNAME.$_core"
    } else {
        set _smp_command "target smp $_TARGETNAME.$_core"
    }

    eval $_command
}

eval $_smp_command
targets $_TARGETNAME.0