当前位置: 首页 > news >正文

I.MX6ULL内核开发10:设备树

目录

一、设备树简介

二、设备树源码

三、获取设备树信息

1、增加设备节点

2、内核编译设备树

3、替换设备树文件

4、查看设备树节点

5、在驱动中获取节点的属性

6、编译驱动模块

7、加载模块


一、设备树简介

设备树的作用是描述一个硬件平台的硬件资源。这个“设备树”可以被bootloader(uboot)传递到内核,内核可以从设备树中获取硬件信息。

几个常见的文档缩写符号:

  • DTS:是指.dts格式的文件,是一种ASII文本格式的设备树描述,设备树源码,一般一个.dts文件对应一个硬件平台。
  • DTC:是指编译设备树源码的工具,一般情况下需要手动安装。
  • DTB:是设备树源码编译生成的文件,类似于C语言中的“.bin”文件,可以被硬件识别。

二、设备树源码

文件定位:内核源码/arch/arm/boot/dts/imx6ull-mmc-npi.dts

/*----------------------头文件--------------------------*/
#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"/*----------------------中间部分--------------------------*// {model = "Embedfire i.MX6ULL Board";compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";aliases {pwm0 = &pwm1;pwm1 = &pwm2;pwm2 = &pwm3;pwm3 = &pwm4;};chosen {stdout-path = &uart1;};memory {reg = <0x80000000 0x20000000>;};reserved-memory {#address-cells = <1>;#size-cells = <1>;ranges;linux,cma {compatible = "shared-dma-pool";reusable;size = <0x14000000>;linux,cma-default;};};/*-------------以下内容省略--------------------*/
};
/*------------------追加部分--------------------------*/
&cpu0 {/*dc-supply = <&reg_gpio_dvfs>;*/clock-frequency = <800000000>;
};&clks {assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;assigned-clock-rates = <786432000>;
};/*------------------以下内容省略--------------------------*/

文件位置:内核源码/arch/arm/boot/dts/imx6ull.dtsi

