2-ARM Linux驱动开发-设备树平台驱动
一、概述
设备树(Device Tree)是一种描述硬件的数据结构,用于将硬件设备的信息传递给操作系统内核。它的主要作用是使内核能够以一种统一、灵活的方式了解硬件平台的细节,包括设备的拓扑结构、资源分配(如内存地址、中断号等)等信息,从而减少了将硬件信息硬编码到内核中的情况,增强了内核的可移植性和可维护性。
1、设备树的基本结构
1.节点(Node)
设备树以节点为基本单元,节点用于描述一个设备或者一个设备集合。每个节点都有一个名字,名字通常反映了设备的类型或者功能。例如,一个典型的节点名字可能是 “uart@0x1000”,其中 “uart” 表示这是一个串口设备,“0x1000” 可能是该设备的基地址。节点可以包含属性(Properties)和子节点(Child Nodes)。
2.属性(Properties)
属性是节点的重要组成部分,用于描述设备的各种特性。属性由键 - 值对(key - value pairs)组成。键是一个字符串,用于标识属性的名称,值可以是多种数据类型,如整数、字符串、字节数组等。例如,一个设备节点可能有一个属性 “compatible”,其值为 “nvidia,tegra - uart”,这个属性用于告诉内核该设备与哪种驱动程序兼容。
3.子节点(Child Nodes)
一个节点可以包含多个子节点,用于描述设备的层次结构。比如,在一个 SoC(片上系统)设备树中,可能有一个 “cpu” 节点,它下面会有多个代表不同 CPU 核心的子节点,每个子节点可以包含自己的属性,用于描述该核心的特性,如频率、缓存大小等。
2、基本概念
1.DTS(Device Tree Source)
DTS 是设备树源文件,它是一种文本格式的文件,用于描述硬件设备的详细信息。其内容包括设备的拓扑结构、设备之间的连接关系、资源分配(如内存地址、中断号等)以及设备的各种属性等。
这里的/{
表示根节点,node1
是根节点下的一个子节点,它有两个属性property1
和property2
,并且还有一个子节点child_node
,这个子节点有自己的属性child_property
。属性的值可以是整数(用<>
包围)、字符串(用双引号包围)等多种形式。
/{node1 {property1 = <value1>;property2 = "string_value";child_node {child_property = <value2>;}}
}
2.DTC(Device Tree Compiler)
DTC是设备树编译器,它是一个工具,用于将DTS文件编译成二进制的DTB文件。DTC会对DTS文件进行语法检查、格式转换等操作,以确保设备树信息的正确性和有效性,并将其转换为内核能够解析的二进制格式。
DTC读取DTS文件的文本内容,根据设备树的语法规则进行解析。它会识别节点、属性等元素,并将其转换为二进制格式存储在DTB文件中。在编译过程中,DTC还可以进行一些优化操作,例如去除注释、压缩数据等,以减小DTB文件的大小。
通常在构建内核或者制作嵌入式系统镜像时使用。例如,在交叉编译环境中,开发人员在完成DTS文件的编写后,会使用DTC工具将DTS编译为DTB文件,然后将DTB文件与内核镜像一起部署到目标设备上。
3.DTB(Device Tree Blob)
DTB是设备树二进制文件,它是DTS文件经过DTC编译后的产物。内核在启动过程中能够直接解析DTB文件来获取硬件设备的信息。文件包含了设备树的所有信息,不过是以二进制形式存储。它的结构包括头部信息(如文件版本、大小等)和设备树数据部分。数据部分按照一定的格式组织,内核通过特定的解析代码可以从中提取出设备节点、属性等信息。
当系统启动时,内核会读取 DTB 文件。例如,在一个基于 ARM 架构的嵌入式系统中,引导加载程序(如 U - Boot)会将 DTB 文件加载到内存中,然后内核启动时会解析 DTB 文件,根据其中的信息来识别硬件设备,如发现系统中的存储设备、网络设备等,并为这些设备分配资源,同时将设备与相应的驱动程序进行匹配。
4.DTSI(Device Tree Source Include)
DTSI 是设备树源文件包含(Include)文件。它也是一种文本格式的文件,主要用于将设备树描述信息进行模块化和复用。
在复杂的硬件系统中,可能有多个设备具有相同的基本属性或者结构。DTSI 文件可以用来定义这些通用的部分,然后在多个 DTS 文件中进行引用。例如,对于一个具有多个相同类型的 UART 设备的系统,可以将 UART 设备的通用属性(如基本的寄存器定义、中断处理方式等)定义在一个 DTSI 文件中,然后在每个具体描述 UART 设备的 DTS 文件中包含这个 DTSI 文件,从而减少代码的重复编写。
#include "xxx.dtsi"
二、实操
1、设备树文件修改
/include/ "system-conf.dtsi"
/ {chosen{bootargs = "earlycon console=ttyPS0,115200 clk_ignore_unused root=/dev/mmcblk0p2 rw rootwait";};gpio-led {compatible = "zynqMP-led";gpios = < &gpio 0x2A 0x0 &gpio 0x28 0x0>;};
};&gpio {emio-gpio-width = <32>;gpio-mask-high = <0x0>;gpio-mask-low = <0x5600>;status = "okay";
};&sdhci1 {clock-frequency = <100000000>;status = "okay";xlnx,mio_bank = <0x1>;no-1-8-v;disable-wp;
};&uart0 {cts-override ;device_type = "serial";port-number = <0>;status = "okay";u-boot,dm-pre-reloc ;
};&usb0 {status = "okay";xlnx,tz-nonsecure = <0x1>;xlnx,usb-polarity = <0x0>;xlnx,usb-reset-mode = <0x0>;
};
2、驱动文件编写
//1、添加头文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>static unsigned int led_major;
static struct class *led_class;struct led_driver
{int gpio1;int gpio2;int irq;struct device dev;
};
struct led_driver *led_dri = NULL;const struct file_operations led_fops = {};//在probe函数中打印获取数据包里面的名字及GPIO
int gpio_pdrv_probe(struct platform_device *pdev)
{struct device_node *node;unsigned int gpio1, gpio2;unsigned int ret = 0;printk("gpio pdrv probe!\n");printk("pdrv name = %s!\n", pdev->name);//申请主设备号led_major = register_chrdev(0, "led_drv", &led_fops);if (led_major < 0){printk("register chrdev led major error!\n");return -ENOMEM;}//创建类led_class = class_create(THIS_MODULE, "led_class");//创建设备device_create(led_class, NULL, MKDEV(led_major, 0), NULL, "led_device%d", 0);//硬件初始化//申请空间led_dri = devm_kmalloc(&pdev->dev, sizeof(struct led_driver), GFP_KERNEL);if (led_dri == NULL){printk("devm kmalloc led_driver error!\n");return -1;}//获取从设备节点传过来的pdev中的dev及node节点led_dri->dev = pdev->dev;node = pdev->dev.of_node;//3.从node节点处获得GPIO号gpio1 = of_get_gpio(node, 0);printk("of get gpio1 number = %d\n", gpio1); //GPIO基数 338 + 40,338 是 512 - 174 得到的。if (gpio1 < 0){printk("of get gpio error!\n");return -1;}gpio2 = of_get_gpio(node, 1);printk("of get gpio2 number = %d\n", gpio2); //GPIO基数 338 + 42if (gpio2 < 0){printk("of get gpio error!\n");return -1;}//4.申请GPIOret = gpio_request(gpio1, "plattree_led");if (ret < 0){printk("plattree led gpio request error!\n");return ret;}ret = gpio_request(gpio2, "plattree_led");if (ret < 0){printk("plattree led gpio request error!\n");return ret;}//5.设置GPIO为输出模式,并设备为0,灭灯gpio_direction_output(gpio1, 0);gpio_direction_output(gpio2, 0);led_dri->gpio1 = gpio1;led_dri->gpio2 = gpio2;return 0;
}int gpio_pdrv_remove(struct platform_device *pdev)
{printk("led pdrv remove!\n");//6.将gpio设为输出。gpio_set_value(led_dri->gpio1, 1);gpio_set_value(led_dri->gpio2, 1);gpio_free(led_dri->gpio1);gpio_free(led_dri->gpio2);device_destroy(led_class, MKDEV(led_major, 0));class_destroy(led_class);unregister_chrdev(led_major, "led_drv");return 0;
}//of_match_table实现
const struct of_device_id gpio_of_match_table[] = {{.compatible = "zynqMP-led",},{}
};//2.当驱动在设备中找到name之后,进行配对获取resource资源,进入probe函数
struct platform_driver gpio_drv = {.driver = {.name = "zynqmp_led",.of_match_table = gpio_of_match_table,},.probe = gpio_pdrv_probe,.remove = gpio_pdrv_remove,
};//实现装载入口函数和卸载入口函数
static __init int platform_gpio_drv_init(void)
{//1.创建pdrv,并且注册到总线中return platform_driver_register(&gpio_drv);
}
static __exit void platform_gpio_drv_exit(void)
{//7.注销设备platform_driver_unregister(&gpio_drv);
}//声明装载入口函数和卸载入口函数
module_init(platform_gpio_drv_init);
module_exit(platform_gpio_drv_exit);//添加GPL协议
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Popeye");
相关文章:

2-ARM Linux驱动开发-设备树平台驱动
一、概述 设备树(Device Tree)是一种描述硬件的数据结构,用于将硬件设备的信息传递给操作系统内核。它的主要作用是使内核能够以一种统一、灵活的方式了解硬件平台的细节,包括设备的拓扑结构、资源分配(如内存地址、中断号等)等信…...

C语言函数与递归
函数 函数是指将一组能完成一个功能或多个功能的语句放在一起的代码结构。在C语言程序中,至少会包含一个函数,主函数main()。本章将详细讲解关于函数的相关内容。 1、库函数 ⭕️C语言库函数是指在C语言标准库中预先定义好的函数,这些函数包…...

Linux下的Debugfs
debugfs 1. 简介 类似sysfs、procfs,debugfs 也是一种内存文件系统。不过不同于sysfs一个kobject对应一个文件,procfs和进程相关的特性,debugfs的灵活度很大,可以根据需求对指定的变量进行导出并提供读写接口。debugfs又是一个Li…...
【FFmpeg】调整音频文件的音量
1、调整音量的命令 1)音量调整为当前音量的十倍 ffmpeg -i inputfile -vol 1000 outputfile 2)音量调整为当前音量的一半 ffmpeg -i input.wav -filter:a "volume=0.5" output.wav3)静音 ffmpeg -i input.wav -filter:a "volume=0" output.wav4)…...
mac 打开访达快捷键
一、使用快捷键组合 1. Command N 在当前桌面或应用程序窗口中,按下“Command N”组合键可以快速打开一个新的访达窗口。这就像在 Windows 系统中通过“Ctrl N”打开新的资源管理器窗口一样。 2. Command Tab 切换 如果访达已经打开,只是被其他应…...

