LinuxDown

LinuxDown.com
Linux系统下载网——精选每一篇高品质的技术干货
  1. 首页
  2. 开源快讯
  3. 正文

ARM内核的组成和结构设备树的应用和使用情况

2023年7月12日 131点热度

linux设备树

参考地址

1.为何要使用设备树(DeviceTree)?

在先前的内核源码中,存在大量对板级细节信息描述的代码,这种代码参杂在/arch/arm/plat-xxx和/arch/arm/mach-xxx目录,对内核而言这种platform设备、resource、i2c_board_info、spi_board_info以及各类硬件的platform_data绝大多数纯属垃圾冗余代码。为了解决这一问题,ARM内核版本3.x以后引入了原本在PowerPC等其他体系构架早已使用的FlattenedDeviceTree。DTS不是arm的专利

在使用了设备树后linux移植时需要编译设备树文件吗,对于同一SOC的不同显卡,只需更换设备树文件.dtb即可实现不同显卡的无差别支持,而无需更换内核文件。

2.设备树的的组成和结构

设备树可以描述的信息包括了

1.CPU的数目和类别、

2.显存基地址和大小、

3.总线和桥、

4.外设联接、

5.中断控制器和中断使用情况、

6.GPIO控制器和GPIO使用情况、

7.Clock控制器和Clock使用情况。

linux移植时需要编译设备树文件吗_编译程序的移植_编译设备树文件命令

须要注意的是,设备树对于可热拔插的热备不进行具体描述,它只描述用于控制该热拔插设备的控制器

2.1设备树的组成

设备树包含了DTC(devicetreecompiler),DTS(devicetreeresource)和DTB(devicetreeblob),简单来说,dts是源码,dtc是编译器,dtb是生成的可执行文件

2.1.1DTS和DTSI

.dts和.dtsi是一种ASCII文本的设备树描述,此文本格式非常适合人们阅读,基本上,一个.dts对应一种ARM设备,放在arch/arm/boot/dts目录,由于一个soc对应好多个不同的开发板,每个开发板有一个.dts,所以这些dts势必有共同部分,为了减少代码的屯余,设备树将这些共同部分提炼保存在dtsi中,供不同的dts使用,dtsi文件类似于c语言的头文件

2.1.2DTC

DTC为编译工具,它可以将.dts文件编译成.dtb文件。DTC的源码坐落内核的scripts/dtc目录,内核选中CONFIG_OF,编译内核的时侯linux命令chm,主机可执行程序DTC都会被编译下来

2.1.3DTB

DTB设备由DTC编译后的二补码格式的设备树描述,可以由linux内核解析,uboot这样的bootloader也可以辨识.dtb,有两种使用方法,一种是bootloader启动内核过程中会先读取dtb到文件中;第二种是把dtb和zImage打包在一起弄成一个印象文件,firefly-3399就是采用这些方法,打包生成了boot.img

2.1.4绑定(bingding)

对于DeviceTree中的结点和属性具体是怎样来描述设备的硬件细节的,通常须要文档来进行讲解,文档的后缀名通常为.txt。那些文档坐落内核的Documentation/devicetree/bindings目录,其下又分为好多子目录

linux移植时需要编译设备树文件吗_编译程序的移植_编译设备树文件命令

2.1.5Bootloader使用dtb

在Uboot中,可以从NAND、SD或则TFTP等任意介质将.dtb读入显存,假定.dtb装入的显存地址为0x71000000,然后可在Uboot运行命令fdtaddr命令设置.dtb的地址,如:

U-Boot>fdtaddr0x71000000

fdt的其他命令就变地可以使用,如fdtresize、fdtprint等

对于ARM来讲,可以透过bootzkernel_addrinitrd_addressdtb_address的命令来启动内核,即dtb_address作为bootz或则bootm的最后一次参数,第一个参数为内核映像的地址,第二个参数为initrd的地址,若不存在initrd,可以用-取代,第三个就是dtb地址

2.2设备树框架

设备树用树形结构描述设备信息,它有以下几种特点

1.每位设备树文件都有一个根节点,每位设备都是一个节点。

2.节点间可以嵌套,产生父女关系,这样就可以便捷的描述设备间的关系。

3.每位设备的属性都用一组key-value对(通配符对)来描述。

4.每位属性的描述用;结束

3.设备树句型

设备树是一颗树,书上的每位节点由节点和属性组成,属性是通配符对

下边这个是rk3399-fpga.dts

#include "rk3399.dtsi"  //包含了公共部分
/ {
        model = "Rockchip RK3399 FPGA Board";
        compatible = "rockchip,fpga", "rockchip,rk3399"; //根节点兼容性分析,下面具体分析
        chosen {
                bootargs = "init=/init console=uart,mmio32,0xff1a0000";
        };
        memory@00000000 { //子节点  memory@00000000节点名
                device_type = "memory";
                reg = <0x0 0x00000000 0x0 0x20000000>;
        };
};
&uart2 { //使用了引用
        status = "okay";
        clocks = , ;
};

3.1根节点兼容性

