2026년 3월 4일 수요일

Embedded Linux Programming with STM32MP257F-DK board(Special Episode)

거의 6년만에 STM32MP 보드를 다시 하나 입수했다(이번에는 STM32MP257F-DK 보드다). 이번 시간 부터는 앞으로 몇차례에 걸쳐서, STM32MP257F-DK 보드 기반 embedded linux와 관련한 다양한 주제를 다뤄 보고자 한다. 😎

 
The special episode

목차
3. STM32MP257F-DK 보드 Device Tree 상세 분석
4. STM32MP257F-DK 보드 Booting Flow 상세 분석
5. OpenSTLinux Yocto Project 기반 Booting Image 생성하기
6. Yocto Project devtool 소개하기
7. Linux Kernel and Bootloader
8. Buildroot 기반 booting image 생성하기
9. Rust Kernel Programming
10. Cortex-M33 CPU#1 - STM32CubeIDE 기반 Application 돌려 보기
11. Cortex-M33 CPU#2 - Zephyr RTOS Application 돌려보기
12. WireGuard Rust 돌려 보기
13. Qt6 Application 돌려 보기 - C++ or PySide6
References 

KeywordsSTM32MP257F-DK, booting flow, u-boot, linux kernel, device tree, yocto project, Buildroot, Rust kernel module, STM32CubeIDE, Zephyr RTOS, PySide6

Embedded linux(echosystem)는 점점 더 복잡해져 가고 있다. 이중 삼중의 bootloader(거기에 TrustZone까지), device tree로 무장한 linux kernel, kernel에 합류한 Rust, build system의 대세 Yocto project ! 어느 하나 무시할 수 없는 것들 뿐이다. 이번 시간에는 STM32MP257F-DK board에 대한 이해를 돕기 위하여 Device Tree와 Booting flow에 관해 상세 분석한 내용을 소개해 보도록 하겠다. 😋


Embedded Linux의 꽃 ? device tree ㅋㅋ


3. STM32MP257F-DK 보드의 Linux Device Tree 상세 분석

임베디드 리눅스 환경에서의 STM32MP257F-DK 및 Device Tree의 아키텍처적 위상

현대의 복잡한 임베디드 리눅스 시스템 설계에 있어서 하드웨어의 물리적 구성과 커널의 소프트웨어 드라이버를 분리하는 것은 시스템의 이식성과 유지보수성을 확보하는 핵심적인 패러다임이다. 이러한 목적을 달성하기 위해 도입된 데이터 구조가 바로 Device Tree이며, 시스템 부팅 시 부트로더(예: TF-A, U-Boot)에 의해 메모리에 적재되어 리눅스 커널로 전달된다. STMicroelectronics가 출시한 STM32MP257F-DK(Discovery Kit)는 64비트 아키텍처 기반의 듀얼 코어 Arm Cortex-A35와 실시간 제어를 위한 32비트 Arm Cortex-M33 코어를 단일 실리콘 다이(Die)에 통합한 고성능 이기종 멀티코어 프로세서(MPU)인 STM32MP257F를 탑재한 공식 레퍼런스 플랫폼이다.1


[그림 3.1] STM32MP25xC/F block diagram
[출처 - STM32MP251C/F STM32MP253C/F, STM32MP255C/F, STM32MP257C/F Datasheet]


[그림 3.2] stm32mp23_25xx interconnect top view
[출처 - RM0457 Reference manual, STM32MP23/25xx advanced Arm®-based 32/64-bit MPUs]

이러한 고도의 이기종 컴퓨팅 환경에서는 리눅스 커널이 처리해야 할 하드웨어 리소스의 방대함이 기존 마이크로컨트롤러(MCU)와는 비교할 수 없을 정도로 복잡하다. STM32MP257F-DK 보드는 4GB 용량의 고속 LPDDR4 메모리를 비롯하여, eMMC 8GB 스토리지, 시스템 전원을 정밀하게 제어하는 STPMIC25 전원 관리 IC, 기가비트 이더넷(RGMII), USB 3.0 DRD(Dual-Role Data), Wi-Fi 및 Bluetooth Low Energy 연결성을 포괄적으로 제공한다.1 뿐만 아니라 멀티미디어 서브시스템 측면에서는 디스플레이 출력을 위한 MIPI DSI, LVDS 인터페이스 및 외부 모니터 연결을 위한 DSI to HDMI 브릿지가 장착되어 있으며, 비디오 캡처를 위한 듀얼 레인 MIPI CSI-2 카메라 커넥터를 구비하고 있다.1


[그림 3.3] stm32mp257-dk board block diagram
[출처 - UM3385 - Discovery kit with STM32MP257F MPU - User manual, STMicroelectronics.]

이처럼 방대하고 복잡한 물리적 하드웨어 토폴로지를 리눅스 커널이 정확하게 파악하고 적절한 커널 모듈(드라이버)을 동적으로 로드할 수 있도록 설계된 청사진이 바로 stm32mp257f-dk.dts 소스 파일이다. 리눅스 커널 소스 트리의 arch/arm64/boot/dts/st/ 경로에 존재하는 이 파일은 단일 텍스트 파일 구조로 작성되지 않으며, 실리콘 벤더가 제공하는 공통 SoC(System on Chip) 계층 정의 파일(.dtsi)과 상수 및 매크로를 제공하는 C 헤더 파일(.h)들을 객체 지향 프로그래밍의 상속(Inheritance)과 유사한 방식으로 광범위하게 포함(Include)하여 완성된다.5 이번 포스팅에서는 stm32mp257f-dk.dts 최상위 파일을 기준으로, 해당 파일이 포함하는 SoC 계층 구조 파일들, 핀 멀티플렉싱(Pinctrl) 설정, 디스플레이 서브시스템(DSI, LVDS, HDMI) 및 카메라(CSI) 구성, 그리고 하드웨어 추상화를 돕는 헤더 파일들의 내용과 상호 연관성을 시스템 아키텍처 관점에서 포괄적으로 분석한다.

최상위 보드 파일과 계층적 Include 구조의 설계 철학

임베디드 리눅스의 Device Tree는 하드웨어의 재사용성을 극대화하기 위해 파일 간의 포함(Include) 메커니즘을 적극적으로 활용한다. 최상위 보드 파일인 .dts 파일은 특정 물리적 인쇄 회로 기판(PCB)의 특화된 결선 상태를 나타내며, 칩셋 내부에 집적된 IP(Intellectual Property) 블록들은 .dtsi (Device Tree Source Include) 파일로 분리되어 다양한 파생 보드에서 재사용된다.7 STM32MP25 계열 프로세서의 경우, 실리콘 다이 하나를 기반으로 기능 활성화 수준에 따라 여러 제품군(STM32MP251, 253, 255, 257)으로 분류되어 시장에 공급되므로, Device Tree 구조 역시 이 하드웨어 등급에 맞추어 매우 깊은 계층적 상속 트리를 형성하고 있다.9

이러한 상속 트리의 정점에 위치한 stm32mp257f-dk.dts는 하위 계층에서 정의된 하드웨어 리소스를 선택적으로 활성화하고 물리적 보드 환경에 맞게 재정의하는 오버라이딩(Overriding)의 주체이다.

linux-stm32mp/arch/arm64/boot/dts/st/stm32mp257f-dk.dts

[그림 3.4] stm32mp257f-dk.dts 파일

[그림 3.5] stm32mp257f-dk board device tree 계층 구조

------------------------------------------------------------------------

구체적인 파일 포함 계층과 각 파일이 담당하는 시스템 아키텍처 영역은 다음과 같이 엄격하게 분리되어 있다.

포함 파일 (Include File)

계층 위상 및 성격 (Hierarchy & Nature)

핵심 하드웨어 기술 내용 및 커널 내 역할 (Core Contents & Role)

stm32mp257f-dk.dts

최상위 보드 계층 (Top-Level Board)

외부 주변기기 활성화(status = "okay"), 메모리 용량 매핑, I2C/SPI 버스에 연결된 외부 센서 및 칩셋(PMIC, HDMI 브릿지 등), 디스플레이 패널 타이밍, 전원 토폴로지 등 물리적 보드의 최종 결선 상태를 정의한다.6

stm32mp25xxai-pinctrl.dtsi

패키지 특화 핀 제어 (Package Pin Control)

칩셋의 물리적 패키지(예: AI3 등 BGA 패키지 유형)에 따라 외부로 인출되는 핀의 종류와 개수가 다르므로, 특정 패키지에 종속적인 핀 라우팅 제약 사항과 멀티플렉싱 그룹을 정의한다.6

stm32mp25-pinctrl.dtsi

공통 핀 제어 계층 (Common Pin Control)

SoC 내부에 존재하는 수백 개의 GPIO 핀에 대한 멀티플렉싱(Alternate Function) 구성 및 전기적 특성(풀업, 풀다운, 슬루 레이트 등)을 정의한다.13 보드 파일은 여기서 정의된 핀 노드를 참조하여 통신 인터페이스를 구성한다.

stm32mp25xf.dtsi

보안 및 서브시스템 패키지 (Security/Subsystem)

특정 파생 모델에 포함되는 암호화 가속기나 특수 하드웨어 블록의 파라미터를 규정하여 상위 노드에 병합한다.3

stm32mp257.dtsi

최상위 SoC 계층 (Top SoC Tier)

하위의 stm32mp255.dtsi를 포함하며, STM32MP25 계열 중 가장 높은 티어의 기능인 고급 디스플레이, 하드웨어 비디오 인코더/디코더, 이더넷 스위치 제어 로직 등을 시스템 버스에 추가한다.8

stm32mp255.dtsi

하위 SoC 계층 (Mid SoC Tier)

하위의 stm32mp253.dtsi를 포함하며, 3D 그래픽 처리를 위한 GPU, 인공지능 연산을 가속하는 NPU 등 멀티미디어 및 AI 가속 연산 장치를 시스템 맵에 추가한다.10

stm32mp253.dtsi

하위 SoC 계층 (Low SoC Tier)

하위의 stm32mp251.dtsi를 포함하며, 기본 단일 코어 환경에 두 번째 Arm Cortex-A35 코어를 추가로 선언하고, 듀얼 코어 간의 캐시 일관성 및 인터럽트 라우팅 설정을 정의한다.9

stm32mp251.dtsi

기본 SoC 계층 (Base SoC Tier)

단일 Cortex-A35 코어를 기반으로 GIC(인터럽트 컨트롤러), 시스템 타이머, RIFSC(Resource Isolation Framework Secure Controller) 시스템 버스 아키텍처, 그리고 I2C, UART, SPI, ADC, 기본 타이머 등 칩셋에 내장된 거의 모든 하드웨어 IP의 메모리 베이스 주소(Base Address)와 인터럽트 번호를 정의한다.9


이러한 깊은 재귀적 포함(Recursive Inclusion) 구조는 하드웨어 파편화를 극복하기 위한 리눅스 커널 커뮤니티의 모범 사례를 철저히 따른 결과이다. 예컨대, 리눅스 커널 개발자는 STM32MP25 계열의 새로운 커스텀 보드를 설계할 때, 복잡한 내부 버스 주소나 인터럽트 맵을 바닥부터 새로 작성할 필요가 없다. 단지 최상위 .dts 파일에서 공통 .dtsi 파일들을 #include 지시어로 불러온 뒤, 해당 커스텀 보드에 실제로 결선된 I2C 포트나 이더넷 포트의 노드만 찾아서 status = "okay"로 변경하고 핀 멀티플렉싱만 재지정하면 완전히 동작하는 커널 하드웨어 트리를 얻을 수 있다.16 하위 계층인 stm32mp251.dtsi에 정의된 대부분의 컨트롤러 노드들이 기본적으로 status = "disabled" 상태로 선언되어 있는 것은 바로 이러한 안전하고 명시적인 활성화(Opt-in) 정책을 강제하기 위함이다.16 이는 사용하지 않는 IP 블록에 커널 드라이버가 바인딩되는 것을 원천 차단하여 메모리를 절약하고 예기치 않은 하드웨어 충돌과 전력 낭비를 방지하는 효과를 제공한다.

