Linux基于设备树的驱动开发

本文介绍了Linux设备树的基础知识,详细阐述了设备树的语法规则,并探讨了如何在Linux内核驱动中使用OF函数获取设备树参数,以驱动具体设备。同时,提到了在驱动开发中涉及的pinctrl和gpio子系统。
摘要由CSDN通过智能技术生成

一、Linux设备树的简介

        设备树的诞生主要是为了解决RAM架构CPU日益增多,对应的设备种类更多的情况;很多设备描述无关紧要,按照传统的设备描述驱动方法会造成Linux系统的冗余;所以外设属性的描述独立于Linux就成为了DTS。

DTS、DTB和DTC:

        DTS是设备树的源码文件;DTB则是将DTS编译以后得到的可以被系统识别的二进制文件。从DTS到DTB需要专用的编译器来编译,也就是所谓的DTC。在Linux的源码目录里,通过命令 make dtbs就可以编译出设备树。

如何在Linux源码中添加自己的dts文件并编译出dtb:

在Linux内核源码目录下,路径./arch/arm/boot/dts/下,有个Makefile文件,找到你使用的SOC对应的配置选项(每种RAM有多种SOC半导体CPU),选项内容如(dtb-$(CONFIG_SOC_XXXX));在对应选项中添加自己写的dts对应的xxx.dtb,然后SOC选项配置为y,就可以编译出来了。

xxx.dtsi头文件:每一块soc都有一个公共的设备树,也就是dtsi,具体的板子的具体外设则叫dts。

 

二、Linux设备树的语法规则(基础篇

1、xxx.dtsi头文件与引用

        与C语言一样,设备树文件也有语法  #include <xxx.h> 或  #include <xxx.dtsi>;用于引用C语言的头文件或其他的设树头文件。编写设备树头文件的时候,最好使用后缀.dtsi。

        一般来说,xxx.dtsi文件是SOC(核心板)用于描述其内部的外设信息的,包括CPU和时钟树;基于此SOC的开发板编写的dts文件都要引用这个xxx.dtsi文件。

//

2、设备节点的概念与规范

① /{}  根节点,每个完整的设备树有且只有一个根节点,如果设备树文件所引用的头文件里也有根节点的话,跟节点会自动合并为一个。

② node-name@unit-address节点命名格式:node-name是节点名字,为ASCII字符串;unit-address用于表示设备的地址或寄存器首地址,如果某个节点没有地址或寄存器的话,可以不要。

③ 节点的标签label:node-name@unit-address:标签+:后才是节点的定义;引入标签的目的就是为了方便访问节点,可以直接通过&label来访问这个节点。

④ 每个节点下面,都有属性定义,格式:键 = 值。节点下面也可以嵌套子节点。

//

3、常用的标准属性

① compatible属性(重要)

基本格式:compatible  = "manufacturer,model","manufacturer,model",......;

内容含义:manufacturer表示驱动或设备的厂商,model表示该设备需要使用的驱动模块;这个属性值与Linux内核驱动的OF匹配表如果有匹配项,则会使用对应的驱动程序来驱动设备。

② model属性

基本格式:model = "xxxx";

内容含义:一般model属性用于描述设备的模块信息,比如模块名称啥的。

③ status属性

基本格式:status = "xxx";

内容含义:与设备运行状态有关,一般的,设备有如下几个运行状态;每个状态的具体含义需要参照设备的手册说明

④ #address-cells和#size-cells属性

基本格式:#address-cells = <number>;  #size-cells = <number>;

内容含义:首先,对于拥有子节点的节点属性值,此值才有用,因为他们控制的是子节点的!!#address-cells决定了子节点属性中reg这个属性的地址信息所占用的字长(32位/字);#size-cells决定了子节点属性中,reg这个属性的地址长度值所占用的字长。

⑤ reg属性

基本格式:reg = <address lenght>,<address lenght>,......;

内容含义:一般用于描述某个外设的物理寄存器的地址占用信息。

⑥ ranges属性

基本格式:ranges = <child-bus-address parent-bud-address length>;  也可以为空

内容含义:child-bus-address表示子总线地址空间的物理地址,由父节点的#address-cells决定字长;parent-bus-address表示父总线地址空间的物理地址,同样由父节点的#address-cells决定字长;length表示子地址空间的物理地址长度,由父节点的#size-cells确定此地址长度所占用的字长。如果此项目为空,标志该节点设备的子地址与父地址空间完全相同,不需要转换(可以理解为相对地址与绝对地址的转换)。

⑦ device_type属性

基本格式:device_type = "xxx";

内容含义:这个属性值只有CPU和memory节点会使用,其他设备节点已经弃用了。

//

4、根节点的compatible属性与Linux启动原理:

① 基本原理:根节点所定义的compatible属性值,第一个值代表板子的类型,第二个值代表使用的SOC;Linux内核在启动时,会读取这个属性值和内核里的DT_MACHINE_START里的各种设备信息做比对,如果找到值相同的则启动内核。

② Linux内核的匹配过程:

//

5、设备树中的特殊节点:

① aliases 子节点:这个是专门用来给其他设备节点定义别名的,但一般我们会在每个设备节点上定义label,所以可以不用

② chosen子节点:这个节点并不是一个真实的设备,closen节点主要是为了uboot向linux内核传递数据,重点是bootargs参数。u-boot引导linux内核启动前会往这个节点传递数据,证据如下:

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值