cpus {#address-cells = <1>;#size-cells = <0>;cpu0: cpu@0 {compatible = "arm,cortex-a7";device_type = "cpu";/*----------以下内容省略-----------------*/};};

设备树源码分为3部分:

  • 第1-2行:头文件。头文件的引用有两种,一种为“.h”文件,一种为“.dtsi文件”。imx6ull.dtsi由NXP官方提供,是一个imx6ull平台“共用”的设备树文件。
  • 中间部分:设备树节点。由{}组成,每一个设备树都只有一个“/”节点。
  • 追加部分:&的意思是像原有的节点中追加内容。

三、获取设备树信息

1、增加设备节点

        在ebf_linux_kernel/arch/arm/boot/dts/imx6ull-mmc-npi.dts这个设备树中,尝试增加一个新的设备节点。

led_test{#address-cells = <1>;#size-cells = <1>;rgb_led_red@0x0209C000{compatible = "fire,rgb_led_red";reg = <0x0209C000 0x00000020>;status = "okay";};
};
  • 以上节点中,#address-cells = <1>,#size-cells = <1>,意味着它的子节点的reg属性里的数据是“地址”、“长度”交替的。
  • 第二部分led的子节点,定了三种属性,分别为compatible、reg、status。由于在父节点设置了#address-cells = <1>,#size-cells = <1>,所以0x0209C000表示的是地址(这里填写的GPIO1控制寄存器的首地址),0x00000020表示的是地址长度。

2、内核编译设备树

        编译内核时会自自动编译设备树,到那时编译内核非常耗时,所以可以用以下命令只编译设备树。

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs

执行结果如下:

 编译成功后生成的设备树文件(.dtb)位于源码目录下/arch/arm/boot/dts/,文件名为“imx6ull-mmc-npi.dtb”

3、替换设备树文件

        将上位机上生成的.dtb文件替换掉开发板中的.dtb文件,替换/usr/lib/linux-image-4.19.35-imx6/imx6ull-mmc-npi.dtb。

uboot在启动的时候负责将该目录的设备我呢见加载到内存,供内核使用。

4、查看设备树节点

        设备树的设备节点在文件系统中有与之相对应的文件,位于/proc/device-tree目录,进入目录查看如下:

 接着进入led_test文件夹,可以发现led_test节点中定义的属性以及它的子节点,如下所示。

 在节点属性中多了一个name,我们在led节点中并没有定义name属性,这是自己生成的,保存节点名。

这里的属性是一个文件,而子系欸但是一个文件夹,再次进入“rgb_led_red@0x0209C000”文件夹。里面有compatible name regs status四个属性文件。我们可以使用“cat”命令查看这些属性文件,如下所示:

 至此,成功的在设备树中添加了一个名为“led_test”的节点。

5、在驱动中获取节点的属性

        实验是一个简化的字符设备驱动,在驱动中没有实际操作硬件,仅在.open函数中调用of函数获取设备树节点中的属性,获取成功后打印获取到的内容。

代码:get_dts_info.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/io.h>#include <linux/of.h>
#include <linux/of_address.h>#define DEV_NAME            "get_dts_info"
#define DEV_CNT                 (1)
//定义字符设备的设备号
static dev_t led_devno;
//定义字符设备结构体chr_dev
static struct cdev led_chr_dev;
//创建类
struct class *led_chrdev_class;struct device_node	*led_device_node; //led的设备树节点
struct device_node  *rgb_led_red_device_node; //rgb_led_red 红灯节点
struct property     *rgb_led_red_property;    //定义属性结构体指针
int size = 0 ;
unsigned int out_values[18];  //保存读取得到的REG 属性值/*.open 函数*/
static int led_chr_dev_open(struct inode *inode, struct file *filp)
{int error_status = -1;printk("\n open form device \n");/*获取DTS属性信息*/led_device_node = of_find_node_by_path("/led_test");if(led_device_node == NULL){printk(KERN_ALERT "\n get led_device_node failed ! \n");return -1;}/*根据 led_device_node 设备节点结构体输出节点的基本信息*/printk(KERN_ALERT "name: %s",led_device_node->name); //输出节点名printk(KERN_ALERT "child name: %s",led_device_node->child->name);  //输出子节点的节点名/*获取 rgb_led_red_device_node 的子节点*/ rgb_led_red_device_node = of_get_next_child(led_device_node,NULL); if(rgb_led_red_device_node == NULL){printk(KERN_ALERT "\n get rgb_led_red_device_node failed ! \n");return -1;}printk(KERN_ALERT "name: %s",rgb_led_red_device_node->name); //输出节点名printk(KERN_ALERT "parent name: %s",rgb_led_red_device_node->parent->name);  //输出父节点的节点名/*获取 rgb_led_red_device_node 节点  的"compatible" 属性 */ rgb_led_red_property = of_find_property(rgb_led_red_device_node,"compatible",&size);if(rgb_led_red_property == NULL){printk(KERN_ALERT "\n get rgb_led_red_property failed ! \n");return -1;}printk(KERN_ALERT "size = : %d",size);                      //实际读取得到的长度printk(KERN_ALERT "name: %s",rgb_led_red_property->name);   //输出属性名printk(KERN_ALERT "length: %d",rgb_led_red_property->length);        //输出属性长度printk(KERN_ALERT "value : %s",(char*)rgb_led_red_property->value);  //属性值/*获取 reg 地址属性*/error_status = of_property_read_u32_array(rgb_led_red_device_node,"reg",out_values, 2);if(error_status != 0){printk(KERN_ALERT "\n get out_values failed ! \n");return -1;}printk(KERN_ALERT"0x%08X ", out_values[0]);printk(KERN_ALERT"0x%08X ", out_values[1]);return 0;
}/*.release 函数*/
static int led_chr_dev_release(struct inode *inode, struct file *filp)
{printk("\nrelease\n");return 0;
}/*字符设备操作函数集*/
static struct file_operations  led_chr_dev_fops = 
{.owner = THIS_MODULE,.open = led_chr_dev_open,.release = led_chr_dev_release,
};/*
*驱动初始化函数
*/
static int __init led_chrdev_init(void)
{int ret = 0;printk("led chrdev init\n");//第一步//采用动态分配的方式,获取设备编号,次设备号为0,//设备名称为EmbedCharDev,可通过命令cat  /proc/devices查看//DEV_CNT为1,当前只申请一个设备编号ret = alloc_chrdev_region(&led_devno, 0, DEV_CNT, DEV_NAME);if(ret < 0){printk("fail to alloc led_devno\n");goto alloc_err;}led_chrdev_class = class_create(THIS_MODULE, "led_chrdev");//第二步//关联字符设备结构体cdev与文件操作结构体file_operationscdev_init(&led_chr_dev, &led_chr_dev_fops);//第三步//添加设备至cdev_map散列表中ret = cdev_add(&led_chr_dev, led_devno, DEV_CNT);if(ret < 0){printk("fail to add cdev\n");goto add_err;}//创建设备device_create(led_chrdev_class, NULL, led_devno, NULL,DEV_NAME);return 0;add_err://添加设备失败时,需要注销设备号unregister_chrdev_region(led_devno, DEV_CNT);
alloc_err:return ret;
}/*
*驱动注销函数
*/
static void __exit led_chrdev_exit(void)
{printk("chrdev exit\n");device_destroy(led_chrdev_class, led_devno);   //清除设备cdev_del(&led_chr_dev);                        //清除设备号unregister_chrdev_region(led_devno, DEV_CNT);  //取消注册字符设备class_destroy(led_chrdev_class);               //清除类
}module_init(led_chrdev_init);
module_exit(led_chrdev_exit);MODULE_LICENSE("GPL");
  •  使用“of_find_node_by_path”函数勋章“led_test”设备节点。参数是“led_test”的设备节点路径。
  • 获取成功后得到的是一个device_node类型的结构体指针,然后就可以从这个结构体中获得想要的数据。获取完整的属性可能还需要使用其他of函数。
  • 获取rgb_led_red_device_node的子节点,在上一部分中获取的“led”节点的“设备节点结构体”,这里就可以使用“of_get_next_child”函数获取它的子节点。也可以从“led”节点的“设备节点结构体”中直接读取它的第一个子节点。
  • 使用“of_find_property”函数获取“rgb_led_red”节点的“compatiable”属性
  • 使用“of_property_read_u32_array”函数获取reg属性

6、编译驱动模块

        命令:make

        生成get_dts_info.ko驱动模块

7、加载模块

        将ko文件拷贝到开发板,使用insmod安装模块然后可以在/dev/目录找到get_dts_info 

         向模块中随便输入一个字符

        sudo sh -c "echo '1' >> /dev/get_dts_info"


 可以看出已经成功打印出led节点属性和rgb_led_red字节点属性。

相关文章:

I.MX6ULL内核开发10:设备树

目录 一、设备树简介 二、设备树源码 三、获取设备树信息 1、增加设备节点 2、内核编译设备树 3、替换设备树文件 4、查看设备树节点 5、在驱动中获取节点的属性 6、编译驱动模块 7、加载模块 一、设备树简介 设备树的作用是描述一个硬件平台的硬件资源。这个“设备树…...

【大数据】记一次hadoop集群missing block问题排查和数据恢复

问题描述 集群环境总共有2个NN节点&#xff0c;3个JN节点&#xff0c;40个DN节点&#xff0c;基于hadoop-3.3.1的版本。集群采用的双副本&#xff0c;未使用ec纠删码。 问题如下&#xff1a; bin/hdfs fsck -list-corruptfileblocks / The list of corrupt files under path…...

国产音质好的蓝牙耳机有哪些?国产音质最好的耳机排行

随着时间的推移&#xff0c;真无线蓝牙耳机逐渐占据耳机市场的份额&#xff0c;成为人们日常生活中必备的数码产品之一。蓝牙耳机品牌也多得数不胜数&#xff0c;哪些国产蓝牙耳机音质好&#xff1f;下面&#xff0c;我们从音质出来&#xff0c;来给大家介绍几款国产蓝牙耳机&a…...

CTFer成长之路之XSS的魔力

XSS的魔力CTF XSS闯关 题目描述: 你能否过关斩将解决所有XSS问题最终获得flag呢&#xff1f; docker-compose.yml version: "3.2"services:xss:image: registry.cn-hangzhou.aliyuncs.com/n1book/web-xss:latestports:- 3000:3000启动方式 docker-compose up -…...

行锁、表锁、主键外键、表之间的关联关系

Java知识点总结&#xff1a;想看的可以从这里进入 目录2.4、行锁、表锁2.5、主键、外键2.5.1、主键2.5.2、外键2.6、表的关联关系2.4、行锁、表锁 MyISAM默认采用表级锁&#xff0c;InnoDB默认采用行级锁。 表锁&#xff1a;开销小&#xff0c;加锁快&#xff0c;不会出现死锁…...

JavaScript 进阶(面试必备)--charater4

文章目录前言一、深浅拷贝:one: 浅拷贝:two:深拷贝二、异常处理:one: throw 抛异常:two: try /catch 捕获异常:three:debugger三、处理thisthis指向 :one:普通函数this指向this指向 :two: 箭头函数this指向3.2 改变this:one: call():two: apply():three: bind()四、性能优化:on…...

ARM+FPGA架构开发板PCIE2SCREEN示例分析与测试-米尔MYD-JX8MMA7

本篇测评由电子发烧友的优秀测评者“zealsoft”提供。 本次测试内容为米尔MYD-JX8MMA7开发板其ARM端的测试例程pcie2screen并介绍一下FPGA端程序的修改。 ​ 01. 测试例程pcie2screen 例程pcie2screen是配合MYD-JX8MMA7开发板所带的MYIR_PCIE_5T_CMOS 工程的测试例&#…...

51单片机入门 - SDCC / Keil_C51 会让没有调用的函数参与编译吗?

Small Device C Compiler&#xff08;SDCC&#xff09;是一款免费 C 编译器&#xff0c;适用于 8 位微控制器。 不想看测试过程的话可以直接划到最下面看结论&#xff1a;&#xff09; 关于软硬件环境的信息&#xff1a; Windows 10STC89C52RCSDCC &#xff08;构建HEX文件&…...

OpenCV只含基本图像模块编译

编译OpenCV4.5.5只含基本图像模块&#xff0c;环境为Windows10 x64CMake3.23.3VS2019。默认编译选项编译得到的OpenCV库往往大几百MB甚至上GB&#xff0c;本文配置下编译得到的库压缩后得到的zip包大小仅6.25MB&#xff0c;适合使用OpenCV基本图像功能模块的项目移植而不牵涉其…...

Java实现阴历日历表(附带星座)

准备工作 1.无敌外挂(GitHub直达源码) Nobb 直击灵魂 https://github.com/xuyishanBD/Java_create_calendar.git2.maven配置(如果没有走上面的捷径) <dependencies><dependency><groupId>net.sourceforge.javacsv</groupId><artifactId>javac…...

Python入门之最基础

Python入门之最基础 IDLE有两种模式&#xff0c;一种是交互模式&#xff0c;通俗讲就是写一个代码&#xff0c;会得到相应的反馈&#xff0c;另一种为编辑模式. 注意事项&#xff1a; 标点符号一定要用英文符号 要注意缩进 dir(builtins)可以看到python所有的内置函数&#…...

浏览器缓存策略

先走强缓存&#xff0c;再走协商缓存 强缓存 不发送请求&#xff0c;直接使用缓存的内容 状态码200 当前会话没有关闭的话就是走memory cache&#xff0c;否则就是disk cache 由响应头的 Pragma&#xff08;逐渐废弃&#xff0c;优先级最高&#xff09;&#xff0c;catch-…...

高清无码的MP4如何采集?python带你保存~

前言 大家早好、午好、晚好吖 ❤ ~ 又是我,我又来采集小姐姐啦~ 这次我们采集的网站是(看下图): 本文所有模块\环境\源码\教程皆可点击文章下方名片获取此处跳转 话不多少,我们赶快开始吧~ 第三方模块: requests >>> pip install requests 如果安装python第三方模块…...

python+pytest接口自动化(1)-接口测试基础

接口定义一般我们所说的接口即API&#xff0c;那什么又是API呢&#xff0c;百度给的定义如下&#xff1a;API&#xff08;Application Programming Interface&#xff0c;应用程序接口&#xff09;是一些预先定义的接口&#xff08;如函数、HTTP接口&#xff09;&#xff0c;或…...

go单元测试

接着上一篇中的go module创建项目calc为例&#xff0c;在simplemath包中&#xff0c;是使用在命令行中使用交互式的方式进行测试&#xff0c;现在可以为这几个函数实现单元测试&#xff0c; go test&#xff0c;这个测试工具来自于 Go 官方的 gc 工具链。 运行 go test 命令将执…...

Mybatis之一级缓存二级缓存

介绍 缓存&#xff0c;就是将经常访问的数据&#xff0c;放到内存中&#xff0c;减少对数据库的访问&#xff0c;提高查询速度。Mybatis中也有缓存的概念&#xff0c;分为一级缓存和二级缓存。 一级缓存 一级缓存是Mybatis中SqlSession对象的缓存。当我们执行查询以后&#x…...

人脸考勤机项目

文章内容如下&#xff1a; 1&#xff09;项目简介 2&#xff09;开发环境和使用的技术知识 3&#xff09;功能实现 4&#xff09;项目源码 一。项目简介 此项目是基于HOG和Dlib开发的一套实时无感考勤系统。首先是待考勤人员的个人信息录入。然后在过道或者入口处装置人脸…...

Python编程自动化办公案例(3)

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.前几章代码 1.获取到第一题的选项单元格 2.实现批量获取文件 二. 批…...

Linux-MYSQL 登录数据库(命令行,图形化) 及 远程登录

命令行登录 &#xff1a;mysql 命令登录数据库语法 &#xff1a; mysql -u用户名 -p密码 -h 连接的数据库服务器的ip [-D] 数据库名 -p 端口注 &#xff1a; 上面的 mysql 命令是指的是 客户端的指令 ~&#xff01;&#xff01;-h &#xff1a; 指的就是 连接数据库服务器的 ip…...

electron网络环境在线/离线事件探测

electron判断网络环境问题&#xff0c;可以说在任何桌面应用都可以使用到&#xff0c;处理方式有很多种&#xff0c;我介绍几种办法第一种HTML5 API navigator.onLine&#xff1a;官方案例给的&#xff0c;这边为直接贴出地址了&#xff0c;有兴趣的同学可自行查看https://www.…...

UE 项目导航数据生成配置

WP构建及常规构建操作WP构建方式 &#xff1a;https://docs.unrealengine.com/5.0/zh-CN/world-partitioned-navigation-mesh/常规构建方式针对WP的构建方式特殊配置项关闭就好&#xff1a;取消勾选RecastNavMesh-XXX下的IsWorldPartitioned执行n.bNavMeshAllowPartitionedBuil…...

494.目标和

1. 回溯算法 这题和之前做的那些排列、组合的回溯稍微有些不同&#xff0c;你不需要每次选数据时都是for遍历去选择&#xff0c;很明显这是顺序选择的 比如 数组[0,1]&#xff0c;target1&#xff1b; 递归数组&#xff0c;每个元素都 或者 - &#xff0c;然后取最后结果为0…...

滑台模组的应用有哪些?

在自动化生产中&#xff0c;我们常常会看到滑台模组的身影&#xff0c;那么&#xff0c;滑台模组究竟在自动化生产设备中起着怎样的作用呢&#xff1f; 简单点说&#xff0c;滑台模组由滑块、滚珠丝杆、导轨、主体等其它传动零件组成的自动化晋级单元&#xff0c;经过各单元的组…...

CS224W课程学习笔记(四):node2vec算法原理与说明

引言 什么是图嵌入&#xff1f; 我想从上节的deepwalk中已经有一个十分完整的轮廓了&#xff0c;这里引出deepwalk论文中的一张很形象的图&#xff08;当然&#xff0c;上节的一些实战演练&#xff0c;也将这种嵌入关系进行了模拟与可视化&#xff0c;前文为&#xff1a;&…...

扩展lucas定理

前置知识&#xff1a; lucas定理中国剩余定理 介绍 当正整数n,mn,mn,m很大&#xff0c;且质数ppp较小的时候&#xff0c;要求CnmC_n^mCnm​对ppp取模后的值&#xff0c;可以用lucas定理。 但如果ppp不是质数&#xff0c;那该怎么办呢&#xff1f;如果mmm较小&#xff0c;则…...

医疗影像工具LEADTOOLS 入门教程: 从 PDF 中提取附件 - 控制台 C#

LEADTOOLS 是一个综合工具包的集合&#xff0c;用于将识别、文档、医疗、成像和多媒体技术整合到桌面、服务器、平板电脑、网络和移动解决方案中&#xff0c;是一项企业级文档自动化解决方案&#xff0c;有捕捉&#xff0c;OCR&#xff0c;OMR&#xff0c;表单识别和处理&#…...

【LVGL】学习笔记--(1)Keil中嵌入式系统移植LVGL

一 LVGL简介最近emwin用的比较烦躁&#xff0c;同时被LVGL酷炫的界面吸引到了&#xff0c;所以准备换用LVGL试试水。LVGL(轻量级和通用图形库)是一个免费和开源的图形库&#xff0c;它提供了创建嵌入式GUI所需的一切&#xff0c;具有易于使用的图形元素&#xff0c;美丽的视觉效…...

Transformer学习笔记

Transformer学习笔记1. 参考2. 模型图3.encoder部分3.1 Positional Encoding3.2 Muti-Head Attention3.3 ADD--残差连接3.4 Norm标准化3.5 单个Transformer Encoder流程图4.decoder部分4.1 mask Muti-Head Attention4.2 Muti-Head Attention5 多个Transformer Encoder和多个Tra…...

vue-cli引入wangEditor、Element,封装可上传附件的富文本编辑器组件(附源代码直接应用,菜单可调整)

关于Element安装引入&#xff0c;请参考我的另一篇文章&#xff1a;vue-cli引入Element Plus&#xff08;element-ui&#xff09;&#xff0c;修改主题变量&#xff0c;定义全局样式_shawxlee的博客-CSDN博客_chalk variables 1、安装wangeditor npm i wangeditor --savewangE…...

移动办公时代,数智化平台如何赋能企业管理升级?

在传统的办公模式下&#xff0c;企业组织办公不仅时效低&#xff0c;周期长、成本高&#xff0c;且各办公系统相互独立。随着社会经济的发展&#xff0c;人们的工作生活变得多样化&#xff0c;对于办公的需求也越来越多&#xff0c;存在明显弊端的传统办公模式已不能满足企业对…...