C 헤더 파일과 매크로 바인딩을 통한 하드웨어 추상화 메커니즘

Device Tree 파일(.dts 및 .dtsi)은 근본적으로 JSON이나 XML과 유사한 계층적 속성-값(Property-Value) 쌍을 가지는 텍스트 기반 데이터 구조이다. 그러나 이 파일은 커널 빌드 과정에서 DTC(Device Tree Compiler)라는 전용 도구를 통해 머신 리더블(Machine-readable)한 이진 포맷인 DTB(Device Tree Blob)로 컴파일된다.16 이 컴파일 과정 이전에 파일들은 C 전처리기(C Preprocessor, CPP)를 거치게 되는데, 이를 통해 일반적인 C 언어 프로그래밍에서 사용하는 #include 지시어와 매크로 상수를 Device Tree 내에서도 그대로 활용할 수 있게 된다.16

stm32mp257f-dk.dts 및 관련 .dtsi 파일들의 최상단에는 리눅스 커널의 include/dt-bindings/ 디렉토리에 위치한 다수의 C 헤더 파일들이 포함되어 있다.6 이 헤더 파일들의 목적은 하드웨어 데이터 시트에 기재된 복잡한 레지스터 오프셋이나 매직 넘버(Magic Number)를 사람이 읽고 이해하기 쉬운 문자열 매크로로 치환하여, 리눅스 커널 C 드라이버 소스 코드와 Device Tree 간의 식별자를 일치(Synchronization)시키는 데 있다.


참조 헤더 파일 경로 (Header File Path)

매크로 정의 목적 및 서브시스템 (Purpose & Subsystem)

실무 적용 및 커널 구동 메커니즘 (Application & Mechanism)

<dt-bindings/gpio/gpio.h>

범용 입출력(GPIO) 핀의 논리적 활성화 상태 및 물리적 토폴로지 정의

하드웨어 핀이 High 상태일 때 활성화될지(GPIO_ACTIVE_HIGH), Low 상태일 때 활성화될지(GPIO_ACTIVE_LOW)를 지정한다. 패널 백라이트, 리셋 핀, 인터럽트 트리거 조건 등 보드의 디지털 신호 흐름 방향을 커널 GPIO 서브시스템에 명확히 전달한다.6

<dt-bindings/clock/stm32mp25-clks.h>

SoC 내부 클럭 트리의 발전기 및 분배기 노드 고유 식별자 정의

CK_SCMI_HSE, CK_BUS_I2C1, CK_KER_LTDC 등 칩셋 내부에 존재하는 수백 개의 클럭 라인에 대한 고유 인덱스를 제공한다. 커널의 공통 클럭 프레임워크(CCF)는 이 매크로를 참조하여 특정 디바이스 드라이버가 요청하는 주파수를 동적으로 계산하고 클럭 게이팅(Gating)을 제어한다.20

<dt-bindings/clock/stm32mp25-clksrc.h>

클럭 소스 선택기 및 멀티플렉서 제어 매크로

MUX_MUXSEL5, MUXSEL_HSE 등 특정 IP 블록이 시스템 클럭을 사용할지, 외부 크리스탈 오실레이터(HSE) 클럭을 사용할지 결정하는 스위칭 식별자이다. 이는 PLL(Phase-Locked Loop) 주파수 동기화 및 CPU 주파수 스케일링 설정 시 필수적으로 사용된다.20

<dt-bindings/reset/stm32mp25-resets.h>

특정 IP 블록의 하드웨어 리셋 라인 식별자

소프트웨어 드라이버가 초기화 과정이나 에러 복구 시 특정 서브시스템(예: I2C 컨트롤러, 디스플레이 파이프라인)만을 독립적으로 초기화할 수 있도록 리셋 컨트롤러 프레임워크에 리셋 라인 번호를 전달한다.20

<dt-bindings/regulator/st,stm32mp25-regulator.h>

전원 레귤레이터의 상태 및 동작 모드 매크로 지정

보드에 실장된 PMIC의 출력 전압 채널을 제어할 때 사용되며, 시스템이 대기 모드에 진입할 때 전원을 차단할지 켤지 등의 전원 트리 활성/대기 모드 전환 플래그를 제공한다.6


이러한 매크로 바인딩 기법은 Device Tree의 가독성을 비약적으로 향상시킨다. 예를 들어, 특정 인터럽트의 트리거 방식을 지정할 때 <&exti1 68 4>라고 작성하면 마지막 파라미터 4가 무엇을 의미하는지 직관적으로 알 수 없으나, 헤더를 포함하여 <&exti1 68 IRQ_TYPE_LEVEL_HIGH>로 표기함으로써 커널 개발자는 데이터 시트를 뒤적이지 않고도 해당 인터럽트가 High 레벨 트리거 방식임을 즉시 파악할 수 있다.11 STM32MP257F-DK 보드의 구성을 정의하는 stm32mp257f-dk.dts 파일 전반에 걸쳐 이러한 헤더 매크로들이 조화롭게 배치되어, 하드웨어의 복잡한 타이밍과 전압, 상태 제어 요구사항을 리눅스 커널의 다양한 프레임워크에 오류 없이 전달하는 가교 역할을 성공적으로 수행하고 있다.

Pinctrl 서브시스템과 GPIO 멀티플렉싱 및 전력 최적화 전략

마이크로프로세서는 내부적으로 수백 가지의 통신 및 제어 기능을 내장하고 있으나, 물리적인 패키지의 핀 수는 제한되어 있다. 따라서 하나의 물리적 핀은 소프트웨어 설정에 따라 일반적인 입출력(GPIO) 역할뿐만 아니라 I2C의 데이터 선(SDA), SPI의 클럭 선(SCK), 디스플레이 픽셀 데이터 출력 등 다양한 대체 기능(Alternate Function, AF)을 수행할 수 있도록 멀티플렉싱(Multiplexing) 구조로 설계된다. STM32MP257F-DK 보드의 Device Tree 아키텍처에서 이러한 복잡한 핀 매핑 규칙은 주로 stm32mp25-pinctrl.dtsi 파일과 패키지에 종속적인 stm32mp25xxai-pinctrl.dtsi 파일에 의해 완벽하게 추상화된다.6

[그림 3.6]  stm32mp25-pinctrl.dtsi 파일


이 핀 제어 파일들은 리눅스 커널의 Pinctrl (Pin Control) 서브시스템에 의해 로드되어 해석된다. 커널 드라이버가 특정 하드웨어 노드(예: 카메라 인터페이스나 디스플레이 패널)를 Probe하여 초기화할 때, Pinctrl 서브시스템은 Device Tree에 기술된 핀 그룹 정의를 참조하여 프로세서의 멀티플렉서 레지스터를 실시간으로 조작함으로써 물리적 핀의 역할을 결정짓는다.13


노드 구조 및 명명 규칙 (Node & Naming)

핀 상태 (Pin State)

역할 및 전원 관리 최적화 시사점 (Role & Power Optimization)

ltdc_pins_a: ltdc-0 22

default (활성 상태)

디스플레이 컨트롤러(LTDC)가 정상적으로 동작할 때 할당되는 핀 구성 그룹이다. 예를 들어 <STM32_PINMUX('D', 9, AF11)>이라는 매크로를 통해 포트 D의 9번 핀을 Alternate Function 11(디스플레이 데이터 라인)로 정확히 스위칭하도록 지시한다.22

dcmipp_sleep_pins_a: dcmi-sleep-0 13

sleep (절전 상태)

시스템이 서스펜드(Suspend) 모드에 진입하거나 카메라 인터페이스가 장시간 유휴 상태일 때 적용된다. 핀의 상태를 입출력이 차단된 ANALOG 모드로 전환하도록 지시하여, 디지털 스위칭으로 인한 동적 전력 소모와 누설 전류(Leakage Current)를 극단적으로 억제하는 고도의 전력 관리 최적화 기법을 제공한다.13

eth1_mdio_pins_a 8

통신 제어 특화

고속으로 스위칭되는 이더넷 PHY 제어 인터페이스(MDIO)를 위한 핀 그룹이다. 신호 무결성(Signal Integrity)을 보장하기 위해 단순히 핀을 할당하는 것에 그치지 않고, 슬루 레이트(Slew Rate) 속도 조절 및 풀업(Pull-up)/풀다운(Pull-down) 저항 상태까지 상세히 제어한다.


stm32mp257f-dk.dts 보드 파일에서는 각 서브시스템 노드 내부에 pinctrl-names = "default", "sleep";과 같이 사용할 상태의 이름을 선언하고, pinctrl-0 = <&ltdc_pins_a>;, pinctrl-1 = <&ltdc_sleep_pins_a>;와 같이 stm32mp25-pinctrl.dtsi에 정의된 핀 그룹 라벨을 포인터 참조형으로 바인딩한다.8 이러한 설계는 디바이스 드라이버 소스 코드 내부에 하드웨어 종속적인 핀 조작 코드를 전혀 포함하지 않고도, 커널의 전원 관리 프레임워크(PM Framework)가 장치의 상태 변이에 맞추어 자동으로 핀 상태를 변경할 수 있도록 하는 매우 우수하고 유연한 아키텍처를 완성한다.

디스플레이 서브시스템 파이프라인 분석: LTDC, LVDS, DSI 및 HDMI Bridge

STM32MP257F-DK 보드에서 구현된 가장 복잡하면서도 정교한 서브시스템 중 하나는 단연 디스플레이 출력 파이프라인이다. 이 시스템은 리눅스 커널의 DRM(Direct Rendering Manager) 및 KMS(Kernel Mode Setting) 프레임워크를 기반으로 동작한다.22 하드웨어 내부의 디스플레이 컨트롤러인 LTDC(LCD-TFT Display Controller)가 메모리 상의 프레임 버퍼를 읽어 들여 생성한 픽셀 데이터가 어떠한 물리적 변환 과정을 거쳐 최종 커넥터(LVDS 패널, HDMI 모니터 등)로 전달되는지에 대한 데이터 흐름은 Device Tree의 OF-Graph(Open Firmware Graph) 모델을 통해 시각적으로, 그리고 논리적으로 정의된다.22 OF-Graph는 데이터를 전송하는 port와 데이터의 방향성을 나타내는 endpoint 노드를 이용하여 복잡한 비디오 파이프라인을 그래프 구조로 모델링한다.

[그림 3.7]  stm32mp257f-dk.dts 내용 중 ltdc node 부분 발췌

1. LVDS 네이티브 패널 인터페이스 파이프라인