Ubuntu学习笔记 - Day2
文章目录 学习目标:学习内容:学习笔记:Linux系统启动过程内核引导运行init运行级别系统初始化建立终端用户登录系统 Ubuntu关机关机流程相关命令 Linux系统目录结构查看目录目录结构 文件基本属性读写权限命令 下载文件的方法安装wget工具下载…...
c++基础12比较/逻辑运算符
比较/逻辑运算符 布尔比较运算符逻辑运算符位运算符(也用于逻辑运算)1<a<10怎么表达T140399判断是否为两位数代码 布尔 在C中,布尔类型是一种基本数据类型,用于表示逻辑值,即真(true)或假…...

mac-ubuntu虚拟机(扩容-共享-vmtools)
一、磁盘扩容 使用GParted工具对Linux磁盘空间进行扩展 https://blog.csdn.net/Time_Waxk/article/details/105675468 经过上面的方式后还不够,需要再进行下面的操作 lvextend 用于扩展逻辑卷的大小,-l 选项允许指定大小。resize2fs 用于调整文件系统的…...
数学建模学习(135):使用Python基于WSM、WPM、WASPAS的多准则决策分析
1. 算法介绍 多标准决策分析(Multi-Criteria Decision Analysis, MCDA)是帮助决策者在复杂环境下做出合理选择的重要工具。WSM(加权和法)、WPM(加权乘积法)、WASPAS(加权和乘积评估法)是 MCDA 中的三种常用算法。它们广泛应用于工程、经济、供应链管理等多个领域,用于…...

