U-Boot 포팅 (7. U-Boot 디버깅 및 문제 해결 / JTAG 디버깅)

2025. 3. 5. 12:52프로그래밍/시스템

JTAG 디버깅 (U-Boot 디버깅을 위한 설정 및 활용법)

JTAG(Joint Test Action Group)은 임베디드 시스템에서 하드웨어 디버깅을 위한 표준 인터페이스입니다.
U-Boot에서 JTAG을 사용하면 CPU 레지스터 값 확인, 메모리 접근, 중단점 설정 및 코드 실행 흐름 분석이 가능합니다.

이 문서에서는 **JTAG 설정 방법 및 활용법(OpenOCD, GDB 연동 포함)**을 설명합니다.


1. JTAG 개요 및 필요성

🔹 JTAG이란?

JTAG은 SoC, 마이크로컨트롤러(MCU), FPGA 등에서 디버깅, 프로그래밍 및 테스트를 수행하는 표준 인터페이스입니다.
운영체제가 실행되지 않아도 CPU 및 메모리를 직접 디버깅 가능
CPU 레지스터 값 확인 및 수정 가능
U-Boot 실행 흐름 분석 및 중단점(Breakpoint) 설정 가능
플래시 메모리 및 부트로더 프로그래밍 가능


🔹 JTAG 디버깅을 위한 준비 사항

  1. JTAG 디버거 하드웨어 (예: SEGGER J-Link, ARM-USB-OCD, FTDI 기반 JTAG 디버거)
  2. JTAG 소프트웨어(OpenOCD, GDB)
  3. JTAG 인터페이스 핀 연결 (TDI, TDO, TCK, TMS, TRST, SRST)
  4. U-Boot를 JTAG 디버깅 모드로 실행 가능하도록 설정

2. JTAG 디버깅을 위한 OpenOCD 설정

🔹 OpenOCD 설치

📌 Ubuntu/Debian 계열

sudo apt update
sudo apt install openocd gdb-multiarch

📌 설치 확인

openocd -v

✅ OpenOCD 버전이 출력되면 설치 성공


🔹 JTAG 하드웨어 연결

JTAG 디버거를 보드의 JTAG 핀에 연결해야 합니다.
일반적인 JTAG 핀 구성:

역할
TDI Test Data In
TDO Test Data Out
TCK Test Clock
TMS Test Mode Select
TRST Test Reset (선택 사항)
SRST System Reset (선택 사항)

JTAG 핀 연결 후, USB를 통해 디버거를 PC에 연결


🔹 OpenOCD 설정 파일 작성 (myboard.cfg)

📌 보드에 맞는 OpenOCD 설정 파일 생성 (/etc/openocd/myboard.cfg)

interface ftdi
ftdi_vid_pid 0x0403 0x6010
ftdi_layout_init 0x0808 0x0a1b
reset_config srst_only srst_push_pull

adapter_khz 1000
transport select jtag

source [find target/arm926ejs.cfg]

FTDI 기반 JTAG 디버거를 사용할 경우 위와 같이 설정
SoC에 맞는 target/*.cfg 파일을 찾아 포함시켜야 함


🔹 OpenOCD 실행

📌 JTAG 디버거와 보드를 연결한 후 OpenOCD 실행

openocd -f /etc/openocd/myboard.cfg

📌 출력 예제

Open On-Chip Debugger 0.11.0 (2025-03-04)
Licensed under GNU GPL v2
Info : clock speed 1000 kHz
Info : JTAG tap: myboard.cpu tap/device found

JTAG이 정상적으로 인식되었음을 확인 가능


3. GDB를 사용한 JTAG 디버깅

🔹 U-Boot ELF 파일 준비

JTAG을 통해 디버깅하려면 심볼 정보가 포함된 u-boot.elf 파일이 필요합니다.

📌 U-Boot ELF 파일 빌드

make myboard_defconfig
make -j$(nproc)

빌드 후 u-boot.elf 파일이 생성됨 (./u-boot)


🔹 GDB를 사용한 디버깅 (gdb-multiarch 연동)

📌 GDB 실행 및 OpenOCD 연결

gdb-multiarch u-boot

📌 GDB 프롬프트에서 OpenOCD 서버에 연결

target remote localhost:3333

JTAG을 통해 U-Boot 실행 상태에 접근 가능

📌 CPU 레지스터 확인

info registers

📌 U-Boot 코드 실행 흐름 확인

layout asm
layout regs

📌 중단점 설정 및 실행

break main
continue

U-Boot의 main() 함수에서 실행이 멈추도록 설정

📌 단계별 실행 및 코드 분석

step   # 한 줄씩 실행
next   # 함수 실행 후 다음 줄로 이동
finish # 현재 함수 실행 완료 후 복귀

📌 메모리 직접 읽기 및 수정

x/10x 0x80000000  # 주소 0x80000000부터 10개 확인
set {int}0x80000000 = 0xDEADBEEF  # 메모리 값 변경

JTAG을 사용하면 커널 실행 없이도 직접 메모리를 수정할 수 있음


4. JTAG을 이용한 플래시 메모리 프로그래밍

📌 OpenOCD를 통해 U-Boot를 NAND/eMMC에 직접 플래싱

openocd -f /etc/openocd/myboard.cfg -c "init; reset halt; flash write_image erase u-boot.bin 0x400000; reset run; shutdown"

U-Boot를 플래시 메모리에 직접 기록 가능


5. JTAG 디버깅 문제 해결

문제  해결 방법
OpenOCD 실행 시 "no device found" 오류 JTAG 핀 연결 확인, lsusb로 디바이스 인식 여부 확인
GDB 연결 시 "Failed to connect to target" 오류 OpenOCD가 정상 실행 중인지 확인 (localhost:3333 포트)
중단점(Breakpoint)이 작동하지 않음 u-boot.elf 빌드 시 CONFIG_DEBUG=y 설정 확인
플래시 메모리 쓰기 실패 reset halt 실행 후 다시 flash write_image 시도

JTAG 연결 문제 발생 시 dmesg | grep usb를 통해 디버거 인식 여부 확인 가능


📌 정리

JTAG을 사용하여 U-Boot 디버깅 가능
OpenOCD를 설정하고 GDB를 연결하여 실행 흐름 분석
메모리 값 확인 및 수정 (info registers, x/10x, set {int}...)
중단점(Breakpoint) 설정 및 코드 단계별 실행 (break main, step, next)
JTAG을 이용하여 NAND/eMMC에 직접 U-Boot 플래싱 가능