Embedded : : Linux/: : Device Tree

[Device Tree 심화] 1. Intro / 2. DT Architecture

Jay.P Morgan 2026. 3. 4. 16:04

 

Device Tree 심화

DTS/DTB/FDT 구조, 바인딩, OF API, 오버레이, 주소 변환, 인터럽트 매핑까지 Linux 커널 Device Tree 종합 가이드.

전제 조건: 커널 아키텍처와 디바이스 드라이버 문서를 먼저 읽으세요. 하드웨어 기술 정보는 커널 초기화와 드라이버 바인딩의 입력이므로, 기술 데이터와 런타임 탐색 경로를 함께 이해해야 합니다.

 

일상 비유: 이 주제는 설비 배선도와 장비 목록 대조와 비슷합니다. 도면과 실제 배치가 맞아야 정상 동작하듯이, ACPI/DT 정보와 드라이버 기대값이 일치해야 안정적으로 부팅됩니다.

 

 

  1.  Intro

 

  1.1  핵심 요약

 

       단계 분리 — 펌웨어, 부트로더, 커널 초기화 경계를 구분합니다.

       하드웨어 기술 — ACPI/DT 등 기술 정보가 어디서 소비되는지 확인합니다.

       신뢰 체인 — Secure Boot 등 검증 체인을 흐름으로 이해합니다.

       실패 지점 — 부팅 로그에서 단계별 실패 단서를 빠르게 찾습니다.

       호환성 관점 — 플랫폼 차이에 따른 초기화 분기를 함께 점검합니다.

 

 

  1.2  단계별 이해  

 

     1.  부팅 단계 식별

           현재 이슈가 어느 단계에서 발생하는지 먼저 고정합니다.

     2.  입력 데이터 확인

           펌웨어/테이블/이미지 메타데이터를 점검합니다.

     3.  전환 경계 검증

           단계 간 인자 전달과 상태 인계를 추적합니다.

     4.  플랫폼별 재검증

           다른 하드웨어 조건에서도 동일하게 동작하는지 확인합니다.

관련 표준: Devicetree Specification v0.4 (devicetree.org) — DT 문법, FDT 바이너리 포맷, 주소 변환 규칙 등 근본 규격. 종합 목록은 참고자료 -- 표준 & 규격 섹션을 참고하세요.

 

Device Tree는 하드웨어 구성을 기술하는 데이터 구조로, PCI/USB처럼 자동 열거(enumeration)가 불가능한 SoC 내장 디바이스의 정보를 커널에 전달합니다. ARM, RISC-V, PowerPC 등 임베디드 플랫폼에서 필수적이며, Open Firmware(IEEE 1275) 표준에서 유래했습니다.

DTS 처리 흐름: .dts (소스) → dtc (컴파일러) → .dtb (바이너리 블롭) → 부트로더가 메모리에 로드 → 커널이 파싱하여 struct device_node 트리 구축 → 드라이버가 of_* API로 프로퍼티 조회

 

 

  2.  Device Tree  아키텍쳐

 

 

 

  2.1  dts (Device Tree Source) 란?

 

dts (Device Tree Source) 파일은 쉘 스크립트 문법이 아니무니다!  디바이스 트리(Device Tree)는 실행을 위한 프로그래밍 언어는 아니지만, 하드웨어의 구조를 기술하는 전용 언어(DSL, Domain Specific Language)로 이해하시면 가장 정확합니다. 데이터의 구조를 정의한다는 점에서 JSON이나 XML, YAML과 성격이 매우 비슷합니다.

 

디바이스 트리가 언어로서 가지는 특징을 정리해 드릴게요.

오히려 C언어나 JSON과 비슷한 계층 구조(Hierarchical Structure)를 가진 데이터 기술 언어에 가깝습니다. 쉘 스크립트처럼 명령어를 실행하는 것이 아니라, 하드웨어가 어떻게 생겼는지 그 '형태'를 묘사하는 설계도라고 이해하시면 됩니다.

주요 문법적 특징은 다음과 같습니다.

 