VScode的C/C++点击转到定义,不是跳转定义而是跳转声明怎么办?(内附详细做法)
以最简单的以原子的跑马灯为例: 1、点击CtrlShiftP,输入setting,然后回车 2、输入Browse 3、点击下面C_Cpp > Default > Browse:Path里面添加你的工程路径 然后就可以愉快地跳转定义啦~ 希望对你有帮助,如果还不可以的话&a…...

设备管理网关(golang版本)
硬件设备:移远EC200A-CN LTE Cat 4 无线通信模块 操作系统:openwrt 技术选型:layui golang sqlite websocket 工程结构 界面展示 区域管理 设备管理 运行监控 系统参数 资源文件 版本信息...

Armv8的安全启动
目录 1. Trust Firmware 2. TF-A启动流程 3. TF-M启动流程 3.1 BL1 3.2 BL2 4.小结 在之前汽车信息安全 -- 再谈车规MCU的安全启动文章里,我们详细描述了TC3xx 、RH850、NXPS32K3的安全启动流程,而在车控类ECU中,我们也基本按照这个流程…...
冒泡排序、选择排序、计数排序、插入排序、快速排序、堆排序、归并排序JAVA实现
常见排序算法实现 冒泡排序、选择排序、计数排序、插入排序、快速排序、堆排序、归并排序JAVA实现 文章目录 常见排序算法实现冒泡排序选择排序计数排序插入排序快速排序堆排序归并排序 冒泡排序 冒泡排序算法,对给定的整数数组进行升序排序。冒泡排序是一种简单…...

