라즈베리파이(RPI)4 OpenOCD JTAG 연결 디버깅 방법
임베디드 시스템 개발 및 분석 중 라즈베리 파이4를 통해 디버깅 및 테스트를 하는 것이 제일 간단하고 유용할 것으로 예상되어 찾아본 결과 라즈베리파이4 자체의 JTAG Pin을 활용하여 ARM64 환경의 Bare-Metal Code 테스트를 진행 할 수 있으며 쉽게 테스트 및 디버깅이 가능하여 테스트 및 응용에 매우 강력하고 유용한 플랫폼으로 활용이 가능할 것으로 생각한다.
대략적인 연결 방법은 라즈베리파이4 Bare-Metal Code 로드 및 디버깅과 커널 디버깅에 사용할 수 있도록 OpenOCD를 사용하여 JTAG Interface를 활용 및 연결해야 한다.
그러기 위해서 라즈베리파이의 JTAG Pin을 소유하고 있는 JTAG Debugger (Olimex ARM-USB-OCD-H) 연결하여 TAP 인식 및 ARM Core Debugging 이 가능하다.
라즈베리파이4의 JTAG Pin 위치는 하기와 같다.
위에 나와있는 그림처럼 RPI의 JTAG Pin을 참고하여 사용하고자 하는 JTAG(여기서는 Olimex ARM-USB-OCD-H)의 Pin Map을 확인하여 1대1 연결하여 JTAG 통신 환경을 구축한다.
라즈베리파이에서 JTAG Pin을 사용하기 위해서는 Default Pin Func(Mux)가 JTAG 용도로 정의 되어 있지 않기 때문에
하기와 같이 booting 시 config.txt에 기입하여 Pin Mux를 진행하여야 한다.
[all]
# Disable pull downs
gpio=22-27=np
# Enable jtag pins (i.e. GPIO22-GPIO27)
enable_jtag_gpio=1
OpenOCD에서 rpi4 디버깅 연결을 위하여 하기와 같이 rpi4 관련된 config 파일을 생성해야 하는데 하기와 같이 작성하여
rpi4.cfg를 /share/openocd/script/targets 내에 저장해준다.
# SPDX-License-Identifier: GPL-2.0-or-later
# The Broadcom BCM2711 used in Raspberry Pi 4
# No documentation was found on Broadcom website
# Partial information is available in raspberry pi website:
# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME bcm2711
}
if { [info exists CHIPCORES] } {
set _cores $CHIPCORES
} else {
set _cores 4
}
if { [info exists USE_SMP] } {
set _USE_SMP $USE_SMP
} else {
set _USE_SMP 0
}
if { [info exists DAP_TAPID] } {
set _DAP_TAPID $DAP_TAPID
} else {
set _DAP_TAPID 0x4ba00477
}
jtag newtap $_CHIPNAME cpu -expected-id $_DAP_TAPID -irlen 4
adapter speed 3000
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
# MEM-AP for direct access
target create $_CHIPNAME.ap mem_ap -dap $_CHIPNAME.dap -ap-num 0
# these addresses are obtained from the ROM table via 'dap info 0' command
set _DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000}
set _CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000}
set _smp_command "target smp"
for { set _core 0 } { $_core < $_cores } { incr _core } {
set _CTINAME $_CHIPNAME.cti$_core
set _TARGETNAME $_CHIPNAME.cpu$_core
cti create $_CTINAME -dap $_CHIPNAME.dap -ap-num 0 -baseaddr [lindex $_CTIBASE $_core]
target create $_TARGETNAME aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase [lindex $_DBGBASE $_core] -cti $_CTINAME
set _smp_command "$_smp_command $_TARGETNAME"
}
if {$_USE_SMP} {
eval $_smp_command
}
# default target is cpu0
targets $_CHIPNAME.cpu0
OpenOCD 실행을 하기와 같이 JTAG Interface와 RPI4에 관련된 cfg 파일을 -f 매개인자를 통하여 실행한다.
.\bin\openocd.exe -f .\share\openocd\scripts\interface\ftdi\olimex-arm-usb-ocd-h.cfg -f .\share\openocd\scripts\target\rpi4.cfg
위의 명령을 통해 OpenOCD를 터미널 혹은 PowerShell 상에서 실행하여 아래의 그림과 같이 GDB Server 와 Telnet Port가 생성되는 것을 확인 할 수 있다.
GDB Server가 정상적으로 실행되면 Rpi4의 Kernel 또는 Bare-metal Code를 작성하여 빌드 후 테스트 할 수 있는 환경을 갖추게 됩니다.
이 이후의 GDB Server Remote 연결 및 GDB 디버깅은 다음 포스트에서 진행하도록 하겠습니다.