compatible = "rockchip,fpga", "rockchip,rk3399";

上面是根节点的兼容属性,定义了整个系统(设备级别)的名称,通过这个属性就可以判断出它启动的是什么设备。它的组织形式是<manufacture><model>,在实际中一般包括两个或两个以上的兼容字符串,上面第一个是"rockchip,fpga",第二个是"rockchip,rk3399",我们来看第二个,manufacture是板子级别的名字,“rockchip”代表的是瑞芯微公司,model是芯片级别的,“rk3399”是瑞芯微公司一个soc的名称

我们从源码中找出rk3399的两个dts,可以看出第一个兼容字符串的model不同,第二个完全相同

rk3399-firefly-linux.dts
compatible = "rockchip,rk3399-firefly-linux", "rockchip,rk3399";
rk3399-fpga.dts
compatible = "rockchip,fpga", "rockchip,rk3399";

3.2节点名

理论个节点名只要是宽度不超过31个字符的ASCII字符串即可,Linux内核还约定设备名应写成形如[@]的方式,其中name就是设备名,最长可以是31个字符宽度。unit_address通常是设备地址,拿来惟一标示一个节点

Linux中的设备树还包括几个特殊的节点,例如chosen,chosen节点不描述一个真实设备,而是用于firmware传递一些数据给OS,例如bootloader传递内核启动参数给内核

chosen{
    bootargs = "console=ttySAC2,115200";
    stdout-path=&serial_2;
};

3.3引用

当我们找一个节点的时侯,我们必须书写完整的节点路径,这样当一个节点嵌套比较深的时侯就不是很便捷,所以,设备树容许我们用下边的方式为节点标明引用(起别称),亦即省去繁杂的路径。这样就可以实现类似函数调用的疗效

3.KEY

在设备树中,通配符对是描述属性的方法,例如linux 软件,Linux驱动中可以通过设备节点中的”compatible”这个属性查找设备节点

inux设备树句型中定义了一些具有规范意义的属性,包括:compatible,address,interrupt等,这种信息才能在内核初始化找到节点的时侯,手动解析生成相应的设备信息。据悉,还有一些Linux内核定义好的,一类设备通用的有默认意义的属性,这种属性通常不能被内核手动解析生成相应的设备信息,并且内核早已编撰的相应的解析提取函数,常见的有“mac_addr”,”gpio”linux移植时需要编译设备树文件吗,”clock”,”power”。”regulator”等等。

patible

设备节点中对应的节点信息早已被内核构造成structplatform_device。驱动可以通过相应的函数从中提取信息。主要有三种方式提取信息

    1、compatible属性是用来查找节点
    2、通过节点名查找指定节点
    3、节点路径查找指定节点

看一个使用compatible提取属性的事例

#dts
    gpio_demo: gpio_demo {
        status = "okay";
        compatible = "firefly,rk3399-gpio";                  
    };
#驱动代码
static struct of_device_id firefly_match_table[] = {
    { .compatible = "firefly,rk3399-gpio",}, //完全相同
    {}, //最后一个成员一定是空,因为相关的操作API会读取这个数组直到遇到一个空。
};

3.2address

        pinctrl: pinctrl {
                compatible = "rockchip,rk3399-pinctrl";
                #address-cells = ;
                #size-cells = ;
                gpio0: gpio0@ff720000 {
                        compatible = "rockchip,gpio-bank";
                        reg = <0x0 0xff720000 0x0 0x100>;
                        //前两个数字表示一个地址0x0 0xff720000
                        //后两个数字表示一个地址跨度 0x100
                };
            ...
    }

3.3interrupts

一个计算机系统中大量设备都是通过中断恳求CPU服务的,所以设备节点中就须要在指定中断

3.4gpio

firefly-gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;          /* GPIO0_B4 */
firefly-irq-gpio = <&gpio4 29 IRQ_TYPE_EDGE_RISING>;  /* GPIO4_D5 */  

4.DTB的加载过程

参考地址

总的归纳为:

①kernel入口处获取到uboot传过来的.dtb镜像的基地址

②通过early_init_dt_scan()函数来获取kernel初始化时须要的bootargs和cmd_line等系统引导参数。

③调用unflatten_device_tree函数来解析dtb文件,建立一个由device_node结构联接而成的双向数组,并使用全局变量of_allnodes保存这个数组的头表针。

④内核调用OF的API插口,获取of_allnodes数组信息来初始化内核其他子系统、设备等。

5.API调用

