Device Tree 구조 및 순서

SMJ·2025년 12월 21일

BSP development

목록 보기
13/17
post-thumbnail
  • 디바이스 트리
    • 하드웨어의 구성 정보를 명시 (어떻게 연결 되어 있는지)
    • 하드웨어를 직접 제어 (하드웨어 초기화, 레지스터 조작, 인터럽트 처리)
  • 순서 : 커널이 디바이스 트리 노드를 순회하다가 노드를 찾으면 해당 드라이버의 probe 함수를 호출

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

하드웨어의 구조와 특성을 운영체제나 소프트웨어가 이해할 수 있도록 기술한 데이터 구조

보드의 하드웨어 정보를 리눅스 커널에 전달하기 위한 텍스트 기반의 데이터 구조

  • 주요 목적
    • 플랫폼 식별 : 커널이 실행 중인 보드의 하드웨어 구조와 자원을 설명하여 플랫폼에 맞게 초기화 과정을 수행
    • 디바이스 등록 : 디바이스 트리 데이터를 파싱하여 커널 내부 데이터 구조를 생성하고 디바이스 드라이버로 전달
  • 소스 경로
    • 커널의 arch/arm/boot/dts 또는 arch/arm64/boot/dts 경로에 있음
    • 소스 스크립트 파일은 아키텍쳐별로 구성
  • .dts
    • 특정보드에서 실제로 어떻게 활용할 것인지 (활성화 여부, 핀 연결)을 정의
  • .dtsi
    • 칩셋의 기본값을 정의
    • UART 컨트롤러의 주소, 레지스터 정보 등 변하지 않는 정보
  • .dtb
    • 실제 로드되는 파일

2. 디바이스 트리 - 커널 동작 관계 분석

  1. 정보 제공 (디바이스 트리)
    • 존재 유무 : gmac0 노드의 status = “okay”를 통해 이더넷 컨트롤러가 존재, 활성화
    • 위치 : reg 속성을 통해 이더넷 컨트롤러의 물리적 메모리 주소 알려줌
    • 연결 정보 : pinctrrl을 통해 이더넷 컨트롤러가 칩
  2. 동작 실행 (커널)
    • 드라이버 매칭 : 노드에서 compatible 속성을 읽고, 자신과 호환된다는 것을 확인
    • 하드웨어 제어 : 디바이스 트리에서 읽어온 reg 주소와 interrupts 정보를 사용하여 이더넷 통신을 시작

3. 디바이스 트리 데이터포맷

전체 데이터 포맷

/dts-v1/;

/ {
    node1 {
        a-string-property = "A string";
        a-string-list-property = "first string", "second string";
        // hex is implied in byte arrays. no '0x' prefix is required
        a-byte-data-property = [01 23 34 56];
        child-node1 {
            first-child-property;
            second-child-property = <1>;
            a-string-property = "Hello, world";
        };
        child-node2 {
        };
    };
    node2 {
        an-empty-property;
        a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
        child-node1 {
        };
    };
};
  • 단일 루드 노드 : “ /
  • 두 개의 자식 노드 “node1” 및 “node2
  • node1에 대한 두 개의 하위 항목 : “child-node1” 및 “child-node2
  • 트리를 통해 흩어져 있는 많은 속성