STM32MP257F-DK 보드는 디스플레이 확장을 위해 4-Lane LVDS(Low-Voltage Differential Signaling) 커넥터를 네이티브로 제공한다.1 디바이스 트리의 &lvds 노드는 이 파이프라인의 중심 허브 역할을 한다.22 LTDC 디스플레이 컨트롤러의 첫 번째 출력은 내부 버스를 통해 이 LVDS PHY 블록으로 라우팅된다. OF-Graph 상에서 LTDC의 송신 엔드포인트(ltdc_ep1_out)는 &lvds 노드의 수신 포트에 속한 lvds_in 엔드포인트와 화살표처럼 서로를 가리키며 논리적으로 결선된다.22 신호를 수신한 LVDS 블록은 이를 다시 패널 방향으로 송출하기 위해 두 번째 포트에 lvds_out0 엔드포인트를 선언한다.22 최종적으로 물리적인 액정 패널의 해상도, 타이밍 동기화 신호(Hsync, Vsync), 물리적 크기 및 백라이트 제어 정보 등은 panel_lvds라는 패널 전용 노드에 상세히 기술된다.6 DRM 프레임워크는 부팅 시 이 그래프를 탐색하여 LTDC -> LVDS PHY -> 패널로 이어지는 완전한 체인을 구성하고, clk_pix_lvds 등의 픽셀 클럭 주파수를 패널이 요구하는 타이밍에 맞추어 역산하여 클럭 트리 서브시스템에 주파수 생성을 요청한다.23

[그림 3.8]  stm32mp257f-dk.dts 내용 중 lvds node 부분 발췌

2. DSI to HDMI 변환 브릿지 파이프라인

더욱 흥미로운 아키텍처는 보드에 탑재된 HDMI 커넥터를 구동하는 방식이다. STM32MP257F SoC는 네이티브 HDMI 출력 IP를 내장하고 있지 않으므로, MIPI DSI(Display Serial Interface) 신호를 HDMI 신호로 변환해주는 외부 브릿지 칩셋(보통 Analog Devices 사의 ADV7533 또는 ADV7535)을 활용하여 이 기능을 구현한다.1

[그림 3.9]  stm32mp257f-dk board schematics - HDMI bridge adapter 부분
[출처 - STM32MP257-DK schematic, STMicroelectronics.]

이 이기종 칩셋 간의 결합 역시 OF-Graph를 통해 완벽하게 해결된다.

  • 먼저, SoC 내부의 MIPI DSI 컨트롤러 출력 엔드포인트(dsi_out)가 선언된다.24

  • I2C 버스 아래에 외부 브릿지 칩인 adv7533 (또는 adv7535) 노드가 status = "okay"로 활성화된다.24

  • 이 브릿지 노드 내부에는 수신을 위한 adv7533_in 엔드포인트가 선언되어 dsi_out과 상호 참조를 맺는다. 브릿지 칩은 2개의 MIPI DSI 데이터 레인(adi,dsi-lanes = )을 사용하여 고속의 직렬 비디오 신호를 수신하도록 설정된다.24

  • 변환된 비디오 데이터는 브릿지 칩의 두 번째 포트에 선언된 adv7533_out 엔드포인트를 거쳐 최종적으로 hdmi_con (물리적 HDMI 커넥터를 추상화한 노드)으로 라우팅된다.24

이러한 정교한 그래프 구조는 커널의 DRM 브릿지 프레임워크가 초기화 순서를 정확히 제어할 수 있게 한다. I2C 제어 버스를 통해 브릿지 칩에 접근한 커널은 외부 모니터의 EDID(Extended Display Identification Data)를 읽어와 해상도를 협상하고, 이 요구사항을 파이프라인을 거슬러 올라가 DSI 컨트롤러와 LTDC에 전달하여 ck_dsi_phyck_ker_ltdc 클럭 스위칭 로직이 정확한 타이밍 신호를 생성하도록 지휘한다.23

[그림 3.10]  stm32mp257f-dk.dts 내용 중 adv7535(hdmi bridge) node 부분 발췌

카메라 및 비디오 입력 서브시스템: MIPI CSI-2 및 DCMIPP

STM32MP257F-DK 보드의 비디오 캡처 파이프라인은 리눅스 커널의 강력한 V4L2(Video for Linux 2) 프레임워크와 그 하위의 Subdev(서브디바이스) 아키텍처를 기반으로 완벽하게 통합되어 있다. 보드에는 고해상도 이미지 센서를 연결할 수 있는 듀얼 레인(2 Data lanes) 규격의 MIPI CSI-2 카메라 커넥터가 장착되어 있으며 1, 카메라 모듈에서 유입된 고속의 직렬 픽셀 데이터는 SoC 내부의 CSI 수신기 블록을 거쳐 최종적으로 DCMIPP(Digital Camera Memory Interface Pixel Processor) 블록에 의해 시스템 메모리(RAM)로 직접 DMA 전송되어 저장된다.13

[그림 3.11] STM32MP25xC/F block diagram 내용 중, CSI, DCMIPP block
[출처 - STM32MP251C/F STM32MP253C/F, STM32MP255C/F, STM32MP257C/F Datasheet]


[그림 3.12]  stm32mp257f-dk.dts 내용 중 csi node 부분 발췌

이 데이터 파이프라인 역시 디스플레이 파이프라인과 마찬가지로 OF-Graph의 엔드포인트 방식을 철저히 준수하여 구성된다. stm32mp257f-dk.dts 및 관련 .dtsi 파일들에서는 물리적 장치 간의 계층적 구조를 다음과 같이 명확하게 분할하여 기술하고 있다.

  • 외부 이미지 센서 노드 (Sony IMX335 예시): 카메라 모듈의 초기화와 노출, 화이트 밸런스 등 제어 명령은 I2C 버스를 통해 이루어지므로, I2C 컨트롤러 노드 하위에 sony,imx335 호환성 문자열을 가진 자식 노드가 reg = <0x1a> (I2C 슬레이브 주소) 설정과 함께 선언된다.13 여기에는 센서 구동에 필요한 1.8V(ovdd-supply), 1.2V(dvdd-supply), 2.9V(avdd-supply) 등 다수의 전압 레귤레이터 핸들이 연결되며, 물리적 클럭 주파수(clocks = <&clk_ext_camera>)가 명시된다.6

  • MIPI CSI-2 데이터 버스 계층: 비디오 데이터 전송을 위해 센서 노드 내부에 OF-Graph port가 선언된다. MIPI D-PHY 물리 계층의 제어를 위해 클럭 레인은 번으로, 데이터 레인은 <1 2>번으로 할당됨(data-lanes = <1 2>)을 명시하여 논리적 레인의 순서가 꼬이지 않고 올바르게 데이터가 디코딩될 수 있도록 보장한다.13 또한, link-frequencies 속성을 통해 CSI 버스의 데이터 전송 대역폭 주파수 한계값(예: 594 MHz)을 커널 드라이버에 선언하여 위상 고정 루프(PLL)가 이 주파수를 넘지 않도록 안전을 기한다.13

  • DCMIPP 파이프라인 연결: 센서의 출력 엔드포인트(imx335_ep)는 상호 참조를 통해 SoC 내부의 CSI 수신기 블록 입력 엔드포인트(csi_sink)와 논리적으로 단단히 결속된다.13 CSI 수신 블록에서 오류 정정과 패킷 디코딩을 거쳐 병렬 데이터로 변환된 픽셀 스트림은 다시 내부 파이프라인을 타고 최종 목적지인 DCMIPP로 라우팅된다. 리눅스의 V4L2 드라이버는 부팅 시 이 그래프를 탐색하여 각각의 하드웨어 블록에 대한 Subdev 드라이버를 로드하고, 이들을 하나의 논리적 비디오 디바이스(예: /dev/video0)로 묶어 사용자 공간의 GStreamer나 카메라 애플리케이션이 손쉽게 프레임을 획득할 수 있는 환경을 조성한다.13

고속 네트워크 및 통신 인터페이스: 기가비트 이더넷과 USB 서브시스템

산업용 IoT 게이트웨이나 고급 멀티미디어 장비에서 네트워크 및 외부 장치 통신의 신뢰성은 시스템 전체의 안정성을 좌우하는 핵심 요소이다. STM32MP257F-DK 보드는 이러한 목적에 부합하도록 기가비트 이더넷 네트워크 인터페이스와 USB 3.0 및 2.0 허브 아키텍처를 포괄적으로 제공하며 1, 이 모든 구성은 리눅스 Device Tree를 통해 정밀하게 제어된다.

1. 기가비트 이더넷 (RGMII 및 MDIO 버스)

SoC 내부에 집적된 이더넷 MAC(Media Access Control) 컨트롤러는 널리 검증된 Synopsys의 DesignWare MAC IP를 기반으로 하며, 커널 내에서 st,stm32mp25-dwmacsnps,dwmac-5.10a 호환 드라이버에 의해 구동된다.11 최상위 보드 파일에서는 비활성화된 기본 이더넷 노드(&eth1 또는 &eth2)를 오버라이딩하여 활성화(status = "okay") 상태로 전환한다.8

[그림 3.13]  stm32mp257f-dk.dts 내용 중 eth1 node 부분 발췌

DK 보드 상의 이더넷 MAC은 외부 이더넷 트랜시버 칩(PHY)과 RGMII(Reduced Gigabit Media Independent Interface) 통신 규격으로 결선되어 있으므로, 디바이스 트리에 phy-mode = "rgmii" 속성을 명시적으로 선언하여 클럭 및 데이터 전송 타이밍을 맞춘다.8 더불어 PHY 칩의 링크 상태(Link Up/Down)와 속도(10/100/1000Mbps 자동 협상)를 커널이 실시간으로 모니터링하고 제어하기 위해 MAC 노드 하위에 MDIO(Management Data Input/Output) 버스 노드가 선언된다.8 특히 Realtek 사 등의 외부 PHY 칩이 부팅 초기에 불안정한 상태에 빠지는 것을 방지하기 위해, 리셋 제어를 담당하는 GPIO 핀 매핑(reset-gpios)과 함께 reset-assert-us, reset-deassert-us 등의 마이크로초 단위의 엄격한 리셋 타이밍 딜레이 파라미터를 Device Tree에 직접 기술하여, 드라이버가 하드웨어 스펙에 한 치의 오차도 없이 PHY를 초기화하도록 보장한다.8

2. USB 서브시스템 (USB 3.0 DRD 및 USB 2.0 Host Hub)

이 보드는 최신 산업 표준인 USB Type-C PD(Power Delivery) 규격을 지원하며, 연결된 케이블의 상태에 따라 디바이스(Peripheral) 모드와 호스트(Host) 모드를 자유롭게 넘나들 수 있는 USB 3.0 DRD(Dual-Role Data) 인터페이스를 구비하고 있다.1 또한 외부 주변기기 확장을 위해 자체적인 USB 2.0 Host Hub도 내장되어 2개의 Type-A 포트를 제공한다.1

이러한 USB 토폴로지를 구성하기 위해 Device Tree 내부에는 논리적인 USB 컨트롤러 노드뿐만 아니라 고속 신호 전송을 전담하는 물리 계층 노드(예: usb2_phy1)가 별도로 선언되어 바인딩된다.25 리눅스 커널의 USB 서브시스템은 이 설정을 바탕으로 드라이버를 로드하며, Type-C 커넥터 칩과 통신하는 Extcon(External Connector) 프레임워크를 통해 케이블 연결 방향을 감지하고 동적으로 DRD 컨트롤러의 역할을 전환시킨다. VBUS 전원 인가 및 외부 기기의 합선 시 시스템을 보호하기 위한 과전류(OVRCUR) 감지 핀 역시 Pinctrl 노드를 통해 USB 서브시스템에 매핑되어 전기적 안정성을 철저히 담보한다.25

[그림 3.14]  stm32mp257f-dk.dts 내용 중 usb2_phy1,2 및 usbh node 부분 발췌

[그림 3.15]  stm32mp257f-dk.dts 내용 중 usb3dr(usb3.0 DRD) node 부분 발췌


메모리 버스, 전원 관리 및 직렬 통신 (DDR, PMIC, USART)