#来查找在dtb中的根节点
unsigned long __init of_get_flat_dt_root(void)
# 根据deice_node结构的full_name参数,在全局链表of_allnodes中,查找合适的device_node
struct device_node *of_find_node_by_path(const char *path)
#若from=NULL,则在全局链表of_allnodes中根据name查找合适的device_node
struct device_node *of_find_node_by_name(struct device_node *from,const char *name)
#根据设备类型查找相应的device_node
struct device_node *of_find_node_by_type(struct device_node *from,const char *type)
# 根据compatible字符串查找device_node
struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compatible)
#根据节点属性的name查找device_node
struct device_node *of_find_node_with_property(struct device_node *from,const char *prop_name)
#根据compat参数与device node的compatible匹配,返回匹配度
int of_device_is_compatible(const struct device_node *device,const char *compat)
#获得父节点的device node
struct device_node *of_get_parent(const struct device_node *node)
#读取该设备的第index个irq号
unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
#读取该设备的第index个irq号,并填充一个irq资源结构体
int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
#获取该设备的irq个数
int of_irq_count(struct device_node *dev)

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 中断 内核 描述 节点 设备
最后更新:2023年7月12日

Linux系统下载网

每日更新,欢迎收藏♥ 不积跬步无以至千里,加油,共勉。

点赞
< 上一篇
下一篇 >

Linux系统下载网

每日更新,欢迎收藏♥
不积跬步无以至千里,加油,共勉。

最新 热点 随机
最新 热点 随机
Linux系统助你轻松查看sh文件内容 熠熠生辉的C语言Linux开发者的好书和技术参考资料 fedora win7 双系统 Fedora与Win7双系统完美融合 Windows10版本1803和更高版本重置密码18031803 yum安装PHP5.4的亲身体验系统管理员 编译流程(12、GCC、hello.s)预处理 不同操作系统中比较常见的文件系统定义是什么 快速掌握fedora终端打开技巧 Ubuntu下软件安装的几种方式,及apt工具的使用 Red Hat Linux AS下载对比 深度解析Linux网络带宽测试,揭秘速度与激情 文件路径例子及应用软件下载工具 Fedora安装Steam,一键搞定 修改root用户的密码需要注意哪些问题? Linux僵死:解决与预防 开始开发小程序的第一步,你的小程序之旅 Linux移植:地址划分与分配解析 应用软件工程师的隐形之道:驱使硬件设备行动 Linux命令与Shell脚本实践:九个重点指南 phpWeChat微信+网站开发框架功能亮点解析!安装方法
完成远程连接以后就可以安装图形化界面,配置低了会比较卡Linux系统助你轻松查看sh文件内容快速了解Linux内核版本,查看命令揭秘!SUSELinux12SP5的安装步骤及安装方法Linux部署Tomcat项目对比评测基于精简指令集计算原理建立的CPU体系结构有不同的特点和应用场景Linux操作系统:端口查进程用做ASIC芯片的EDA仿真工具来做FPGA的仿真调试ghost linux系统 备受瞩目的Ghost Linux:稳定性与性能共赢Centos7无人值守安装系统架构及工作原理启动畅行编程世界,掌握Linux Java环境LinuxCentOS7中如何安装字体库以及中文字体?Linux Find命令:简单使用正则统计次数本地Windows远程桌面连接阿里云Ubuntu16.04服务器:1linux 解压zip文件 (Linux基础知识)Linux常用的压缩命令和常见用法打造高效稳定的Linux网络应用(Linux基础知识)linuxuserdel命令是系统管理员命令解决Linux命令行中文乱码问题Linux内核下载地址,Linux之旅加速!《Linux命令大全Linuxscp命令》命令
高效编译内核,轻松上手嵌入式Linux驱动开发pdf 北京时间Asia/Shanghai时区语言和键盘7安装配置 centos awstats CentosAwstats日志分析工具对比 → CentosAwstats:全面对比日志分析工具 掌握Linux发行版本查看技巧,轻松了解系统信息 基于RedHatLinux的企业级查看发行版本的系统的方法 安装后系统默认不会自动启动的服务,避免不必要损失和麻烦 Linux系统安装串口转换驱动教程 Linux更改目录主人,简单易学! 哪些电脑可安装Linux?十大特点解析! Linux系统虚拟界面全方位解析 红帽Linux全线开放下载 1.主动信息搜集直接访问目标对其进行工具扫描 一种嵌入式Linux操作系统的构建方法:王晓辉,孙新贺 Linux轻松驾驭 DOS,命令完美融合 玩转Linux:掌握fork函数,实现高效编程 快速掌握Linux版本号查看方法,轻松操作! Linux用户空间SP安全策略应用 关于Linux服务器内存清理的一些常见问题及解决办法 下载SUSE Linux虚拟机,开启Linux软件开发 打造高效稳定的Linux网络应用
标签聚合
命令 linux系统 linux服务器 安装 内核 文件 应用 操作 软件 电脑
书籍
课程
技术群
技术干货大合集↓
  • 2023年9月 / 118篇
  • 2023年8月 / 122篇
  • 2023年7月 / 122篇
  • 2023年6月 / 119篇
  • 2023年5月 / 123篇
  • 2023年4月 / 113篇
  • 2023年3月 / 265篇
友情链接:

Linux书籍 | Linux命令 | Linux系统 | RHCE红帽认证 | Linux软件 | Linux教程 | CentOS系统 | Linux内核 | Linux服务器 | Linux大神 | IT资源

COPYRIGHT © 2023 LinuxDown.com ALL RIGHTS RESERVED.

京ICP备14023444号-2