设备树开发

设备树

  1. 设备树描述的信息包括:CPU的数量和类别、内存基地址和大小、总线和桥、外设连接、中断控制器和中断使用情况、GPIO控制器和GPIO使用情况、Clock控制器和Clock使用情况。
  2. 以上信息被保存在一个ASCII文件中,类似于xml文件,在ARM Linux中,一个.dts文件对应一个ARM的machine放置在内核的arch/arm/boot/dts目录。
  3. 设备树文件用于操作系统中描述硬件,不需要对设备信息进行硬编码。
  4. 描述的每个信息体由被命名的结点和属性组成,并且结点本身可包含子结点。属性即为成对出现的name和value。
  5. 设备树源文件dts被编译成dtb二进制文件,在BootLoader运行时传递给操作系统,操作系统在对其进行展开为二叉树结构,从而产生一个硬件设备的拓扑图,有了该拓扑图,在编程过程中可以直接通过系统提供的接口获取到设备树中的结点和属性信息。

设备树的编译过程

编译工具:dtc,源代码位于内核 /scripts/dtc目录,在内核使能了Device Tree情况下,编译内核的时候主机工具dtc会被编译出来。在Linux内核的arch/arm/boot/dts/Makefile中,描述了当某种SoC被选中后,哪些.dtb文件会被编译出来,如与EXYNOS对应的.dtb包括:
dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ exynos-smdkv310.dtb \ exynos4412-origen.dtb\

CONFIG_ARCH_EXYNOS 变量在.config文件中指定
dtsi为通用代码,类似头文件可包含在其他文件中,include “xx.dtsi”

dtb文件的作用

传递给BootLoader,在加载内核时对设备树文件进行展开二叉树,并将设备注册入内核。

名称解释

DT:device tree 设备树
FDT:flattened device tree 展开后的设备树,二叉树结构
OF:OPEN Firmware 开发固件库
DTS:配置文件
DTSI:可以包含的设备树配置文件
DTB:设备树二进制文件
DTC:设备树编译工具

值类型

文本字符串(双引号):" xxx “; 无结束符
32位无符号整数(尖括号):< xx xx xx >; 可多个
二进制数据(方括号):[ xx xx xx ]; 可多个
多类型数据(逗号连在一起):” xx “, [ xx xx ], < xx xx xx >;
字符串列表:” xx ", " xx ";

语法

  1. 包含:#include “xxx.dtsi”
  2. 节点名称:< 名字 [@<设备地址>] >,方括号为可选填内容,名字不超过31位简单ascii字符串。设备地址填对应寄存器地址,也可以填其他用于区分同一名字不同功能节点的区分,例如1-10序号。
  3. 引用:节点名称前带有 xxx: < 名字 [@<设备地址>] >,则xxx的属性及方法将可以在该节点用进行使用。
  4. compatible属性:用于决定使用哪个设备驱动来绑定,一个字符串列表,格式为" <制造商>,<型号> ",可以为多个,其余字符表示其他与之兼容的设备
  5. #address-cells与#size-cells:表示指定子结点的reg格式,address-cells指定地址列表大小,而size-cells表示长度列表大小。例如#address-cells = <2>, #size-cells = <1>;则reg = <0x11 0x22 0x100>表示0x11为地址1,0x22为地址2,0x100为这两个地址对应的大小空间。
  6. 关于设备地址,分为三种:
    1. 内存映射设备:一般具有地址范围,对于32位地址可用1个cell来指定地址值和一个cell指定范围值。而对于64位则应该为2个cell指定地址值,因为数据技能记录无符号整型32位。还有一种为基地址、偏移和长度,也是用2个cell来指定地址值。
    2. 非内存映射设备:没有被映射到cpu的存储器总线上,虽然可有一个地址范围,但不是由CPU直接访问,而是父设备驱动程序代表CPU执行间接访问,例如I2C的从设备地址,通过I2C控制器发送地址来匹配从设备,该地址并不存在CPU存储器总线上。
    3. 范围(地址转换):根结点的地址空间是从CPU的视角进行描述的,根结点的直接子结点使用的也是这个地址域,非根结点的直接子结点就没有使用这个地址域,于是需要把这个地址进行转换,rangs这个属性就用于此目的。即实现子结点和父结点使用一样的地址域
  7. 描述中断的四个属性:
    1. interrupt-controler:一个空属性,定义该结点为一个接受中断的设备,即中断控制器。
    2. #interrupt-cells:一个中断控制器结点的属性,声明该控制器的中断指示符中cell格式。
    3. interrupt-parents:一个设备结点的属性,指向设备所连接的中断控制器。
    4. interrupt:一个设备结点的属性,含一个中断指示符的列表,对应该设备的每一个中断输出信号。
    5. 中断指示符:第一个 cell为中断类型:0 SPI / 1 PPI / 2 IRQ;第二个cell为中断号:SPI[0-987] / PPI[0-15] IRQ[看手册]; 第三个为触发方式: 1表示上升沿,2下降沿,4高电平,8低电平,而可以用宏定义。
  8. aliases:用于结点的别名,例如aliases { spi0 = &spi_0; } 指定spi_0的别名为spi0.
  9. chosen:结点并不代表真正的设备,而是一个为固件和操作系统传递数据的地方,例如引导参数bootargs。

设备树相关操作

  1. 在设备树文件中添加结点:在目录arch/arm/boot/dts/xxx.dts文件下添加相关结点信息。
  2. 内核加载设备树文件生成树状结构,并且在目录/proc/device-tree中查看加载的结点。
  3. OF固件库提供的函数位于drivers/of目录下,常用的有以下:
根据device_node结构的full_name参数,在全局链表of_allnodes中查找适合的device_node
struct device_node *of_find_node_by_path
struct device_node *of_find_node_by_name

根据property结构的name参数,在指定的device_node中查找适合的property属性
struct property *of_find_property

根据compat参数与device_node的compatible匹配,返回匹配度
int of_device_is_compatible

获得父节点
struct device_node *of_get_parent

根据属性名propname,读出该属性的数组中sz个属性值给out_values
int of_property_read_u32_array

读取该设备的第index个irq号
unsigned int irq_or_parse_and_map
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值