운영체제가 동작하기 위한 가장 기초적이고 핵심적인 하부 구조인 메모리 토폴로지, 전원 분배, 그리고 시스템 디버깅을 위한 시리얼 콘솔 환경 역시 모두 stm32mp257f-dk.dts 및 연관 파일들에 치밀하게 정의되어 있다.

1. 시스템 메모리 (LPDDR4) 및 컨트롤러 최적화

STM32MP257F-DK 보드에는 고속 데이터 처리와 저전력 특성을 동시에 만족시키는 4GB 용량의 LPDDR4 메모리가 탑재되어 있다.1 리눅스 커널이 이 방대한 물리적 메모리를 페이지 테이블로 매핑하고 관리할 수 있도록, 디바이스 트리 최상단에는 memory@80000000 노드가 선언되어 시스템 RAM의 물리적 베이스 주소(0x80000000)와 총 크기 범위 파라미터를 명시한다.6

흥미로운 점은 메모리 컨트롤러(DDRCTRL)와 물리 계층(DDRPHYC)의 복잡한 타이밍 캘리브레이션은 리눅스 커널이 부팅되기 훨씬 이전 단계인 부트로더(TF-A, Trusted Firmware-A)에서 전적으로 수행된다는 사실이다.27 TF-A 역시 자신만의 Device Tree를 사용하여 하드웨어를 파악하는데, 이때 vdd1-supply, vdd2-supply와 같이 LPDDR4 구동에 필수적인 레귤레이터 전압 소스 핸들을 참조하여 정확한 전원을 인가한 후 27, 수십 가지의 임피던스 및 타이밍 파라미터(st,phy-basic, st,phy-advanced 등)를 DDR 컨트롤러 레지스터에 주입하여 메모리 안정성을 확보한다.27 리눅스 커널은 이처럼 TF-A가 안전하게 초기화를 마친 메모리 영역을 그대로 이양받아 사용하게 되는 효율적인 분업 구조를 취한다.

2. 고집적 전원 관리 프레임워크 (STPMIC25 및 SCMI)

이기종 멀티코어 환경에서 수많은 인터페이스의 전력을 낭비 없이 제어하기 위해, 보드는 전담 전원 관리 IC인 STPMIC25를 채택하고 있다.1 STPMIC25는 I2C 버스를 통해 메인 프로세서와 제어 통신을 수행하므로, 디바이스 트리의 특정 I2C 컨트롤러 노드 하위에 자식 노드로 선언되어 커널의 레귤레이터 프레임워크(Regulator Framework)에 결합된다.6

[그림 3.16] stm32mp257-dk board power diagram
[출처 - UM3385 - Discovery kit with STM32MP257F MPU - User manual, STMicroelectronics.]

그러나 STM32MP2 아키텍처에서는 보안성과 전력 효율성을 극대화하기 위해 리눅스 커널이 PMIC를 직접 제어하는 것을 지양하고, SCMI(System Control and Management Interface) 프로토콜을 광범위하게 도입하였다. 즉, 전원 상태를 변경하거나 핵심 클럭을 조절하는 권한은 보안 코어 영역(OP-TEE 등)으로 이관되며, 리눅스 커널은 SCMI 드라이버를 통해 보안 영역에 가상적인 요청 메시지만을 전달하는 방식으로 동작한다.6 디바이스 트리에 선언된 &scmi_vddcore, &scmi_v1v8 등의 핸들 포인터가 바로 이러한 메일박스 통신 기반의 추상화된 전원 객체를 나타낸다.

[그림 3.17]  stm32mp257f-dk.dts 내용 중 scmi_regu(scmi regulator) node 부분 발췌

3. 직렬 통신 환경 (USART 및 Console)

리눅스 커널의 부팅 메시지 로깅과 초기 시스템 디버깅을 위한 시리얼 콘솔 환경은 chosen 노드에서 결정된다. stm32mp257f-dk.dts 파일의 chosen 노드에는 stdout-path = "serial0:115200n8"; 속성이 선언되어, 부팅 시 표준 출력 터미널이 초당 115200 비트의 전송 속도로 작동하도록 커널에 지시한다.6

여기서 serial0는 물리적 포트 식별자가 아니라, aliases 노드 블록에서 serial0 = &usart2; 또는 serial1 = &usart6;와 같이 선언된 논리적 별칭(Alias)이다.6 이 방식을 통해 커널은 복잡한 하드웨어 베이스 주소를 참조할 필요 없이, 일관된 논리적 디바이스 노드 이름(예: /dev/ttySTM0)을 생성하여 사용자 공간 애플리케이션에 제공한다. 또한, 고속 데이터 처리가 요구되는 USART 포트의 경우 CPU의 인터럽트 부하를 줄이기 위해 dmas 속성과 dma-names 속성을 디바이스 트리에 바인딩하여 백그라운드에서 하드웨어 DMA 컨트롤러가 송수신 버퍼를 직접 관리하도록 아키텍처 수준에서 최적화되어 있다.15

보안 프레임워크 (TrustZone, OP-TEE) 및 이기종 코어 (Cortex-M33) 격리 통신 아키텍처

STM32MP257F-DK 보드의 가장 차별화된 시스템 아키텍처 설계는 ARM TrustZone 하드웨어 격리 기술과 Cortex-M33 보조 프로세서를 활용한 이기종 코어 분할(Partitioning) 환경이다. 이는 범용 운영체제인 리눅스 커널의 권한을 엄격히 제한하고, 시스템의 루트 오브 트러스트(Root of Trust) 보안성 및 실시간 제어(Real-time) 응답성을 동시에 보장하기 위한 첨단 아키텍처이다. 이러한 복잡한 메모리 및 버스 격리 설정 역시 Device Tree의 하드웨어 리소스 할당 메커니즘을 통해 완벽하게 조정된다.

1. RIFSC 버스와 보안 영역(Secure World) 리소스 할당

시스템 전원을 켜면 리눅스 커널보다 훨씬 이전 단계에서 보안 부트로더인 TF-A와 보안 운영체제인 OP-TEE(Open Portable Trusted Execution Environment)가 먼저 실행된다. 이들은 보안 전용으로 분리된 Device Tree 영역을 독자적으로 파싱하여 자신들만이 배타적으로 소유할 보안 하드웨어 리소스를 할당받는다.30

STM32MP2 계열의 핵심적인 보안 버스 아키텍처인 RIFSC(Resource Isolation Framework Secure Controller)와 ETZPC(Extended TrustZone Protection Controller)는 특정 주변기기(예: 시스템 전원 제어용 I2C 버스, 하드웨어 난수 생성기, 특수 타이머 등)를 일반 리눅스 환경(Non-Secure World)에서 접근하거나 읽을 수 없도록 하드웨어적으로 완전히 마스킹(Masking) 처리한다.14 결과적으로 stm32mp257f-dk.dts 파일 구조는 리눅스 커널용 파일과 OP-TEE용 파일이 물리적으로는 동일한 구조의 파일을 상속받되, 보안 컴파일 플래그나 별도의 .dtsi 오버레이를 통해 특정 노드가 보안 영역 전용으로 바인딩되도록 유기적으로 설계되어 시스템 훼손(Tampering)을 원천 차단한다.30

[그림 3.18]  stm32mp251.dtsi 내용 중 rifsc node 부분 발췌

2. Cortex-M33 코어 구동을 위한 RemoteProc 프레임워크 통합

물리적 모터 제어나 센서 데이터 수집 등 마이크로초 단위의 엄격한 결정론적(Deterministic) 타이밍이 요구되는 태스크는 리눅스가 구동되는 Cortex-A35 코어가 아닌, 실시간 운영체제(RTOS)가 탑재되는 Cortex-M33 코어로 오프로딩(Off-loading)된다. 리눅스 커널은 이 M33 코어의 전원을 켜고 펌웨어(ELF 바이너리 포맷)를 동적으로 로드 및 제어하기 위해 remoteproc (Remote Processor) 서브시스템 프레임워크를 활용한다.31

이러한 제어 관계를 형성하기 위해 stm32mp257f-dk.dts (혹은 연관 파일)에는 Cortex-M33 코어의 추상화 객체인 m0_rproc 노드가 선언된다.31 이기종 코어들은 물리적으로 분리된 메모리 공간에서 동작하지만 데이터를 교환해야 하므로, 디바이스 트리 내부에 코어 간 통신(Inter-Processor Communication, IPC)을 전담할 하드웨어 메일박스(Mailbox) 컨트롤러의 인터럽트 라인과, 데이터를 임시로 저장할 전용 공유 메모리 영역(Shared Memory, memory-regions)의 주소 및 크기가 명시적으로 할당된다.31 이 구조를 통해 비보안 리눅스 환경과 보안 RTOS 환경은 하드웨어 기반의 스핀락(Spinlock) 세마포어를 통해 데이터 정합성을 유지하며, 메모리 충돌이나 교착 상태 없이 병렬로 안전하게 시스템을 통제할 수 있게 된다.

[그림 3.19]  stm32mp257f-dk.dts 내용 중 rproc node 부분 발췌

결론

STM32MP257F-DK 보드의 Linux Device Tree 아키텍처(stm32mp257f-dk.dts를 정점으로 하는 방대한 계층적 파일 트리)는 단순한 하드웨어 레지스터 목록이나 환경 설정 파일의 범주를 훨씬 뛰어넘는다. 이는 프로세서의 근본적인 실리콘 설계 사상부터 물리적인 보드 레벨의 핀 배선, 외부 컴포넌트 간의 전력 공급 인과 관계, 그리고 고수준 커널 서브시스템의 논리적인 데이터 흐름 파이프라인까지, 임베디드 시스템 전체의 동작 메커니즘을 객체 지향적인 그래프 모델로 완벽하게 묘사한 소프트웨어적 설계도이다.

첫째, .dtsi 파일들의 극도로 깊고 세분화된 상속 구조와 <dt-bindings/...> C 헤더 파일들을 활용한 매크로 연동 기법은, 소스 코드의 파편화를 근본적으로 차단하고 다양한 실리콘 패키지 변형 및 파생 제품들에 대해 타의 추종을 불허하는 수준의 이식성(Portability)과 유지보수성을 제공한다. 하드웨어의 물리적 파라미터를 커널의 C 드라이버 소스 코드에서 완전히 분리해 냄으로써, STMicroelectronics와 리눅스 커널 커뮤니티는 단일 커널 소스 트리 환경 내에서도 수십에서 수백 종에 이르는 이질적인 보드들을 충돌 없이 일관성 있게 구동하고 관리할 수 있는 탄탄한 아키텍처 기반을 확립하였다.

둘째, 디스플레이 서브시스템(LTDC-DSI-HDMI/LVDS)과 비디오 캡처 서브시스템(CSI-DCMIPP)의 설계에서 뚜렷하게 관찰할 수 있듯이, OF-Graph(Open Firmware Graph)를 활용한 portendpoint 구조는 이기종 하드웨어 칩셋들 간의 얽혀있는 데이터 파이프라인 복잡성을 극도로 직관적인 방식으로 추상화해 낸다. 이를 통해 리눅스 커널의 DRM(Direct Rendering Manager) 및 V4L2(Video for Linux 2) 프레임워크는 각각의 드라이버 모듈(디스플레이 컨트롤러, 브릿지 칩, 카메라 센서 등)들 사이의 소프트웨어적 결합도(Coupling)를 느슨하게 유지하면서도, 시스템 부팅 시점에 동적으로 의존성을 파악하여 최적의 데이터 경로와 클럭 동기화를 자동으로 확립할 수 있는 탁월한 유연성을 확보하였다.

