在傳統(tǒng)的 RTOS 驅(qū)動開發(fā)中,硬件資源往往靠硬編碼、設(shè)備與驅(qū)動強(qiáng)耦合,導(dǎo)致移植難、復(fù)用低、維護(hù)成本高。
如今,RT-Thread 推出了新一代DM(Device Manager)驅(qū)動框架,引入設(shè)備樹(Device Tree)、自動匹配與動態(tài) probe 機(jī)制,讓驅(qū)動開發(fā)更加現(xiàn)代化、可擴(kuò)展。
本文以qemu-virt64-aarch64 平臺為例,帶你從零上手DM 框架:
設(shè)備樹的三種使用方式
最小系統(tǒng)與多核啟動實戰(zhàn)
與傳統(tǒng)驅(qū)動框架的對比
如果你是嵌入式開發(fā)者或RT-Thread 愛好者,這篇文章將幫你快速掌握下一代 RT-Thread 驅(qū)動開發(fā)范式。
目錄
簡介
核心特點
兩種驅(qū)動框架對比
DM使用方式(以qemu-virt64-aarch64為例)
1 簡介
RT-Thread 新一代 DM(Device Manager)驅(qū)動框架,是近年來引入的一套現(xiàn)代化設(shè)備驅(qū)動管理模型。
該框架主要面向高性能平臺(MPU / SoC),通過引入類似 Linux 驅(qū)動模型的設(shè)計理念,實現(xiàn):
設(shè)備與驅(qū)動解耦
基于設(shè)備樹(Device Tree)的硬件描述
自動匹配與動態(tài)加載(probe 機(jī)制)
其目標(biāo)是逐步替代或并行于傳統(tǒng)靜態(tài)設(shè)備注冊方式,構(gòu)建更加統(tǒng)一、靈活、可擴(kuò)展的驅(qū)動體系。
2 核心特點
基于設(shè)備樹描述硬件資源
Driver / Device 解耦
自動匹配(compatible)
動態(tài) probe / remove 機(jī)制
更適合復(fù)雜 SoC 平臺
3 兩種驅(qū)動框架對比

