设备树
这个不是linus设计的,是linus借鉴别人的。这个是Open Firmware的设计,常见于powerPC等架构中,linus觉得很好,就把他引进到了linux中了,使用它的目的,也是为了统一管理和分配硬件,减少代码量。所以,遇到哪个of开头的文件和api,因为它来自Open Firmware哦。
使用设备树的时候,先看看uboot是否支持设备树,不支持就找打uboot的一些头文件增加#define CONFIG_OF_LIBFDT /* Device Tress support */试试
再看看菜单中是否开启了设备树功能,在cpu.c中引用了头文件 。比如kernel/arch/arm/mach-s5p6818/cpu.c。
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
在cpu_init_machine添加“加载设备树函数of_platform_populate”
1 | const struct of_device_id of_default_bus_match_table[] = { |
在比较新的linux内核中,设备树dts已经取代了传统的machine board device description,dts
在内核中以各种device node的形式存在,而这些device node对于大部分的内核驱动模块
platform_driver来说,最终需要有对应的platform device来与他匹配才可以完成一次device和
driver的probe过程。
所有有必要将dts中需要加载为device的device node转为platform device,而这个过程是交给
of_platform_populate来完成的(dts相关的device node tree是在main.c中的start_kernel-
>setup_arch->unflatten_device_tree来加载dtb并解析)。
1 | void __init unflatten_device_tree(void) |
MACHINE_START 改为DT_MACHINE_START,并在其中增加设备树匹配信息。
设备树文件
DTS 、DTC、DTB、
DTS是设备树源码,就是描绘了硬件的配置;如地址、大小、种类、外设配置等
DTC是编译设备树的编译工具,这个需要install下单编译器
1 | #dtc 工具安装: |
DTB是可执行文件,经过上面的编译之后,可以被编译器识别的文件。可以加到特定位置同内核一起运行,也可以加到内核所在设备树目录中一起编译到内核之中。
设备树语法
设备树该怎么写呢?首先,一个树肯定就是有主干,这个主干,不是我们这些小卡拉米写的,所以,顶多是在芯片原厂的基础上增加一些自己的设备。
枝叶这个该怎么写呢?首先,你得让编译器和主干识别到我这个枝叶吧,这就像一个叶子,一定有叶柄才能和主干连接,而我们修改不过是叶子的形状和功能,所以,开头一定要有一个和主干一模一样的开头。这个就是叶柄了。如下面这种结构:
1 | /* |
语法开始:这个就简单的说一下设备树语法,只有使用的时候再去仔细看一下需要的。
Linux设备树学习笔记(一、设备树语法规范)_reg = <0x00 0x80000000 0x00 0x60000000>;-CSDN博客
设备树5个使用方法
1.将dtb文件拷贝到根文件系统(推荐,利于调试)
/* 从根文件系统拷贝dtb文件,更方便,更利于调试 */
setenv bootcmd ext4load mmc 2:2 0x42000000 gec6818.dtb ;ext4load mmc 2:1 0x48000000
uImage ;bootm 0x48000000 - 0x42000000
saveenv
2.挂载开发板内核镜像分区,将dtb拷贝到该分区(安全性高,用户不能随意修改或删除)
mount -t ext4 /dev/mmcblk0p1 /mnt
cp gec6818.dtb /mnt
umount /mnt
/* 拷贝到内核镜像的分区 */
setenv bootcmd ext4load mmc 2:1 0x42000000 gec6818.dtb ;ext4load mmc 2:1 0x48000000
uImage ;bootm 0x48000000 - 0x42000000
saveenv
3.使用网络,配置uboot环境变量。
setenv bootcmd tftp 0x42000000 gec6818.dtb ; ext4load mmc 2:1 0x48000000 uImage ;
bootm 0x48000000 - 0x42000000
4.不使用网络,可以使用串口下载dtb文件到内存地址0x42000000。
loady 0x42000000
setenv bootcmd ext4load mmc 2:1 0x48000000 uImage ; bootm 0x48000000 - 0x42000000
saveenv
5.将dtb文件编译到boot.img,重新烧录内核。
在ubuntu中
将文件拷贝到一个/target/product/6818/boot的目录之下
./mk -k
在uboot中
setenv bootcmd ext4load mmc 2:1 0x42000000 gec6818.dtb ;ext4load mmc 2:1 0x48000000
uImage ;bootm 0x48000000 - 0x42000000
驱动使用设备树节点
驱动想要使用设备树,只能使用平台设备方法的,此时平台设备platform_driver中的dirver结构体中的of_match_table这个就要指向所满足需求的
1 | static const struct of_device_id of_led_match[]={ |
此时,这个驱动就知道,该找到compatible=”gec,myled”的要求的设备树节点,读取这个节点上面的数据(引脚号和介绍),此时驱动就知道有这个led设备了,就可以控制对应的GPIO引脚的高低电平。
1 | struct platform_device *pdev;//已经对应上的平台设备 |
总结
设备树,就是省去了,对硬件的描述的复杂和多种写法,统一写法,节约空间和利于管理。