마지막으로, Pinctrl 서브시스템을 통한 절전 모드 자동화, SCMI와 레귤레이터 바인딩을 활용한 동적 전원 관리 토폴로지, 그리고 RIFSC 버스 아키텍처와 Cortex-M33 리모트 프로세서(m0_rproc) 통합을 통한 하드웨어 기반의 권한 격리 기술은, 현대의 이기종 멀티코어 임베디드 리눅스 시스템이 직면한 치명적인 리소스 간섭 문제와 전력 낭비 이슈를 아키텍처 차원에서 근원적으로 해소하는 모범적인 해법을 제시하고 있다.

결론적으로, stm32mp257f-dk.dts 소스 트리의 심층적인 분석 과정은 단순히 특정 개발 보드에 리눅스를 포팅하는 지엽적인 엔지니어링 지식을 습득하는 것을 넘어선다. 이는 최신 임베디드 리눅스의 서브시스템 프레임워크들이 극도로 복잡해진 하드웨어 인프라를 어떠한 철학과 방법론으로 추상화하고 논리적으로 지배하는지 이해할 수 있는 명확한 아키텍처적 통찰을 제공한다. 이러한 깊이 있는 이해를 바탕으로, 시스템 엔지니어는 기본 레퍼런스 디자인의 구조적 완전성을 훼손하지 않으면서도 Device Tree Overlay 기법이나 새로운 커스텀 Device Tree를 자유롭게 직조하여, 산업 현장의 가혹한 요구사항에 부합하는 가장 견고하고 전력 효율적인 맞춤형 임베디드 시스템을 성공적으로 설계하고 배포할 수 있을 것이다.


References
  1. UM3385 Discovery kit with STM32MP257F MPU - Mouser Electronics, 3월 7, 2026에 액세스, https://www.mouser.com/pdfDocs/um3385-discovery-kit-with-stm32mp257f-mpu-stmicroelectronics.pdf

  2. STM32MP257F-DK, 3월 7, 2026에 액세스, https://static6.arrow.com/aropdfconversion/50bdb69961286c180e2d18a727c9f3ba615e6bae/stm32mp257fdk.pdf

  3. STM32MP257F-DK Discovery Kit — Zephyr Project Documentation, 3월 7, 2026에 액세스, https://docs.zephyrproject.org/latest/boards/st/stm32mp257f_dk/doc/index.html

  4. UM3385 Discovery kit with STM32MP257F MPU - User manual - STMicroelectronics, 3월 7, 2026에 액세스, https://www.st.com/resource/en/user_manual/um3385-discovery-kit-with-stm32mp257f-mpu-stmicroelectronics.pdf

  5. Where to get STM32MP257F-DK source code and device tree file?, 3월 7, 2026에 액세스, https://community.st.com/t5/stm32-mpus-products-and-hardware/where-to-get-stm32mp257f-dk-source-code-and-device-tree-file/td-p/790483

  6. linux/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts at master · torvalds/linux - GitHub, 3월 7, 2026에 액세스, https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts

  7. Device tree files and overlays | ConnectCore MP25 - Digi International, 3월 7, 2026에 액세스, https://docs.digi.com/resources/documentation/digidocs/embedded/dey/5.0/ccmp25/bsp-device-tree-files_r_ov.html

  8. Ethernet switch device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/Ethernet_switch_device_tree_configuration

  9. [00/10] Expand STM32MP2 family with new SoC and boards - Patchwork - OzLabs, 3월 7, 2026에 액세스, https://patchwork.ozlabs.org/comment/3461448/

  10. 3월 7, 2026에 액세스, https://tracker.debian.org/media/packages/a/arm-trusted-firmware/copyright-2.12.1dfsg-1

  11. Ethernet device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/Ethernet_device_tree_configuration

  12. What Device Tree/Configuration of USART/UART does the MP2xROMtracesdump have? - STMicroelectronics Community, 3월 7, 2026에 액세스, https://community.st.com/t5/stm32-mpus-products-and-hardware/what-device-tree-configuration-of-usart-uart-does-the/td-p/874808

  13. DCMIPP device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/DCMIPP_device_tree_configuration

  14. LTDC device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/LTDC_device_tree_configuration

  15. Serial TTY device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/Serial_TTY_device_tree_configuration

  16. Practical Labs - Bootlin, 3월 7, 2026에 액세스, https://bootlin.com/doc/training/embedded-linux/embedded-linux-stm32mp2-labs.pdf

  17. STM32MP257F-DK Study - HackMD, 3월 7, 2026에 액세스, https://hackmd.io/@Ming-Jun/HJB-W1SDWl?utm_source=preview-mode&utm_medium=rec

  18. UM12366: Getting Started with NXP-based Wireless Modules on STM32MP257F-DK Running OpenST Linux OS - Documentation, 3월 7, 2026에 액세스, https://docs.nxp.com/bundle/UM12366/page/topics/host_system_configuration.html

  19. CSI device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/CSI_device_tree_configuration

  20. Diff - f9274127f5a8f5ba2110305eb6bb6d42c2a82032^2..f9274127f5a8f5ba2110305eb6bb6d42c2a82032 - external/github.com/ARM-software/arm-trusted-firmware - Git at Google, 3월 7, 2026에 액세스, https://chromium.googlesource.com/external/github.com/ARM-software/arm-trusted-firmware/+/f9274127f5a8f5ba2110305eb6bb6d42c2a82032%5E2..f9274127f5a8f5ba2110305eb6bb6d42c2a82032/

  21. How to change the CPU frequency - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/How_to_change_the_CPU_frequency

  22. Display panels hardware components - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/Display_panels_hardware_components

  23. [PATCH v5 00/13] Enable display support for STM32MP25, 3월 7, 2026에 액세스, https://lists.freedesktop.org/archives/dri-devel/2025-August/521965.html

  24. Display bridges hardware components - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/Display_bridges_hardware_components

  25. USBH device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/USBH_device_tree_configuration

  26. TF-A boot only can handle 2 GB RAM? Does Op-tee or other TF-A DT causing this?, 3월 7, 2026에 액세스, https://community.st.com/t5/stm32-mpus-embedded-software-and/tf-a-boot-only-can-handle-2-gb-ram-does-op-tee-or-other-tf-a-dt/td-p/879048

  27. DDRCTRL and DDRPHYC device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/DDRCTRL_and_DDRPHYC_device_tree_configuration

  28. Enabling USART6 as a serial Port - STMicroelectronics Community, 3월 7, 2026에 액세스, https://community.st.com/t5/stm32-mpus-embedded-software-and/enabling-usart6-as-a-serial-port/td-p/857915

  29. STM32MP257F-DK: Issue in Getting the USART6 up on this MPU board - STMicroelectronics Community, 3월 7, 2026에 액세스, https://community.st.com/t5/stm32-mpus-products-and-hardware/stm32mp257f-dk-issue-in-getting-the-usart6-up-on-this-mpu-board/td-p/791622

  30. OpenSTLinux distribution - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/OpenSTLinux_distribution

  31. Linux remoteproc framework overview - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/Linux_remoteproc_framework_overview

  32. TAMP device tree configuration - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/TAMP_device_tree_configuration

  33. STM32MP2 power overview - stm32mpu - ST wiki, 3월 7, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/STM32MP2_power_overview

  34. Releases · STMicroelectronics/dt-stm32mp - GitHub, 3월 7, 2026에 액세스, https://github.com/STMicroelectronics/dt-stm32mp/releases





4. STM32MP257F-DK 보드 Booting Flow 상세 분석

최신 임베디드 시스템, 특히 STMicroelectronics의 STM32MP257F와 같은 고성능 이기종 멀티코어 마이크로프로세서(MPU) 환경에서 리눅스 커널의 초기화 과정은 단순한 소프트웨어 로딩을 넘어선 복잡한 하드웨어 추상화 및 보안 계층 확립의 과정이다. STM32MP257F-DK (Discovery Kit) 보드는 1.5GHz로 동작하는 듀얼 코어 Arm Cortex-A35와 400MHz로 동작하는 Cortex-M33 코프로세서를 탑재하고 있으며, TrustZone 기반의 강력한 리소스 격리 프레임워크(Resource Isolation Framework, RIF)를 하드웨어 레벨에서 구현하고 있다.1 이러한 복잡한 하드웨어 토폴로지를 범용 운영체제인 리눅스가 인식하고 제어하기 위해서는, 부트로더가 전달하는 디바이스 트리(Device Tree) 페이로드와 커널의 아키텍처 종속적인 초기화 코드가 극도로 정밀하게 맞물려 동작해야 한다.

이번 포스팅에서는 하드웨어 리셋 직후 실행되는 마스크 롬(ROM Code)부터 TrustZone 기반의 보안 부트 체인(TF-A, OP-TEE, U-Boot)을 거쳐, ARM64 아키텍처 기반의 리눅스 커널이 STM32MP257F-DK 보드에서 구동되는 전체 궤적을 심층적으로 추적한다. 부트로더의 단계별 이관 과정과 head.S의 어셈블리 진입점, 아키텍처 독립적인 start_kernel로의 전환, stm32mp257f-dk.dts 디바이스 트리의 파싱 및 메모리 내 구조화 작업, 그리고 최종적으로 플랫폼 디바이스의 인스턴스화 과정까지의 논리적 흐름과 메커니즘을 상세히 분석한다.

[그림 4.1] STM32MP257F-DK boot flow

1 단계: 마스크 롬(ROM Code)과 초기 부트 장치 판별

STM32MP257F-DK 보드에 전원이 인가되거나 하드웨어 리셋이 발생하면, 가장 먼저 프로세서 내부에 하드코딩된 마스크 롬(ROM Code)이 실행된다. Cortex-A35 코어에서 실행을 시작하는 이 ROM 코드는 보드 상의 부트 핀(Boot 0~3) 스위치 상태를 읽어 어떤 저장 매체(예: microSD 카드, eMMC, USB 등)에서 부팅할지 판별한다.1

ROM 코드는 감지된 부트 매체와 통신하기 위해 필요한 최소한의 시스템 클록 트리만을 활성화한다. 이후 해당 매체에서 1단계 부트로더(FSBL, First Stage Boot Loader) 이미지를 검색하여 칩 내부의 내장 SRAM(SYSRAM) 영역으로 로드한 뒤 실행 제어권을 넘긴다. 이 단계에서는 아직 외부의 대용량 DDR 메모리가 초기화되지 않았으므로 극히 제한된 내부 메모리 공간 내에서 작업이 이루어진다.

2 단계: TF-A 기반의 1단계 부트로더(FSBL)와 시스템 기초 설정

STM32MP2 아키텍처에서 Cortex-A35를 위한 FSBL의 역할은 일반적으로 보안성이 입증된 Trusted Firmware-A (TF-A) BL2가 담당한다. 내장 SRAM에서 실행을 시작한 TF-A BL2는 시스템이 본격적인 구동을 할 수 있도록 주요 하드웨어 인프라를 설정한다. 여기서 가장 중요하고 필수적인 작업은 DDR 컨트롤러(DDRCTRL)와 DDR PHY(DDRPHYC)를 초기화하여 보드에 장착된 4GB LPDDR4 외부 메모리를 활성화하는 것이다.

외부 메모리가 준비되면, TF-A BL2는 부트 매체로부터 FIP(Firmware Image Package)라는 캡슐화된 펌웨어 패키지를 읽어들여 DDR 메모리로 전송한다. FIP 내부에는 EL3 보안 모니터(TF-A BL31), 보안 운영체제(OP-TEE), 그리고 2단계 부트로더(U-Boot)가 포함되어 있다. 보안 부트(Secure Boot)가 활성화된 시스템의 경우, TF-A BL2는 이 패키지 내 컴포넌트들의 인증서와 서명을 검증하는 신뢰할 수 있는 보드 부트(Trusted Board Boot) 절차를 엄격하게 수행한다.

