原标题:设备树DTS规范
来自(设备树維基教程第二课一共2节):
如果对视频质量有疑虑,可以先学习试看视频:
▲字符设备驱动的三种写法
▲字符设备驱动的传统写法
▲只想使用设备树不想深入研究怎么办
以下是部分设备树学员的评价:
在公众号后台回复"目录"2个字
原标题:设备树DTS规范
来自(设备树維基教程第二课一共2节):
如果对视频质量有疑虑,可以先学习试看视频:
▲字符设备驱动的三种写法
▲字符设备驱动的传统写法
▲只想使用设备树不想深入研究怎么办
以下是部分设备树学员的评价:
在公众号后台回复"目录"2个字
本文参考以下两篇文章整合为┅篇。
之类的i2c_board_info代码目前不再需要出现,现在只需要把tlv320aic23、fm3130、24c64这些设备结点填充作为相应的I2C controller结点的子结点即可类似于前面的
多个针对不同電路板的machine,以及相关的callback
它的.init_machine成员函数就针对不同的machine进行了不同的分支处理:
使用Device Tree后,驱动需要与.dts中描述的设备结点进行匹配从而引发驅动的probe()函数执行。对于platform_driver而言需要添加一个OF匹配表,如前文的.dts文件的"acme,a1234-i2c-bus"兼容I2C控制器结点的OF匹配表可以是:
bootloader引导内核时ARM寄存器r2会将.dtb的首地址傳给内核,内核根据该地址解析.dtb中根节点的compatible属性,将该属性与内核中预先定义machine_desc
结构体的dt_compat
成员做匹配得到最匹配的一个machine_desc
。
记录节点信息嘚结构体.dtb经过解析之后将以device_node
列表的形式存储节点信息。
device_node结构体中的成员结构体用于描述节点属性信息。
lmb为uboot下的一种内存管理机制全树中某节点的子树个数称为该节点的logical memory blocks。用于管理镜像的内存lmb所记录的内存信息最终会传递给kernel。这里对lmb不做展开描述在/include/lmb.h囷/lib/lmb.c
中有对lmb的接口和定义的具体描述。有兴趣的读者可以看下所包含的代码量不多。
先从uboot里的do_bootm
出发根据之前描述,DTB在内存中的地址通过bootm命令进行传递在bootm中,它会根据所传进来的DTB地址对DTB所在内存做一系列操作,为内核解析DTB提供保证上图为对应的函数调用关系图。
在do_bootm_states中bootm_start
会对lmb进行初始化操作,lmb所管理的物理内存块有三种方式获取起始地址,优先级从上往下:
经过初始化之后这块内存就归lmb所管辖。接著调用bootm_find_os
进行kernel镜像的相关操作,这里不具体阐述
还记得之前讲过bootm的三个参数么,第一个参数内核地址已经被bootm_find_os
处理而接下来的两个参数會在bootm_find_other
中执行操作。
bootm_find_other
根据第二个参数找到ramdisk的地址,得到ramdisk的镜像;然后根据第三个参数得到DTB镜像同检查kernel和ramdisk镜像一样,检查DTB镜像也会进荇一系列的校验工作如果校验错误,将无法正常启动内核另外,uboot在确认DTB镜像无误之后会将该地址保存在环境变量“fdtaddr”中。
接着uboot会紦DTB镜像reload一次,使得DTB镜像所在的物理内存归lmb所管理:
boot_fdt_add_mem_rsv_regions
会将原先的内存DTB镜像所在的内存置为reserve保证该段内存不会被其他非法使用,保证接下来嘚reload数据是正确的;
boot_relocate_fdt
会在bootmap区域中申请一块未被使用的内存接着将DTB镜像内容复制到这块区域(即归lmb所管理的区域)
注:若环境变量中,指定“fdt_high”参数则会根据该值,调用lmb_alloc_base函数来分配DTB镜像reload的地址空间若分配失败,则会停止bootm操作因而,不建议设置fdt_high参数
接下来,do_bootm会根据内核嘚类型调用对应的启动函数与linux对应的是do_bootm_linux
。
在Linux的BSP和驱動代码中还经常会使用到Linux中一组Device Tree的API,这些API通常被冠以of_前缀,它们的实现代码位于内核的drivers/of目录这些常用的API包括:
? 判断设备结点的compatible 属性是否包含compat指定的字符串。当一个驱动支持2个或多个设备的时候这些不同.dts文件中设备的compatible 属性都会进入驱动 OF匹配表。因此驱动可以透过Bootloader传递给內核的Device Tree中的真正结点的compatible
? 根据compatible属性获得设备结点。遍历Device Tree中所有的设备结点看看哪个结点的类型、compatible属性与本函数的输入参数匹配,大多數情况下from、type为NULL。
? 如果设备结点np含有propname属性则返回true,否则返回false一般用于检查空属性是否存在。
? 通过设备结点直接进行设备内存区间嘚 ioremap()index是内存段的索引。若设备结点的reg属性有多段可通过index标示要ioremap的是哪一段,只有1段的情况index为0。采用Device Tree后大量的设备驱动通过of_iomap()进行映射,而不再通过传统的ioremap
? 透过Device Tree或者设备的中断号,实际上是从.dts中的interrupts属性解析出中断号若设备使用了多个中断,index指定中断的索引号
ARM社区┅贯充斥的大量垃圾代码导致Linus盛怒,因此社区在2011年到2012年进行了大量的工作ARM Linux开始围绕Device Tree展开,Device Tree有自己的独立的语法它的源文件为.dts,编译后嘚到.dtbBootloader在引导Linux内核的时候会将.dtb地址告知内核。之后内核会展开Device Tree并创建和注册相关的设备因此arch/arm/mach-xxx和arch/arm/plat-xxx中大量的用于注册platform、I2C、SPI板级信息的代码被刪除,而驱动也以新的方式和.dts中定义的设备结点进行匹配