U-Boot 포팅 (5. 디바이스 트리(DTS) 및 환경 변수 설정 / 디바이스 트리(Device Tree)란?)

2025. 2. 26. 12:26프로그래밍/시스템

디바이스 트리(Device Tree)란?

디바이스 트리(Device Tree)는 임베디드 시스템에서 하드웨어 정보를 커널과 부트로더가 이해할 수 있도록 제공하는 데이터 구조입니다.
기존의 보드별 하드웨어 정보를 커널 코드에 직접 작성하는 방식 대신, 독립적인 데이터 구조(DTS/DTB)로 관리하여 유지보수성과 확장성을 향상시킵니다.


1. 디바이스 트리의 개념과 역할

🔹 디바이스 트리는 무엇인가?

  • 하드웨어 정보(RAM, CPU, 저장 장치, GPIO, I2C, SPI 등)를 커널과 부트로더가 이해할 수 있도록 정의한 데이터 구조입니다.
  • 소프트웨어(커널, 부트로더)가 특정 보드의 하드웨어 정보를 코드 없이 동적으로 읽어올 수 있도록 제공합니다.
  • DTS (Device Tree Source) 파일로 작성되며, 컴파일되어 DTB (Device Tree Blob) 형식으로 변환됩니다.

🔹 왜 디바이스 트리를 사용할까?

보드별 하드웨어 차이를 커널 코드에서 분리
커널/부트로더를 수정하지 않고 DTS만 변경하여 다양한 보드 지원 가능
하드웨어 정보를 효율적으로 정의하고 관리 가능

📌 기존 방식 (커널 직접 수정 방식)

static struct platform_device my_device = {
    .name = "my-device",
    .id = -1,
    .resource = my_device_resources,
};

📌 디바이스 트리 방식 (DTS 사용)

/my-device {
    compatible = "vendor,my-device";
    reg = <0x01 0x02>;
};

디바이스 트리를 사용하면 커널을 직접 수정할 필요 없이 보드별 설정을 분리할 수 있음


2. U-Boot에서 사용하는 DTS 및 DTB 개념

🔹 DTS (Device Tree Source)란?

  • 디바이스 트리는 DTS (Device Tree Source) 파일로 작성됩니다.
  • 사람이 읽을 수 있는 텍스트 기반의 파일이며, 보드의 하드웨어 설정을 정의합니다.
  • CPU, RAM, 저장장치, UART, GPIO, I2C, SPI 등의 정보가 포함됩니다.

📌 DTS 파일 예제 (arch/arm/dts/myboard.dts)

/dts-v1/;
#include "arm/boot/dts/soc.dtsi"

/ {
    model = "My Custom Board";
    compatible = "myboard,my-soc";

    memory {
        device_type = "memory";
        reg = <0x80000000 0x40000000>; /* 1GB RAM */
    };

    chosen {
        bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2 rw";
    };

    uart0: serial@10000000 {
        compatible = "ns16550";
        reg = <0x10000000 0x1000>;
        clock-frequency = <24000000>;
    };
};

DTS는 계층 구조(Tree)로 되어 있으며, 각 노드는 특정 하드웨어 정보를 정의합니다.


🔹 DTB (Device Tree Blob)란?

  • DTS 파일은 컴파일되어 바이너리 형태인 DTB (Device Tree Blob) 파일로 변환됩니다.
  • 부트로더(U-Boot)와 커널이 DTB 파일을 로드하여 하드웨어 정보를 참조합니다.

📌 DTS → DTB 변환 과정

dtc -I dts -O dtb -o myboard.dtb myboard.dts

📌 출력 결과

myboard.dtb (바이너리 파일)

부트로더와 커널이 사용할 수 있도록 DTS 파일을 DTB 파일로 변환해야 합니다.


3. U-Boot에서 DTS 및 DTB 파일 작성법

🔹 1) DTS 파일의 기본 구조

📌 DTS 파일 구조 예제

/dts-v1/;
#include "soc.dtsi"

/ {
    model = "My Custom Board";
    compatible = "myboard,my-soc";

    memory {
        device_type = "memory";
        reg = <0x80000000 0x40000000>; /* 1GB RAM */
    };

    chosen {
        bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2 rw";
    };

    uart0: serial@10000000 {
        compatible = "ns16550";
        reg = <0x10000000 0x1000>;
        clock-frequency = <24000000>;
    };
};

각 노드(Node)는 하드웨어 구성 요소를 나타내며, compatible 속성을 통해 드라이버와 연결됩니다.


🔹 2) DTS 파일 작성 및 추가 방법

📌 새로운 보드용 DTS 파일 추가

cp arch/arm/dts/existing_board.dts arch/arm/dts/myboard.dts

📌 DTS 파일 수정

vim arch/arm/dts/myboard.dts

📌 새로운 DTS 파일을 Makefile에 추가 (arch/arm/dts/Makefile)

dtb-$(CONFIG_ARCH_MYBOARD) += myboard.dtb

DTS 파일을 빌드하면 myboard.dtb 파일이 생성됩니다.

📌 DTB 파일 빌드

make dtbs

📌 빌드된 DTB 파일 확인

ls arch/arm/dts/*.dtb
myboard.dtb

이제 U-Boot에서 이 DTB 파일을 사용할 수 있습니다.


4. U-Boot에서 DTB 파일 로드 및 사용

📌 U-Boot에서 DTB 파일 로드하는 방법

setenv fdtfile myboard.dtb
load mmc 0:1 0x83000000 /boot/dtb/myboard.dtb
bootz 0x82000000 - 0x83000000

이 명령어는 DTB 파일을 RAM에 로드한 후, 커널과 함께 실행합니다.


5. 디바이스 트리 디버깅 및 확인 방법

📌 DTB 파일을 확인하는 방법 (dtc 명령어 사용)

dtc -I dtb -O dts -o myboard_decoded.dts myboard.dtb

컴파일된 DTB 파일을 다시 DTS 형식으로 변환하여 내용을 확인할 수 있습니다.

📌 U-Boot에서 디바이스 트리 확인 (fdt 명령어 사용)

fdt print

현재 사용 중인 DTB의 내용을 출력합니다.


📌 정리

디바이스 트리는 하드웨어 정보를 커널과 부트로더가 이해할 수 있도록 제공하는 방식
DTS(Device Tree Source)는 텍스트 파일로 작성되며, DTB(Device Tree Blob)로 변환되어 사용됨
U-Boot에서 DTS 파일을 작성하고 DTB로 변환하는 방법 학습
U-Boot에서 DTB 파일을 로드하고 커널과 함께 실행하는 방법 설명
디바이스 트리 디버깅 및 확인 방법 정리