SQL CASE表达式与窗口函数
CASE 表达式是一种通用的条件表达式,类似于其他编程语言中的if/else语句。 窗口函数类似于group by,但是不会改变记录行数,能扫描所有行,能对每一行执行聚合计算或其他复杂计算,并把结果填到每一行中。 1 CASE 表达式…...

基于SpringBoot的植物园管理小程序【附源码】
基于SpringBoot的植物园管理小程序 效果如下: 系统登录页面 管理员主页面 商品订单管理页面 植物园信息管理页面 小程序主页面 小程序登录页面 植物信息查询推荐页面 研究背景 随着互联网技术的快速发展和移动设备的普及,线上管理已经成为各行各业提高…...
asp.net网站项目如何设置定时器,定时获取数据
在 Global.asax.cs 文件中编写代码来初始化和启动定时器。Global.asax.cs 文件定义了应用程序全局事件,比如应用程序的启动和结束。在这里,我们将在应用程序启动时初始化和启动定时器。 using System; using System.Timers;public class Global : Syste…...

单元/集成测试解决方案
在项目开发的前期针对软件单元/模块功能开展单元/集成测试,可以尽早地发现软件Bug,避免将Bug带入系统测试阶段,有效地降低HIL测试的测试周期,也能有效降低开发成本。单元/集成测试旨在证明被测软件实现其单元/架构设计规范、证明被…...

高效作业跟踪:SpringBoot作业管理系统
1 绪论 1.1 研究背景 现在大家正处于互联网加的时代,这个时代它就是一个信息内容无比丰富,信息处理与管理变得越加高效的网络化的时代,这个时代让大家的生活不仅变得更加地便利化,也让时间变得更加地宝贵化,因为每天的…...

keepalived + nginx 实现网站高可用性(HA)
keepalive 一、keepalive简介二、实现步骤1. 环境准备2. 安装 Keepalived3. 配置 Keepalived 双机主备集群架构4. 配置 Nginx5. 启动Keepalived6. 测试高可用性7. 配置keepalived 双主热备集群架构 三、虚拟ip 一、keepalive简介 目前互联网主流的实现WEB网站及数据库服务高可用…...
有哪些编辑器,怎样选择编辑器
1. Visual Studio Code (VSCode) 特点: 轻量级且强大:启动速度快,占用资源少,但功能强大。跨平台:支持 Windows、macOS 和 Linux。丰富的扩展生态:拥有庞大的扩展市场,可以安装各种插件来扩展功…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...