3 단계: TrustZone 보안 환경 구축 (BL31 및 OP-TEE)

FIP 패키지의 검증과 메모리 적재가 완료되면, 제어권은 TF-A BL31로 인계된다. BL31은 ARMv8 아키텍처의 가장 높은 특권 레벨인 EL3(Exception Level 3)에 상주하며, 일반 영역(Normal World)와 보안 영역(Secure World) 간의 컨텍스트 스위칭을 전담하는 보안 모니터(Secure Monitor) 펌웨어 역할을 수행한다.

이어서 보안 영역(Secure World)의 커널인 OP-TEE(BL32)가 실행된다. STM32MP25 환경에서 OP-TEE는 단순한 암호화 연산 처리 환경을 넘어 시스템 전체 리소스의 통제권을 갖는 핵심 주체이다. OP-TEE는 자체적인 디바이스 트리를 기반으로 전체 시스템 클록, 전원(PMIC), 그리고 하드웨어 리소스 격리 프레임워크(RIFSC) 방화벽을 설정한다. 이를 통해 어떤 하드웨어 블록이 보안 영역 전용이고 어떤 블록이 리눅스에 개방될지 결정한다.

또한 OP-TEE는 리눅스와 같은 넌시큐어 운영체제가 하드웨어 레지스터를 직접 조작하지 않고도 클록과 전원을 제어할 수 있도록 SCMI(System Control and Management Interface) 서버를 구동한다. 보안 아키텍처의 인프라가 모두 확립되면, OP-TEE는 제어권을 다시 BL31로 넘겨 프로세서를 비보안(Non-Secure) EL2/EL1 상태로 강등시킨 뒤 2단계 부트로더(SSBL)를 호출한다.

4 단계: U-Boot (SSBL) 실행과 리눅스 커널 로딩

비보안 영역에서 실행되는 2단계 부트로더(SSBL)인 U-Boot(BL33)는 운영체제를 메모리에 적재하고 부팅하는 임무를 맡는다. U-Boot는 이더넷, USB, SD/eMMC 등 다양한 인터페이스의 비보안 디바이스 드라이버를 초기화하여 복잡한 네트워크 부팅이나 로컬 파일 시스템 접근을 가능하게 한다.

부팅 시퀀스가 시작되면 U-Boot는 extlinux.conf나 U-Boot 스크립트 환경 변수를 스캔한다.3 이를 통해 부트 파티션에 위치한 리눅스 커널 이미지(주로 압축된 Image.gz)와 보드에 특화된 평탄화된 디바이스 트리(FDT) 블롭인 stm32mp257f-dk.dtb 파일을 읽어들여 DDR 메모리의 특정 물리 주소 영역(예: 커널은 0x84000000, DTB는 0x8f7cd000 부근)에 배치하고 커널의 압축을 해제한다.3

로딩이 완료되면 U-Boot는 런타임에 결정된 정보(예: 메모리 맵, 할당된 이더넷 MAC 주소, 루트 파일 시스템 위치와 콘솔 포트를 담은 bootargs 커맨드라인 매개변수)를 디바이스 트리의 /chosen 노드 등에 동적으로 주입(Patching)한다.4 최종적으로 U-Boot는 ARM64 부팅 규약에 맞춰 x0 레지스터에 FDT 블롭의 물리적 주소를 저장하고, 커널 이미지의 맨 앞부분에 위치한 head.S의 진입점(primary_entry)으로 분기하여 리눅스 커널로 제어권을 완전히 이관한다.

5 단계: 부트로더 핸드오프와 ARM64 저수준 어셈블리 초기화

앞선 부트로더와 보안 계층의 초기화가 완료되고, U-Boot가 DDR 메모리에 적재된 커널 이미지로 점프하면서 본격적인 리눅스 커널의 생명주기가 시작된다. ARM64 리눅스 부팅 프로토콜은 U-Boot가 커널로 점프하기 전 반드시 준수해야 하는 엄격한 하드웨어 상태 조건을 규정하고 있다. 구체적으로 메모리 관리 장치(MMU)와 데이터 캐시(D-Cache)는 비활성화되어야 하며, 모든 직접 메모리 접근(DMA) 컨트롤러는 정지 상태여야 하고, 범용 레지스터 x0에는 U-Boot가 런타임 수정을 거친 평탄화된 디바이스 트리(FDT) 블롭의 물리 주소가 담겨 있어야 한다.5

커널 진입점: primary_entry의 레지스터 및 상태 보존

STM32MP257F-DK 보드에서 커널 제어권이 이관되는 최초의 실행 지점은 arch/arm64/kernel/head.S 파일에 정의된 primary_entry 심볼이다.5 커널은 가상 메모리 공간으로 전환하기 전, 극히 제한된 물리적 주소 공간에서 최소한의 C 언어 실행 환경과 페이지 테이블을 구축하는 어셈블리 루틴을 수행한다.

진입 직후 커널은 record_mmu_state 루틴을 호출하여 현재의 하드웨어 상태를 진단한다. 이 함수는 CurrentEL(Current Exception Level) 레지스터를 읽어 현재 코어가 EL2(하이퍼바이저 레벨)인지 EL1(커널 레벨)인지 판별한 후, 해당 예외 레벨의 시스템 제어 레지스터(SCTLR_EL1 또는 SCTLR_EL2)에서 M (MMU 활성화) 비트를 추출한다.5 ARM64 부트 프로토콜은 MMU가 꺼진 상태를 요구하지만, 규격을 위반한 부트로더로 인해 MMU가 켜진 채 진입할 경우를 대비하여 이 상태 값을 호출자 저장 레지스터인 x19에 안전하게 보존한다.5

이어서 preserve_boot_args 루틴이 실행된다. 부트로더가 x0 레지스터를 통해 전달한 FDT 물리 주소는 이후의 초기화 과정에서 덮어쓰여질 위험이 있으므로, 즉시 x21 레지스터로 복사되어 보존된다.5 동시에 x0부터 x3까지의 부트로더 인자들은 전역 배열인 boot_args 메모리 영역에 저장된다. 커널은 dcache_inval_poc 함수에 대한 테일 콜(Tail Call)을 수행하여 boot_args가 저장된 메모리 영역의 캐시 라인을 일관성 지점(Point of Consistency, PoC)까지 강제로 무효화(Invalidate)한다.5 이는 추후 MMU와 캐시가 활성화되었을 때 발생할 수 있는 잠재적인 메모리 오염을 원천적으로 차단하기 위한 필수 기제이다.

초기 페이지 테이블 구축과 가상 주소 공간으로의 도약

부트 인자 보존이 완료되면, 커널은 C 언어 코드가 실행될 수 있는 가상 주소(Virtual Address, VA) 매핑을 생성하기 위해 __pi_create_init_idmap 매크로를 호출하여 초기 페이지 테이블을 구축한다.5 이 과정에서 두 가지 핵심적인 페이지 테이블이 구성된다.


페이지 테이블 구조체

목적 및 역할

가상 주소 (VA) 맵핑 기준

물리 주소 (PA) 맵핑 기준

idmap_pg_dir

MMU가 켜지는 정확한 순간에 명령어 페치(Fetch) 결함을 방지하기 위한 물리-가상 1:1 식별(Identity) 맵핑

.idmap.text 섹션의 런타임 물리 주소

.idmap.text 섹션의 런타임 물리 주소 6

init_pg_dir

커널 코어가 실제로 동작할 vmalloc 영역을 위한 초기 커널 이미지 맵핑

KIMAGE_VADDR 기준의 컴파일 타임 주소

DRAM 내 _text 섹션의 런타임 물리 주소 6


페이지 테이블이 메모리에 기록된 후, 프로세서의 투기적 실행(Speculative Execution)에 의해 캐시에 잘못 적재되는 것을 막기 위해 다시 한번 캐시가 무효화된다.5 이후 init_kernel_el 루틴을 통해 부팅 모드를 초기화하고, __cpu_setup 루틴을 통해 TLB 무효화 및 48비트 가상 주소 공간을 지원하도록 TCR(Translation Control Register)을 설정한다.5

하드웨어 설정이 완료되면 커널은 __primary_switch 루틴으로 분기하여 TTBR0와 TTBR1 레지스터에 각각 페이지 테이블 주소를 로드하고 마침내 MMU를 활성화한다.5 가상 주소 공간으로 넘어간 프로세서는 __primary_switched 레이블에서 유휴 스레드(Idle Task, 프로세스 0)의 초기화 데이터인 init_task를 로드하여 스택 포인터를 설정하고, 예외 벡터 테이블 주소를 기록한다.5 마지막으로 x21에 보존했던 FDT 주소를 전역 변수 __fdt_pointer에 저장한 후 아키텍처 독립적 C 언어 진입점인 start_kernel()을 호출한다.5

6 단계: C 로직 기반의 코어 시스템 브링업과 아키텍처 설정

init/main.c 파일에 정의된 start_kernel() 함수는 리눅스 커널의 심장부로, 운영체제의 근간을 이루는 코어 컴포넌트들을 순차적으로 초기화한다.8 이 함수는 실행 초반부에 setup_arch() 함수를 호출하여 STM32MP257F-DK 플랫폼 특성에 커널을 동기화시키는 아키텍처 종속적 초기화를 위임한다.6