1. 하드웨어 기술 언어 (Hardware Description Language)

  일반적인 언어(C, Python)가 "무엇을 어떻게 실행하라"는 로직(Logic)을 담고, 쉘 스크립트는 위에서 아래로 명령을 실행합니다.

  하지만, 디바이스 트리는 "어떤 하드웨어가 어디에 연결되어 있다"는 상태(State)와 구성(Configuration)을 묘사합니다.

계층적 트리 구조 (Tree Structure)로,  DTS는 노드(Node) 안에 속성(Property)과 자식 노드(Child Node)가 들어가는 트리 형태를 가집니다.

 

  • 노드(Node): 객체(Object)를 의미.  node-name { ... }; 형태.  (C의 구조체나 JSON의 객체와 유사, 예: uart0, cpu@0)
  • 속성(Property, 프로퍼티): 객체의 속성(Attribute)을 의미.  key = value; 형태  (예: reg, compatible)

 

2. 컴파일러 존재 (DTC)

  쉘 스크립트는 인터프리터가 한 줄씩 읽어 실행하지만, DTS는 DTC(Device Tree Compiler)라는 전용 컴파일러를 통해 DTB(Device Tree Blob)라는 바이너리 파일로 변환되어야 커널이 읽을 수 있습니다.

 

컴파일 과정과정 (Build Process)

컴퓨터가 이해할 수 있는 바이너리로 변환되는 과정이 있다는 점에서도 언어의 면모를 갖추고 있습니다.

  1. DTS (Source): 사람이 읽을 수 있는 텍스트 파일.
  2. DTC (Compiler): 소스를 바이너리로 변환하는 컴파일러.
  3. DTB (Binary): 커널이 부팅 시 읽어들이는 저수준 데이터 바이너리(Blob).

 

3. 언어의 문법 구조 (Grammar)

디바이스 트리 언어(DTS)는 자신만의 고유한 문법 규칙을 가지고 있습니다.

  • 상속과 오버라이드: .dtsi 파일을 인클루드한 뒤, 특정 노드의 값을 덮어쓰거나 수정할 수 있습니다. 이는 객체지향 언어의 상속 개념과 유사합니다.
  • 참조(Referencing): phandle(&label)을 사용하여 한 노드가 다른 노드(예: 클럭 컨트롤러, 인터럽트 컨트롤러)를 가리킬 수 있는데, 이는 프로그래밍 언어의 포인터(Pointer)나 ID 참조와 같습니다.
  • 선언적 언어 (Declarative Language): 디바이스 트리는 선언적입니다. 쉘 스크립트처럼 if문으로 조건을 따지거나 for문으로 반복하는 기능이 기본적으로 없습니다. 대신, 하드웨어의 설계도면처럼 정보를 나열하기만 하면, 이를 읽어가는 주체인 리눅스 커널이 그 정보를 바탕으로 로직을 실행합니다.
  • C 전처기(Preprocessor) 사용: 코드에 #include가 있는 이유는, DTS가 컴파일되기 전에 C 전처리기를 거치기 때문입니다. 이 부분 때문에 C언어와 비슷해 보일 수 있지만, 그 안의 본문({ ... })은 완전히 독자적인 규칙을 따릅니다.

 

4. 데이터 타입의 엄격함

쉘 스크립트는 변수 타입이 유연하지만, DTS는 데이터 타입을 명확히 구분합니다.

  • Cell (u32): < 0x1234 >
  • String: "hello"
  • Byte array: [00 11 22]

 

요약하자면: DTS는 쉘 스크립트처럼 로직(if, for, 함수 호출 등)을 실행하는 언어가 아니라, 하드웨어 부품 간의 연결 상태와 주소를 정적으로 정의하는 "데이터 사전"입니다.

디바이스 트리 "리눅스 커널과 하드웨어 사이의 약속된 언어"입니다. 이 언어를 통해 커널은 수천 가지의 서로 다른 보드들을 일일이 소스 코드를 수정하지 않고도(재컴파일 없이) 지원할 수 있게 됩니다.

 

 

 

참조: https://www.minzkn.com/linuxkernel/pages/device-tree.html#dt-device-node