4 DM使用方式(以qemu-virt64-aarch64為例)
4.1 準(zhǔn)備工作
獲取最新RT-Thread源碼 本文檔使用commit: 2b58dec87b584aa7ded6e8c736498716f8d29cd0
進(jìn)入BSP 目錄:bsp/qemu-virt64-aarch64
打開menuconfig,開啟 SMART 選項
下載 SMART 專用工具鏈,并設(shè)置RTT_EXEC_PATH與RTT_CC_PREFIX環(huán)境變量
4.2 設(shè)備樹使用方式
在 DM 框架中,設(shè)備樹(Device Tree)是核心輸入,用于描述硬件資源(UART、GIC、VirtIO 等)。
當(dāng)前支持三種方式:
方式一:使用 QEMU 自動生成 DTB
QEMU 的 virt 平臺可以自動生成設(shè)備樹,并通過寄存器傳遞給內(nèi)核。
啟動命令:
qemu-system-aarch64\ -M virt,gic-version=2\ -cpu cortex-a53\ -m128M\ -smp4\ -kernel rtthread.bin\ -nographic
原理:
QEMU 在啟動時動態(tài)構(gòu)建 DTB
將 DTB 地址通過寄存器傳遞
RT-Thread 在 early boot 階段解析該 DTB
方式二:使用外部 DTB 文件
可以自定義 .dts 并編譯為 .dtb,然后傳給 QEMU:
qemu-system-aarch64\ -M virt\ -cpu cortex-a53\ -m128M\ -kernel rtthread.bin\ -dtb virt.dtb\ -nographic
設(shè)備樹編譯方法:
dtc -Idts -O dtb -o virt.dtbvirt.dts
方式三:內(nèi)嵌設(shè)備樹(RT-Thread 內(nèi)置 DTB)
可以在 menuconfig 中配置:
RT_BUILTIN_FDT_PATH="path/to/your.dtb"
系統(tǒng)會通過 .incbin 將 DTB 嵌入到最終鏡像中。
實現(xiàn)原理:
編譯階段將 DTB 二進(jìn)制嵌入 .rodata
啟動時直接使用內(nèi)置 DTB,而不依賴 QEMU 傳參
4.3 自定義設(shè)備樹使用(最小系統(tǒng)示例)
本節(jié)基于一個最小可運行設(shè)備樹(DTS),講解如何在 RT-Thread DM 框架中使用自定義設(shè)備樹。
4.3.1 最小設(shè)備樹示例
/dts-v1/;/ { compatible ="linux,dummy-virt"; #address-cells =<2>; #size-cells =<2>; interrupt-parent = <0x8002>; memory@40000000{ reg = <0x000x400000000x000x8000000>; device_type ="memory"; }; chosen { stdout-path ="/pl011@9000000"; }; cpus { #size-cells =<0x00>; #address-cells =<0x01>; cpu@0{ reg = <0x00>; compatible ="arm,cortex-a53"; device_type ="cpu"; }; }; intc@8000000{ phandle = <0x8002>; reg = <0x000x80000000x000x100000x000x80100000x000x10000>; compatible ="arm,cortex-a15-gic"; ranges; #size-cells =<0x02>; #address-cells =<0x02>; interrupt-controller; #interrupt-cells =<0x03>; }; timer { interrupts = <0x010x0d0x1040x010x0e0x1040x010x0b0x1040x010x0a0x104>; always-on; compatible ="arm,armv8-timer\0arm,armv7-timer"; }; apb-pclk { phandle = <0x8000>; clock-output-names ="clk24mhz"; clock-frequency = <0x16e3600>; #clock-cells =<0x00>; compatible ="fixed-clock"; }; pl011@9000000{ clock-names ="uartclk\0apb_pclk"; clocks = <0x80000x8000>; interrupts = <0x000x010x04>; reg = <0x000x90000000x000x1000>; compatible ="arm,pl011\0arm,primecell"; };};
在上述設(shè)備樹中只包含以下內(nèi)容:

使用下述命令將dts編譯為dtb,交由rt-thread去解析處理
dtc -Idts -O dtb -o qemu-virt.dtb qemu-virt.dts
使用如下命令啟動QEMU:
qemu-system-aarch64\ -machine virt,gic-version=2\ -cpu cortex-a53\ -smp1\ -m128M\ -kernel rtthread.elf\ -dtb qemu-virt.dtb\ -nographic
可以看到系統(tǒng)啟動成功LOG:
[I/rtdm.ofw] Booting RT-Thread on physical CPU 0x0[I/rtdm.ofw] Machine model: linux,dummy-virt[I/rtdm.ofw] Memory node(0) ranges: 0x0000000040000000 - 0x0000000048000000[I/mm.memblock] System memory:[I/mm.memblock] [0x0000000040000000, 0x0000000048000000][I/mm.memblock] Reserved memory:[I/mm.memblock] [0x0000000040080000, 0x00000000401ef000][I/mm.memblock] [0x00000000401ef000, 0x00000000441ef000][I/mm.memblock] [0x00000000441ef000, 0x00000000443ef000][I/mm.memblock] [0x00000000443ef000, 0x00000000443f5000][I/mm.memblock] physical memory region [0x0000000040000000-0x0000000040080000] installed to system page[I/mm.memblock] physical memory region [0x00000000443f5000-0x0000000048000000] installed to system page[I/mm.memblock] 63 MB memory installed to system page[I/osi.psci] Using PSCI v1.1 Function IDs[I/rtdm.ofw] Console: uart0()\ | /- RT - Thread Smart Operating System/ | \ 5.3.0 build Mar 19 2026 08102006 - 2024 Copyright by RT-Thread team[I/drivers.serial] Using /dev/ttyS0 as default console[E/DFS.fs] mount point(/proc) already mounted![I/rtdm.mnt] File system initializationdonehello rt-threadmsh />msh />msh /
4.3.2 設(shè)備樹多核啟動示例
在之前menuconfig中可以看到,當(dāng)前系統(tǒng)是支持 SMP的,并且qemu-virt64-aarch64默認(rèn)配置#define RT_CPUS_NR 4,這里啟動兩個CPU作為演示
那么我們需要額外配置一下設(shè)備樹,首先配置CPUS節(jié)點
cpus { #address-cells = <1>; #size-cells = <0>; cpu@0{ reg = <0>; enable-method= "psci"; compatible ="arm,cortex-a53"; device_type ="cpu"; }; cpu@1{ reg = <1>; enable-method= "psci"; compatible ="arm,cortex-a53"; device_type ="cpu"; };};
在這個CPU配置中,CPU多核啟動需要通過調(diào)用 PSCI來完成,所以設(shè)備樹中需要加入PSCI的節(jié)點,如下:
psci { migrate = <0xc4000005>; cpu_on = <0xc4000003>; cpu_off = <0x84000002>; cpu_suspend = <0xc4000001>; method= "hvc"; compatible ="arm,psci-1.0\0arm,psci-0.2\0arm,psci";};
使用下述命令將dts編譯為dtb,交由rt-thread去解析處理
dtc -Idts -O dtb -o qemu-virt.dtb qemu-virt.dts
使用如下命令啟動QEMU:
qemu-system-aarch64\ -machine virt,gic-version=2\ -cpu cortex-a53\ -smp1\ -m128M\ -kernel rtthread.elf\ -dtb qemu-virt.dtb\ -nographic
可以看到系統(tǒng)啟動成功LOG:
[I/rtdm.ofw] Booting RT-Thread on physical CPU 0x0[I/rtdm.ofw] Machine model: linux,dummy-virt[I/rtdm.ofw] Memory node(0) ranges: 0x0000000040000000 - 0x0000000048000000[I/mm.memblock] System memory:[I/mm.memblock] [0x0000000040000000, 0x0000000048000000][I/mm.memblock] Reserved memory:[I/mm.memblock] [0x0000000040080000, 0x00000000401ef000][I/mm.memblock] [0x00000000401ef000, 0x00000000441ef000][I/mm.memblock] [0x00000000441ef000, 0x00000000443ef000][I/mm.memblock] [0x00000000443ef000, 0x00000000443f5000][I/mm.memblock] physical memory region [0x0000000040000000-0x0000000040080000] installed to system page[I/mm.memblock] physical memory region [0x00000000443f5000-0x0000000048000000] installed to system page[I/mm.memblock] 63 MB memory installed to system page[I/osi.psci] Using PSCI v1.1 Function IDs[I/rtdm.ofw] Console: uart0()\ | /- RT - Thread Smart Operating System/ | \ 5.3.0 build Mar 20 2026 03142006 - 2024 Copyright by RT-Thread team[I/drivers.serial] Using /dev/ttyS0 as default console[E/DFS.fs] mount point(/proc) already mounted![I/rtdm.mnt] File system initializationdonehello rt-threadmsh />[I/cpu.aa64] Call cpu 1 on successmsh />msh />msh />
注:在之前所提到的,系統(tǒng)啟動時是根據(jù)設(shè)備樹來決定系統(tǒng)配置的,所以,即使我們定義了 #define RT_CPUS_NR 4 也還是啟動了2個CPU
如果將QEMU啟動時的參數(shù) -smp 修改的比設(shè)備樹中定義的多,或?qū)?RT_CPUS_NR 修改的比設(shè)備樹中定義的少,或?qū)⑾到y(tǒng)的SMP關(guān)掉會發(fā)生什么,這里建議上手驗證一下
-
RTOS
+關(guān)注
關(guān)注
25文章
870瀏覽量
123213 -
驅(qū)動開發(fā)
+關(guān)注
關(guān)注
0文章
142瀏覽量
12718 -
RT-Thread
+關(guān)注
關(guān)注
32文章
1639瀏覽量
45207
發(fā)布評論請先 登錄
從0到1教你寫RT-Thread之新建工程
基于RT-Thread的RoboMaster電控框架設(shè)計
基于RT-Thread的簡單物聯(lián)網(wǎng)溫控箱 | 技術(shù)集結(jié)
RT-Thread Vector軟件包:嵌入式開發(fā)的動態(tài)數(shù)組容器 | 技術(shù)集結(jié)
從0到1,教你徹底學(xué)透RT-Thread
RT-Thread全球技術(shù)大會:RT-Thread上的單元測試框架與運行測試用例
RT-Thread設(shè)備模型框架及創(chuàng)建注冊設(shè)備的實現(xiàn)
RT-Thread全球技術(shù)大會:RNDIS設(shè)備介紹及應(yīng)用
RT-Thread全球技術(shù)大會:RNDIS通信協(xié)議原理及主機(jī)驅(qū)動框架
淺析RT-Thread設(shè)備驅(qū)動框架
基于 RT-Thread 的 RoboMaster 電控框架(一)
基于RT-Thread的RoboMaster電控框架(二)
《RT-Thread設(shè)備驅(qū)動開發(fā)指南》基礎(chǔ)篇--以先楫bsp的hwtimer設(shè)備為例
RT-Thread 中設(shè)備樹的適配方法 | 技術(shù)集結(jié)
RT-Thread 新一代驅(qū)動框架 DM 揭秘:從設(shè)備樹到動態(tài)加載,徹底告別硬編碼 | 技術(shù)集結(jié)
評論