设备树使用简介
时间:2019-11-01 15:06来源:ZLG立功科技·致远电子
摘要:是不是所有的Linux内核都是完美的?毕竟诸多黑客效力于此,当然不是,至少在内核3x版本之前不是,之前的代码臃肿,代码利用率较低,直到设备树的引入,彻底改善这一情况;
一、FDT的概念
系统启动时,Bootloader开始加载,将内核文件,如zImage读取到内存中,内核按照我们的代码,逐一去配置每个寄存器,每个外设,似乎没有什么问题。但是试想一下,100种ARM芯片,就要写100个配置文件么?当然,如果你非要这么做,我也无话可说。如果能抽象出一种数据结构,它可以直接抽象出内核需要配置的所有硬件以及硬件属性,BootLoader预读取到内存中,在内核启动以后,可以直接配置,对于用户而言,配置MCU的外围时我们直接面对的就只是这个DTS文件,极其方便快捷。FDT准确来讲是一种数据结构,使得硬件可以用形如XML的描述语言来描述。
二、设备树结构
► 根节点“/”下的model ,这个一般为字符串类型,它描述了厂商以及板子名称;
► 根节点“/”下的compitable,这个一般为字符串类型,用以匹配model选定的开发板对应的代码;包括后续外围驱动的匹配均是有这个compitable来完成;
► 根节点“/”下的aliases,这个设备节点只能放在根节点目录,主要用以存放外设的别名,简单讲,"/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000"其实是一个串口,但是开发人员自己看起来并不直观,我可以在aliases中写作:serial ="/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000";serial即可代替刚才的串口设备;
► 根节点“/”下的chosen:这个并非物理设备节点,而是内核启动参数的节点,类似于uboot阶段的bootargs参数;
当然,这个节点也可以是子节点,不一定要在根节点下;
实例:chosen {
stdout-path = &uart1;
};
Ø snvs@020b0000:除以上节点,剩下的我一般称之为物理设备节点(可能不准确),以snvs外设举例,直接举例;
实例:snvs@020b0000{
conpitable = “fsl,imx6ul-snvs”;
reg = <0x020b0000 0x4000>;
interrupts = <0x0 0x4 0x4>;
};
(1)“@”后面紧跟就是该外设在MCU总线的地址,这个不难理解,可以理解为外设的基地址,外设模型 name@addresss;”
(2)“compitable”:如上陈述,非常关键的属性,匹配外设驱动,属性模型 compitable = “[manufacture,[model]]”;
(3)“reg”:该属性为外设地址属性,第一个参数为该节点总线地址,后者为地址长度;
(4)“interrupt”:顾名思义,该外设的中断,para1表示该中断是不是SPI中断(shared peripheral interrupt),注意名词区分,参数值为1表示为SPI中断,反之不是SPI中断;para2是该中断号;para3表示触发方式,参数值为1,表示上升沿触发,为4表示高电平触发;如果需要低电平以及下降沿触发,硬件需要加非门;
三、编译设备树与反编译
设备树编译,我们都知道使用如下命令编译:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs 或者
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all
实际上,是dtc这个文件在负责把dts解释成dtb文件,该文件在内核源码根目录 ./scripts/dtc
编译命令:
./scripts/dtc/dtc –I dts –O dtb /home/gyh/tmp/imx6y2c-256m.dtb ./arch/arm/boot/dts/imx6y2c-256m.dts
反编译命令:
./scripts/dtc/dtc -I dtb -O dts -o /home/gyh/tmp/imx6y2c_asm.dts ./arch/arm/boot/dts/imx6y2c-256m.dtb
对于Linux命令的使用,可以使用help cmdname 或者man cmdname,对于dtc,非内建命令,man dtc:
-I
Input formats are:
dts - device tree source text
dtb - device tree blob
fs - /proc/device-tree style directory
-O
四、设备树节点添加与验证
(1)直接在dts文件中查找,是否已经存在你需要的外设节点;如果有,且该外设支持多从机或者多节点,直接在该节点下面,添加子节点,以GPIO_LED为例。
(4)如果之前已经完全编译过内核,可以直接编译dtb,注意不要make menuconfig或者defconfig,否则会覆盖zImage的配置文件.config;
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs
(5)编译完成后,开发板直接进入uboot模式,tftp网络烧写dtb,reset重启生效;
run updtb
(备注:updtb为组合命令updtb=if tftp ${fdt_file}; then nand erase.part dtb; nand write ${loadaddr} dtb ${filesize}; fi;)
(6)如果dtb按照我们理解修改是正确的,那么我们将在开发板的/sys/class/leds下面看到我们的My_Cute这个LED节点;结果如下:
(7)文件IO操作:打开My_Cute节点,可以看到以下接口可以操作,但是我们在添加GPIO_LEDS并没有添加这些属性。Brightness, trigger—led亮度以及触发方式比较常用,那么问题来了,为什么会有这些接口。因为它们继承了母节点的属性,所以我们需要找到母节点设备的定义。
五、结语
设备树相比于传统的配置文件,无疑是降低了Linux外设开发与使用的门槛,但是也隐藏了大量的细节,难以了解其底层的驱动原理;对于LINUX内核的了解,我所认识的还不及冰山一角,单希望对你有一点帮助。
系统启动时,Bootloader开始加载,将内核文件,如zImage读取到内存中,内核按照我们的代码,逐一去配置每个寄存器,每个外设,似乎没有什么问题。但是试想一下,100种ARM芯片,就要写100个配置文件么?当然,如果你非要这么做,我也无话可说。如果能抽象出一种数据结构,它可以直接抽象出内核需要配置的所有硬件以及硬件属性,BootLoader预读取到内存中,在内核启动以后,可以直接配置,对于用户而言,配置MCU的外围时我们直接面对的就只是这个DTS文件,极其方便快捷。FDT准确来讲是一种数据结构,使得硬件可以用形如XML的描述语言来描述。
二、设备树结构
图一 设备树结构
设备树一般包含以上内容:► 根节点“/”下的model ,这个一般为字符串类型,它描述了厂商以及板子名称;
► 根节点“/”下的compitable,这个一般为字符串类型,用以匹配model选定的开发板对应的代码;包括后续外围驱动的匹配均是有这个compitable来完成;
► 根节点“/”下的aliases,这个设备节点只能放在根节点目录,主要用以存放外设的别名,简单讲,"/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000"其实是一个串口,但是开发人员自己看起来并不直观,我可以在aliases中写作:serial ="/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000";serial即可代替刚才的串口设备;
► 根节点“/”下的chosen:这个并非物理设备节点,而是内核启动参数的节点,类似于uboot阶段的bootargs参数;
当然,这个节点也可以是子节点,不一定要在根节点下;
实例:chosen {
stdout-path = &uart1;
};
Ø snvs@020b0000:除以上节点,剩下的我一般称之为物理设备节点(可能不准确),以snvs外设举例,直接举例;
实例:snvs@020b0000{
conpitable = “fsl,imx6ul-snvs”;
reg = <0x020b0000 0x4000>;
interrupts = <0x0 0x4 0x4>;
};
(1)“@”后面紧跟就是该外设在MCU总线的地址,这个不难理解,可以理解为外设的基地址,外设模型 name@addresss;”
(2)“compitable”:如上陈述,非常关键的属性,匹配外设驱动,属性模型 compitable = “[manufacture,[model]]”;
(3)“reg”:该属性为外设地址属性,第一个参数为该节点总线地址,后者为地址长度;
(4)“interrupt”:顾名思义,该外设的中断,para1表示该中断是不是SPI中断(shared peripheral interrupt),注意名词区分,参数值为1表示为SPI中断,反之不是SPI中断;para2是该中断号;para3表示触发方式,参数值为1,表示上升沿触发,为4表示高电平触发;如果需要低电平以及下降沿触发,硬件需要加非门;
三、编译设备树与反编译
设备树编译,我们都知道使用如下命令编译:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs 或者
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all
实际上,是dtc这个文件在负责把dts解释成dtb文件,该文件在内核源码根目录 ./scripts/dtc
编译命令:
./scripts/dtc/dtc –I dts –O dtb /home/gyh/tmp/imx6y2c-256m.dtb ./arch/arm/boot/dts/imx6y2c-256m.dts
反编译命令:
./scripts/dtc/dtc -I dtb -O dts -o /home/gyh/tmp/imx6y2c_asm.dts ./arch/arm/boot/dts/imx6y2c-256m.dtb
对于Linux命令的使用,可以使用help cmdname 或者man cmdname,对于dtc,非内建命令,man dtc:
-I
Input formats are:
dts - device tree source text
dtb - device tree blob
fs - /proc/device-tree style directory
-O
图二 BSP提供的dts文件
图三 反编译的dts文件
对同一个chosen节点:BSP中dts描述为stdout-path = &uart1;这样很难想象它是怎样把该外设定义为标准输出的,但是如果看反编译文件可以较好的理解,标准输出被重定向到某个可以作为输出的外设地址;四、设备树节点添加与验证
(1)直接在dts文件中查找,是否已经存在你需要的外设节点;如果有,且该外设支持多从机或者多节点,直接在该节点下面,添加子节点,以GPIO_LED为例。
图四 GPIO_LEDS节点
(2)假设,你需要添加一个黄色的LED,那么仿照已经存在的节点,复制一个节点在母节点下,命名为green-led,同时用GPIO3_4为该LED驱动引脚;你希望在arm板上叫他,My_Cute(这个名字不好),那么最后修改如下:图五 增加yellow-led节点
(3)节点添加完成,引用了GPIO3_4,所以你需要确认该MCU引脚已经配置为GPIO功能,这里直接贴出配置代码:MX6UL_PAD_LCD_RESET__GPIO3_IO04 0x40017059图六 引脚配置为GPIO
该宏定义MX6UL_PAD_LCD_RESET__GPIO3_IO04在./arch/arm/boot/dts/imx6ull-pinfunc.h中;针对同一个引脚的全部复用,均定义了宏,可以直接调用;该dts并未直接包含imx6ull-pinfunc.h,在其他dtsi中已经包含该头文件;(4)如果之前已经完全编译过内核,可以直接编译dtb,注意不要make menuconfig或者defconfig,否则会覆盖zImage的配置文件.config;
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs
(5)编译完成后,开发板直接进入uboot模式,tftp网络烧写dtb,reset重启生效;
run updtb
(备注:updtb为组合命令updtb=if tftp ${fdt_file}; then nand erase.part dtb; nand write ${loadaddr} dtb ${filesize}; fi;)
(6)如果dtb按照我们理解修改是正确的,那么我们将在开发板的/sys/class/leds下面看到我们的My_Cute这个LED节点;结果如下:
图七 开发板设备截图
其实,可以看到/sys/class/leds下面的设备节点都是指向/devices/platfome/leds目录的连接文件,也就是这里仅仅是这个设备的“快捷方式”,我们也可以进行文件IO操作;(7)文件IO操作:打开My_Cute节点,可以看到以下接口可以操作,但是我们在添加GPIO_LEDS并没有添加这些属性。Brightness, trigger—led亮度以及触发方式比较常用,那么问题来了,为什么会有这些接口。因为它们继承了母节点的属性,所以我们需要找到母节点设备的定义。
图八 yellow-led的操作接口
(8)讲道理,所有的内核驱动你都可以尝试在 ./driver/下面去找,针对led类,我们直接进入leds文件夹,发现leds的驱动leds-gpio.c在,在这里就可以理解led的接口为什么是这样;当然优秀的驱动应该还有一份清晰的文档,你同样可也尝试去源码根目录的. /Documentation 中查找leds-gpio的使用文档;这里也会解释,我为什么会去开发板的/sys/class/leds下面去查看我增加的My_Cute节点;图九 驱动使用文档
(9)增加一个驱动或者一个设备节点到设备树中,你可以先查看内核源码的/ Documentation目录,其中包含了几乎所有驱动的使用说明以及设备树属性的解释,同时也包括大量优秀的内核调试技巧;再去写节点,也可以先模仿,针对不懂的地方再来看文档,印象更为深刻。五、结语
设备树相比于传统的配置文件,无疑是降低了Linux外设开发与使用的门槛,但是也隐藏了大量的细节,难以了解其底层的驱动原理;对于LINUX内核的了解,我所认识的还不及冰山一角,单希望对你有一点帮助。
免责声明:本文若是转载新闻稿,转载此文目的是在于传递更多的信息,版权归原作者所有。文章所用文字、图片、视频等素材如涉及作品版权问题,请联系本网编辑予以删除。
我要投稿
近期活动
- 安森美汽车&能源基础设施白皮书下载活动时间:2024年04月01日 - 2024年10月31日[立即参与]
- 2023年安森美(onsemi)在线答题活动时间:2023年09月01日 - 2023年09月30日[查看回顾]
- 2023年安森美(onsemi)在线答题活动时间:2023年08月01日 - 2023年08月31日[查看回顾]
- 【在线答题活动】PI 智能家居热门产品,带您领略科技智慧家庭时间:2023年06月15日 - 2023年07月15日[查看回顾]
- 2023年安森美(onsemi)在线答题活动时间:2023年06月01日 - 2023年06月30日[查看回顾]
分类排行榜
- 汽车电子电源行业可靠性要求,你了解多少?
- 内置可编程模拟功能的新型 Renesas Synergy™ 低功耗 S1JA 微控制器
- Vishay 推出高集成度且符合 IrDA® 标准的红外收发器模块
- ROHM 发布全新车载升降压电源芯片组
- 艾迈斯半导体推出行业超薄的接近/颜色传感器模块,助力实现无边框智能手机设计
- 艾迈斯半导体与 Qualcomm Technologies 集中工程优势开发适用于手机 3D 应用的主动式立体视觉解决方案
- 维谛技术(Vertiv)同时亮相南北两大高端峰会,精彩亮点不容错过
- 缤特力推出全新商务系列耳机 助力解决开放式办公的噪音难题
- CISSOID 和泰科天润(GPT)达成战略合作协议,携手推动碳化硅功率器件的广泛应用
- 瑞萨电子推出 R-Car E3 SoC,为汽车大显示屏仪表盘带来高端3D 图形处理性能
编辑推荐
小型化和稳定性如何兼得?ROHM 推出超小型高输出线性 LED 驱动器 IC,为插座型 LED 驱动 IC 装上一颗强有力的 “心脏”
众所周知,LED的驱动IC担负着在输入电压不稳定的情况下,为LED提供恒定的电流,并控制恒定(可调)亮度的作用。无论是室内照明,还是车载应用,都肩负着极为重要的使命。
- 关于反激电源效率的一个疑问
时间:2022-07-12 浏览量:10197
- 面对热拔插阐述的瞬间大电流怎么解决
时间:2022-07-11 浏览量:8951
- PFC电路对N线进行电压采样的目的是什么
时间:2022-07-08 浏览量:9593
- RCD中的C对反激稳定性有何影响
时间:2022-07-07 浏览量:7205
- 36W单反激 传导7~10M 热机5分钟后超标 不知道哪里出了问题
时间:2022-07-07 浏览量:5979
- PFC电感计算
时间:2022-07-06 浏览量:4189
- 多相同步BUCK
时间:2010-10-03 浏览量:37870
- 大家来讨论 系列之二:开机浪涌电流究竟多大?
时间:2016-01-12 浏览量:43165
- 目前世界超NB的65W适配器
时间:2016-09-28 浏览量:60029
- 精讲双管正激电源
时间:2016-11-25 浏览量:128135
- 利用ANSYS Maxwell深入探究软磁体之----电感变压器
时间:2016-09-20 浏览量:107562
- 【文原创】认真的写了一篇基于SG3525的推挽,附有详细..
时间:2015-08-27 浏览量:100301