4. 디바이스 트리 경로

  • MA35D1 Yocto Build의 경우 외부 git에서 source code를 clone해서 build하고 있음
  • Yocto Recipes File에서 리눅스 커널을 어떻게 빌드할 지에 대한 정보를 담고 있음
    • /home/smjeon/yocto/sources/meta-ma35d1

      recipe-core  recipe-devtools  recipes-graphics  recipes-image  recipes-kernel ...
    • /home/smjeon/shared/yocto/sources/meta-ma35d1/recipes-kernel/linux/linux-ma35d1_5.4.181.bb

      # Copyright (C) 2019-2020
      # Copyright 2019-2020 Nuvoton
      # Released under the MIT license (see COPYING.MIT for the terms)
      
      SUMMARY = "Linux Kernel provided and supported by Nuvoton"
      DESCRIPTION = "Linux Kernel provided and supported by Nuvoton ma35d1"
      
      inherit kernel
      
      # We need to pass it as param since kernel might support more then one
      # machine, with different entry points
      ma35d1_KERNEL_LOADADDR = "0x80080000"
      KERNEL_EXTRA_ARGS += "LOADADDR=${ma35d1_KERNEL_LOADADDR}"
      
      LICENSE = "GPLv2"
      LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
      
      SRCBRANCH = "linux-5.4.y"
      LOCALVERSION = "-${SRCBRANCH}"
      
      KERNEL_SRC ?= "git://github.com/OpenNuvoton/MA35D1_linux-5.4.y.git;protocol=https"
      SRC_URI = "${KERNEL_SRC}"
      
      SRC_URI += " \
          file://optee.config \
          file://cfg80211.config \
          "
      
      SRC_URI += "${@bb.utils.contains('DISTRO_FEATURES', '88x2bu', ' file://88x2bu.ko', '', d)}"
      
      SRCREV="${KERNEL_SRCREV}"
      S = "${WORKDIR}/git"
      B = "${WORKDIR}/build"
      
      DEPENDS += "openssl-native util-linux-native libyaml-native"
      DEFAULT_PREFERENCE = "1"
      # =========================================================================
      # Kernel
      # =========================================================================
      # Kernel image type
      KERNEL_IMAGETYPE = "Image"
      
      do_configure_prepend() {
          bbnote "Copying defconfig"
          cp ${S}/arch/${ARCH}/configs/${KERNEL_DEFCONFIG} ${WORKDIR}/defconfig
          cat ${WORKDIR}/cfg80211.config >> ${WORKDIR}/defconfig
      
          if ${@bb.utils.contains('MACHINE_FEATURES', 'optee', 'true', 'false', d)}; then
              cat ${WORKDIR}/optee.config >> ${WORKDIR}/defconfig
          fi
      }
      
      do_deploy_append() {
          for dtbf in ${KERNEL_DEVICETREE}; do
              dtb=`normalize_dtb "$dtbf"`
              dtb_ext=${dtb##*.}
              dtb_base_name=`basename $dtb .$dtb_ext`
              ln -sf $dtb_base_name.dtb ${DEPLOYDIR}/Image.dtb
          done
      }
      
      do_install_append() {
          if [ -e ${WORKDIR}/88x2bu.ko ]; then
              install -d ${D}/${base_libdir}/modules/${PV}
              install -m 0644 ${WORKDIR}/88x2bu.ko ${D}/${base_libdir}/modules/${PV}/88x2bu.ko
          fi
      }
      
      FILES_${PN} += "${base_libdir}/modules/${PV}/${@bb.utils.contains('DISTRO_FEATURES', '88x2bu', '88x2bu.ko', '', d)}"
      COMPATIBLE_MACHINE = "(ma35d1)"
  • .dts 경로
    • /home/smjeon/shared/yocto/build/tmp-glibc/work/numaker_som_ma35d16a81-poky-linux/linux-ma35d1/5.10.140-r0/git/arch/arm64/boot/dts/nuvoton
    • Docker에서 build하였기 때문에 git directory 에 접근 하지 못함

5. 디바이스 트리 문법 구조

  • 하드웨어의 논리적 구조를 계층적인 텍스트로 표현

  • 구성
    • 문법 구조

  • 노드(Node) : 하드웨어 장치 하나하나를 나타내는 기본 단위 (최상위 노드는 슬래시(/)로 표현
    • 속성(Property) : 노드에 포함된 키(key)와 값(value)의 쌍
    • competible = “제조사, 모델명” : 장치와 호환되는 드라이버를 커널이 찾을 수 있도록 도움
      • reg = <주소 크기> : 장치의 물리적 메모리 주소와 그 크기를 나타냄
      • status = “okay” 또는 “disable” : 장치의 활성화 상태를 나타냄
      • 레이블(Label) : 노드에 붙이는 별명. 엠퍼센트와 사용되어 다른 노드에서 해당 노드를 참조
    • 루트노드(/)
      • competible = “보드 명”
      • #address-cells = <2> 주소와 크기를 64비트로 표현
    • CPU 및 코어 하드웨어
      • competible
      • reg : 코어 들의 ID
    • 주변 장치 및 I/O 컨트롤러
      • ciompetible
      • reg : UART의 물리적 레지스터 주소
      • status
    • 핀 컨트롤
      • 노드 : GPIOA라는 GPIO 뱅크를 정의
      • gpio-controller, interrupt-controller 데이터 개수 정의
      • 특정 핀의 전기적 특성을 정의 하는 노드 (ex. pcfg_default, pcfg_emac_1_8V)

결론 (디바이스 트리 수정 방법)

  • Yocto의 .bbappend 파일 사용
    • meta-layer/recipe-kernel/linux 디렉토리에 <보드명>.bbappend 와 같은 파일 생성
    • 이 파일에 SRC_URI += file://<보드명>.dts" 와 같이 새로운 <보드명>.dts 파일 추가하고, FILESEXTRAPATHS_prepend := "${DIR}/${PN}:"을 설정하여 빌드 시스템이 이 파일을 인식할 있도록 함
  • 소스 코드 직접 수정 및 git 패치생성
    • 로컬 소스 수정 : .dts 파일을 열어 수정

    • git patch 생성 : 변경 사항을 git 패치 파일로 만듦

      • git add arch/arm64/boot/dts/
      • git commit -m "Add my dts changes"
      • git format-patch HEAD-1
    • 패치 적용 : 생성된 패치 파일을 Yocto 레시피에 추가하여 다음에 빌드할 때 자동으로 수정사항 적용토록 함

profile
Embedded Junior Developer

0개의 댓글