[그림 4.2] STM32MP257F-DK kernel boot sequence#1
[출처 - https://labs.dese.iisc.ac.in/embeddedlab/device-tree-and-boot-flow/]
📌 위의 그림에 표현된 arch/arm 디렉토리는 stm32mp257f-dk board의 경우 arch/arm64로 수정되어야 한다.

setup_arch()와 초기 FDT(Flattened Device Tree) 스캔

ARM64 아키텍처를 위한 setup_arch(char **cmdline_p) 함수는 부트로더가 메모리에 남겨둔 FDT를 파싱하여 물리적 특성을 커널 자료구조에 주입한다.10 커널은 __fdt_pointer 물리 주소를 초기 픽스맵(Early Fixmap)으로 매핑한 후 setup_machine_fdt() 함수를 호출한다.10

[그림 4.3] STM32MP257F-DK kernel boot sequence#2
[출처 - https://labs.dese.iisc.ac.in/embeddedlab/device-tree-and-boot-flow/]

📌 위의 그림에 표현된 arch/arm 디렉토리는 stm32mp257f-dk board의 경우 arch/arm64로 수정되어야 한다.

setup_machine_fdt()는 루트 노드(/)의 compatible 속성을 검색하여 커널에 컴파일된 machine_desc 구조체 테이블과 대조한다. STM32MP257F-DK 보드 디바이스 트리의 루트 노드는 compatible = "st,stm32mp257f-dk", "st,stm32mp257";를 포함하고 있다.13 완벽한 일치가 확인되면, 현재 플랫폼을 인지하고 특화된 초기화 훅을 설정한다.

동시에 페이징 서브시스템 활성화 전 of_scan_flat_dt()를 사용하여 FDT를 선행 스캔한다.14

  1. early_init_dt_scan_chosen(): /chosen 노드를 스캔하여 stdout-path로 시리얼 콘솔 출력을 라우팅하고, U-Boot가 전달한 커맨드라인 인수를 boot_command_line 버퍼에 복사한다.11

  2. early_init_dt_scan_root(): #address-cells와 #size-cells 속성을 초기화한다.14

  3. early_init_dt_scan_memory(): /memory 노드를 파싱하여 가용 물리적 RAM(DDR 베이스 0x80000000)의 크기와 경계를 파악하고 Memblock 서브시스템에 등록한다.13

메모리 블록 초기화와 예약 메모리(Reserved Memory) 처리

FDT 초기 스캔 후 setup_arch()는 arm64_memblock_init()을 호출해 전체 물리 메모리 맵을 확정한다.7 커널 코드/데이터 영역 예약과 함께, FDT의 /reserved-memory 노드들을 파싱하여 코프로세서 및 특수 IP용 메모리 풀을 격리한다.

STM32MP257F-DK 보드의 경우 멀티미디어가 강력하여 이 설정이 중요하다. 디바이스 트리는 0xf2200000 주소에 128 MiB 크기의 DMA 풀(shared-dma-pool)을 CMA로 예약하여 GPU, VDEC, LTDC 디스플레이 컨트롤러가 대량의 연속된 물리 메모리를 사용할 수 있도록 보장한다.3 또한 TF-A와 OP-TEE 보안 운영체제가 상주하는 공간(0x0a000000 등)을 nomap 속성으로 선언하여 리눅스 커널의 접근을 원천 차단한다.3

7 단계: 디바이스 트리 Unflattening과 메모리 내 객체화

압축된 이진 블롭(Blob) 형태인 FDT는 런타임 드라이버 모델에 적합하지 않다.15 따라서 setup_arch() 후반부에서 커널은 unflatten_device_tree() 함수를 호출하여 이진 데이터를 메모리 상의 연결 리스트와 포인터 구조를 가진 계층적 C 구조체(struct device_node)로 변환한다.10

이 프로세스는 2패스(Two-Pass) 알고리즘을 사용한다.16

  1. 크기 계산: 트리를 순차적으로 읽으며 구조체와 속성 문자열들을 담는 데 필요한 총 바이트 수를 정밀 계산한다.

  2. 할당 및 링킹: 초기 할당자로부터 연속된 메모리를 한 번에 할당받고 데이터를 채운다.17 각 노드는 부모(Parent), 형제(Sibling), 자식(Child) 포인터 및 속성(Property) 리스트 헤드를 가지게 된다.

이 과정이 완료되면, 리눅스 커널은 포인터 기반으로 즉각적 순회와 검색이 가능한 고도의 내비게이션 트리 객체를 확보하며, 이는 플랫폼 디바이스 생성의 근간이 된다.

8 단계: STM32MP257F-DK의 디바이스 트리 계층 구조 설계 분석

리눅스 커널 메모리에 로드된 동적 트리는 재사용성을 위해 여러 .dtsi 파일이 중첩 결합된 결과물이다.18 STM32MP257F-DK의 토폴로지는 다음과 같은 병합 과정을 거친다.13


디바이스 트리 파일명

계층적 역할 및 추상화 레벨

주요 하드웨어 노드 및 컴포넌트 정의

stm32mp251.dtsi

기본 SoC 파운데이션 (Base)

단일 Cortex-A35 코어 정의, 코어 버스, 인터럽트(GIC), RIFSC 방화벽 버스 및 기본 주변장치 맵.19

stm32mp253.dtsi

듀얼 코어 확장

두 번째 Cortex-A35 추가, CAN FD 등.20

stm32mp255.dtsi

멀티미디어 확장

비디오 디코더(VDEC) 노드 등 선언.19

stm32mp257.dtsi

플래그십 SoC 완성

3D GPU 노드 및 DSI 인터페이스 추가.13

stm32mp25-pinctrl.dtsi

핀 멀티플렉싱(Pinmux) 맵

PF13/14 핀을 USART6 TX/RX로 묶는 등 하드웨어 핀 제어 상태 노드들의 대규모 정의.13

stm32mp257f-dk.dts

최종 보드 인스턴스화

보드의 물리적 구성(이더넷 PHY, HDMI/LVDS 브리지)을 명시하고, 사용할 노드의 status = "okay" 덮어쓰기 수행.13


기본 뼈대인 .dtsi 파일에서 주변장치 노드들은 status = "disabled"로 정의되어 있으나,22 최상위 보드 파일인 stm32mp257f-dk.dts에서 라벨 참조를 통해 이 속성을 재정의하여 필요한 장치만 커널에서 인스턴스화되도록 활성화(okay)한다.13

9 단계: 버스 Population과 플랫폼 디바이스 생성 흐름

커널 초기화 루프인 do_initcalls() 단계에 진입하면, 디바이스 트리 노드를 리눅스 디바이스 드라이버 모델과 바인딩하기 위해 arch_initcall_sync(of_platform_default_populate_init)가 실행된다.24

of_platform_populate의 재귀적 트리 순회

커널은 "simple-bus", "simple-mfd" 등의 호환성 문자열을 포함하는 기본 버스 매치 테이블을 가지고 루트 노드부터 순회를 시작한다.24 매치 테이블에 부합하는 버스 노드를 만나면 of_platform_bus_create()를 재귀적으로 호출해 하위 노드로 진입한다.25

버스가 아닌 일반 페리페럴 노드에 도달하면 of_device_alloc()을 통해 struct platform_device 구조체를 동적으로 할당하고, 레지스터 주소 및 인터럽트 정보를 변환하여 채워 넣는다.24 디바이스가 커널 코어에 등록되면, 호환되는 platform_driver의 매치 테이블 스캔을 통해 드라이버의 .probe() 콜백 함수가 즉각 실행된다.26

STM32MP25 RIFSC 방화벽 버스의 특수 Population 제어

STM32MP25 아키텍처는 대부분의 페리페럴이 RIFSC(Resource Isolation Framework Security Controller) 버스 하위 노드로 캡슐화되어 있는 매우 독특한 구조를 지닌다.28

RIFSC 노드는 compatible = "st,stm32mp25-rifsc", "simple-bus"; 속성을 가지기 때문에28 일반적인 로직으로는 커널이 이를 단순 버스로 인식해 방화벽 권한 획득 전에 하위 디바이스들을 자동 생성하려고 시도하여 버스 결함(Bus Fault) 크래시를 유발할 수 있다.

이를 방지하기 위해 "st,stm32mp25-rifsc" 드라이버가 개입한다. 이 드라이버는 자신의 stm32_rifsc_probe 함수에서 하드웨어 레지스터(RISUP, RIMU, RISAL)를 매핑하고 방화벽 컨트롤러를 커널에 등록하는 보안 설정 준비를 완전히 끝마친 뒤, 함수의 맨 마지막 줄에서 of_platform_populate(np, NULL, NULL, &pdev->dev);를 직접 수동으로 호출한다.27 즉, 방화벽 통제가 완벽히 준비된 시점에 하위 페리페럴 탐색을 재개시켜 수십 개의 IP(USART, GPU 등)가 안전하게 자신의 보안 권한을 획득하고 인스턴스화되도록 보장하는 정교한 트릭이다.

10 단계: 핵심 종속성 주입 및 하위 시스템(SCMI, Pinctrl) 초기화 연계

생성된 디바이스 드라이버들이 동작하기 위해서는 클록 공급, 전압 인가, 핀 제어라는 선행 종속성이 필수적이며, 시스템은 SCMI 프로토콜과 지연 프로빙(Deferred Probing)을 통해 이 서열을 조율한다.30

SCMI 프로토콜을 통한 안전한 리소스 획득

TrustZone 기반 환경에서 리눅스(비보안 운영체제)는 코어 클록(RCC)이나 PMIC 레지스터에 직접 접근할 수 없다. 이를 OP-TEE(SCMI 서버)에 위임하고 리눅스 커널은 SCMI 에이전트로 동작한다.32 특정 디바이스 트리 노드가 클록을 요구하면 커널 공통 클록 프레임워크(CCF)는 이를 SCMI 드라이버로 전달하고, 드라이버는 공유 메모리를 통해 OP-TEE 측으로 SMC(Secure Monitor Call) 인터럽트를 보내 클록 갱신을 요청한다.32 초기 부팅 로그에서 arm-scmi firmware:scmi 메세지와 함께 SCMI가 확립되는 것을 볼 수 있으며3 모든 드라이버는 SCMI 프로토콜 활성화 이후에만 정상 동작이 가능하다.

Pinctrl 프레임워크와 Deferred Probing

또한 외부로 데이터를 주고받기 위해서는 칩의 물리적 패드가 올바르게 다중화되어야 한다. USART 등의 장치가 프로브될 때 커널은 노드 내부의 pinctrl-0 속성을 확인하고 STM32 전용 Pinctrl 드라이버에 핀 매핑을 요청한다.21 만약 Pinctrl 드라이버가 아직 초기화되지 않았다면 해당 드라이버는 -EPROBE_DEFER 오류를 반환한다.30 커널 드라이버 코어는 이 디바이스를 대기열로 넘겨 종속성이 충족될 때 런타임에 초기화를 재시도하는 우아한 퍼즐 맞추기를 수행한다.31

11 단계: 고급 멀티미디어 인터페이스의 동적 그래프 바인딩

시스템 인프라가 굳건해지면 STM32MP257F-DK의 고성능 멀티미디어 IP들이 디바이스 트리의 동적 포트 그래프(Graph) 바인딩으로 결합된다.

카메라 파이프라인의 경우, DCMIPP 프로세서 노드는 CSI(카메라 시리얼 인터페이스) 노드 하위의 endpoint를 가리키며 엮인다.23 커널 V4L2 프레임워크가 초기화될 때 I2C 통신을 통해 데이터 레인 개수, 클록 주파수 등을 동적으로 협상하여 드라이버 스택 파이프라인을 구축한다.19 출력 화면 역시 LTDC 디스플레이 컨트롤러가 LVDS 또는 HDMI 브리지 패널의 endpoint와 연결되며, 커널 내 DRM 서브시스템에 세밀한 패널 타이밍 데이터가 파싱되어 적용된 후에 비로소 /dev/fb0 프레임버퍼가 완성되어 유저 스페이스 어플리케이션 화면이 송출된다.13


정리/요약: STM32MP257F-DK 하드웨어 추상화의 정합성

STM32MP257F-DK 보드에서 리눅스 커널이 구동되는 과정은, 가장 근원적인 마스크 롬(ROM)과 TrustZone 보안 펌웨어(TF-A, OP-TEE)가 쌓아 올린 견고하고 안전한 토대 위에서 시작된다. 부트로더 부트 체인을 거쳐 U-Boot로부터 제어권을 인계받은 커널은 head.S의 어셈블리 단계에서 MMU와 가상 메모리 공간을 안전하게 도약시킨다.

이후 C 언어 영역인 setup_arch()에 진입하여 FDT를 파싱하고 unflatten_device_tree()를 통해 이진 데이터를 생동감 있는 동적 트리 객체로 탈바꿈시킨다. 특히, RIFSC 방화벽 드라이버를 통해 보안 경계를 존중하며 진행되는 특수한 디바이스 인스턴스화, SCMI를 통한 안전한 클록 제어, 지연 프로빙(Deferred Probing)과 멀티미디어 동적 그래프 바인딩이 유기적으로 결합된다. 이처럼 복잡하고 정밀하게 직조된 소프트웨어 공학의 결합 덕분에, 거대한 범용 운영체제인 리눅스는 STM32MP257F-DK라는 고도의 하드웨어 플랫폼 위에 완벽하게 안착할 수 있다.



부록: 이기종 멀티코어(Cortex-A35 및 Cortex-M33) 간의 통신 및 제어 메커니즘

STM32MP257F-DK 보드에서 메인 프로세서인 Cortex-A35(Linux 환경)와 코프로세서인 Cortex-M33(Zephyr RTOS 또는 STM32Cube 펌웨어 환경) 간의 제어 및 데이터 통신은 주로 OpenAMP (Open Asymmetric Multi-Processing) 표준 아키텍처를 기반으로 구현된다. 이 시스템은 크게 세 가지 계층적 프레임워크의 결합으로 작동한다.

1. 펌웨어 로드 및 생명주기 관리 (Linux Remoteproc Framework)

리눅스 커널은 remoteproc (Remote Processor) 서브시스템을 사용하여 Cortex-M33 코어의 생명주기(부팅, 펌웨어 로드, 중지, 상태 모니터링 등)를 총괄적으로 통제한다.

  • 디바이스 트리 바인딩: 리눅스 커널의 디바이스 트리에는 m33_rproc 노드(compatible = "st,stm32mp2-m33")가 정의되어 있다.35 이 노드에는 M33 코어가 펌웨어를 실행할 전용 메모리 영역(RETRAM, SRAM 등)과 통신을 위한 공유 메모리 주소 공간이 명시적으로 매핑된다.35

  • 사용자 공간 제어: 리눅스의 sysfs 가상 파일 시스템 경로인 /sys/class/remoteproc/remoteprocX/state에 애플리케이션이나 셸 스크립트가 start 또는 stop 명령을 기록하는 방식으로 M33 펌웨어의 실행을 런타임에 동적으로 시작하고 제어할 수 있다.

2. 데이터 통신 채널 확립 (RPMsg 및 VirtIO)

두 코어 간의 실제 데이터 송수신은 RPMsg (Remote Processor Messaging) 프로토콜과 가상화 큐인 VirtIO 기술을 통해 이루어진다.

  • 리소스 테이블(Resource Table): Zephyr RTOS나 STM32 펌웨어 바이너리(.elf)를 컴파일할 때, 내부에는 반드시 .resource_table이라는 특수한 구조체 섹션이 포함되어야 한다.

  • 공유 메모리 동기화: 리눅스의 remoteproc 드라이버가 M33 펌웨어를 메모리에 적재할 때 이 리소스 테이블을 파싱한다. 이를 통해 두 코어가 메시지 큐를 주고받을 공유 메모리(VirtIO Ring)의 물리적 위치와 통신 엔드포인트(Endpoint) 설정 정보를 상호 동기화하게 된다.

3. 하드웨어 동기화 및 시그널링 (IPCC 및 Mailbox)

실제 데이터 페이로드 자체는 시스템의 공유 메모리 공간에 저장되지만, 상대 코어에 "새로운 데이터가 도착했다"는 사실을 지연 없이 즉각적으로 알리기 위해 **IPCC (Inter-Processor Communication Controller)**라는 STM32 전용 하드웨어 방식을 사용한다.

  • 메일박스(Mailbox) 컨트롤러: IPCC 하드웨어는 여러 채널(예: STM32MP257F의 경우 IPCC1에 16개 채널 제공)을 갖춘 메일박스 역할을 수행하며, 리눅스와 M33 코어 사이에 논블로킹(non-blocking) 방식으로 하드웨어 인터럽트를 안전하게 발생시킨다.

  • 드라이버 계층: 리눅스 커널 내에서는 drivers/mailbox/stm32-ipcc.c 드라이버가 IPCC 제어 레지스터를 직접 조작하여 상대 코어에 시그널을 보내고 데이터를 인출(Retrieve)할 수 있도록 지원한다.

요약된 전체 동작 흐름

Cortex-M33에 올라간 Zephyr RTOS 내부에서 애플리케이션이 rpmsg_send()와 같은 API를 호출하여 데이터를 전송하면, 데이터는 지정된 공유 메모리 버퍼(VirtIO)에 쓰인다. 직후 M33 코어는 하드웨어 IPCC 레지스터를 건드려 리눅스(A35) 측으로 인터럽트를 발생시킨다.

리눅스 커널의 Mailbox/IPCC 드라이버는 이 인터럽트를 수신하고 상위의 RPMsg 버스 드라이버로 메시지를 올려보내며, 최종적으로 사용자 공간에 /dev/ttyrpmsgX와 같은 가상 TTY 문자 장치 노드를 생성한다. 리눅스 유저 애플리케이션은 이 파일 노드에 단순한 읽기/쓰기 작업을 수행함으로써 복잡한 내부 과정을 몰라도 M33 코어와 원활하게 양방향 통신을 수행할 수 있게 된다.


References

  1. UM3385 Discovery kit with STM32MP257F MPU - User manual - STMicroelectronics, 3월 6, 2026에 액세스, https://www.st.com/resource/en/user_manual/um3385-discovery-kit-with-stm32mp257f-mpu-stmicroelectronics.pdf

  2. STM32MP257F-DK Discovery Kit - Zephyr Documentation, 3월 6, 2026에 액세스, https://docs.zephyrproject.org/latest/boards/st/stm32mp257f_dk/doc/index.html

  3. Execute basic commands - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/Getting_started/STM32MP2_boards/STM32MP257x-DK/Let%27s_start/Execute_basic_commands

  4. Device Tree and Boot Flow | Embedded systems - DESE Labs, 3월 6, 2026에 액세스, https://labs.dese.iisc.ac.in/embeddedlab/device-tree-and-boot-flow/

  5. linux/arch/arm64/kernel/head.S at master - GitHub, 3월 6, 2026에 액세스, https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/head.S

  6. ARM64 Kernel Booting Process - NXP Community, 3월 6, 2026에 액세스, https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/imx-processors%40tkb/5659/2/How%20to%20boot%20the%20kernel.pdf

  7. ARM64 Kernel Booting Process - NXP Community, 3월 6, 2026에 액세스, https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/Layerscape%40tkb/153/1/ARM64%20Kernel%20Booting%20Process.pdf

  8. Understanding Linux Kernel Initialization: From Bootloader to Userspace | by Hasan Can Sert | Medium, 3월 6, 2026에 액세스, https://medium.com/@hasancansert/understanding-linux-kernel-initialization-from-bootloader-to-userspace-d875431d27ec

  9. Linux kernel 6.1 start_kernel procedure, 3월 6, 2026에 액세스, https://unix.stackexchange.com/questions/788051/linux-kernel-6-1-start-kernel-procedure

  10. linux/arch/arm64/kernel/setup.c at master - GitHub, 3월 6, 2026에 액세스, https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/setup.c

  11. how does the bootloader pass the kernel command line to the kernel? - Stack Overflow, 3월 6, 2026에 액세스, https://stackoverflow.com/questions/64877292/how-does-the-bootloader-pass-the-kernel-command-line-to-the-kernel

  12. Linux kernel initialization - When are devicetree blobs parsed and tree nodes are loaded?, 3월 6, 2026에 액세스, https://stackoverflow.com/questions/65368615/linux-kernel-initialization-when-are-devicetree-blobs-parsed-and-tree-nodes-ar

  13. linux/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts at master · torvalds/linux - GitHub, 3월 6, 2026에 액세스, https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts

  14. Linux and the Devicetree - The Linux Kernel documentation, 3월 6, 2026에 액세스, https://docs.kernel.org/devicetree/usage-model.html

  15. Kernel parameters using Flattened Device Trees - Arm Developer, 3월 6, 2026에 액세스, https://developer.arm.com/documentation/den0013/latest/Boot-Code/Booting-Linux/Kernel-parameters-using-Flattened-Device-Trees

  16. Diff - 9c4b86ebf5bfdaceba4bedbaf76e4ff745db17ef^2..9c4b86ebf5bfdaceba4bedbaf76e4ff745db17ef - kernel/common - Git at Google - Android GoogleSource, 3월 6, 2026에 액세스, https://android.googlesource.com/kernel/common/+/9c4b86ebf5bfdaceba4bedbaf76e4ff745db17ef%5E2..9c4b86ebf5bfdaceba4bedbaf76e4ff745db17ef/

  17. CVE-2023-52750 - Red Hat Customer Portal, 3월 6, 2026에 액세스, https://access.redhat.com/security/cve/CVE-2023-52750

  18. Mastering Device Trees: A Guide to Hardware Integration in Linux | by Hasan Can Sert, 3월 6, 2026에 액세스, https://medium.com/@hasancansert/mastering-device-trees-a-guide-to-hardware-integration-in-linux-3e1516a75e04

  19. DCMIPP device tree configuration - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/DCMIPP_device_tree_configuration

  20. DSI device tree configuration - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/DSI_device_tree_configuration

  21. USART6 (PF13/PF14) on STM32MP257-DK - /dev/ttySTM6 never appears; SSH broke, 3월 6, 2026에 액세스, https://community.st.com/t5/stm32-mpus-products-and-hardware/usart6-pf13-pf14-on-stm32mp257-dk-dev-ttystm6-never-appears-ssh/td-p/852708

  22. Practical Labs - Bootlin, 3월 6, 2026에 액세스, https://bootlin.com/doc/training/embedded-linux/embedded-linux-stm32mp2-labs.pdf

  23. CSI device tree configuration - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/CSI_device_tree_configuration

  24. linux/drivers/of/platform.c at master · torvalds/linux · GitHub, 3월 6, 2026에 액세스, https://github.com/torvalds/linux/blob/master/drivers/of/platform.c

  25. Linux device tree learning (2) Transfer and use of device tree - EEWorld, 3월 6, 2026에 액세스, https://en.eeworld.com.cn/news/mcu/eic641510.html

  26. USBH device tree configuration - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/USBH_device_tree_configuration

  27. drivers/bus/stm32_rifsc.c · 1e26c5e28ca5821a824e90dd359556f5e9e7b89f · Ture Bentzin / linux - beim GitLab der FH Aachen!, 3월 6, 2026에 액세스, https://git.fh-aachen.de/tb3838s/linux/-/blob/1e26c5e28ca5821a824e90dd359556f5e9e7b89f/drivers/bus/stm32_rifsc.c

  28. Diff - 6951abe8f37b1f4f9a0e7c036873f0ab4f56abf1^2..6951abe8f37b1f4f9a0e7c036873f0ab4f56abf1 - pub/scm/linux/kernel/git/at91/linux - Git at Google, 3월 6, 2026에 액세스, https://kernel.googlesource.com/pub/scm/linux/kernel/git/at91/linux/+/6951abe8f37b1f4f9a0e7c036873f0ab4f56abf1%5E2..6951abe8f37b1f4f9a0e7c036873f0ab4f56abf1/

  29. Diff - b6394d6f715919c053c1450ef0d7c5e517b53764^2..b6394d6f715919c053c1450ef0d7c5e517b53764 - kernel/common - Git at Google - Git repositories on android, 3월 6, 2026에 액세스, https://android.googlesource.com/kernel/common/+/b6394d6f715919c053c1450ef0d7c5e517b53764%5E2..b6394d6f715919c053c1450ef0d7c5e517b53764/

  30. GPIO internal peripheral - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/GPIO_internal_peripheral

  31. Changing Linux kernel module boot order - Stack Overflow, 3월 6, 2026에 액세스, https://stackoverflow.com/questions/62007282/changing-linux-kernel-module-boot-order

  32. SCMI device tree configuration - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/SCMI_device_tree_configuration

  33. SCMI overview - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/SCMI_overview

  34. Display panels hardware components - stm32mpu - ST wiki, 3월 6, 2026에 액세스, https://wiki.st.com/stm32mpu/wiki/Display_panels_hardware_components

  35. Linux remoteproc framework overview - stm32mpu - ST wiki, 3월 6, 2026에 액세스,



Slowboot

댓글 없음:

댓글 쓰기