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

嵌入式linux驱动开发篇之设备树

什么是设备树?

在这里插入图片描述

设备树(Device Tree)是一种用于描述嵌入式系统硬件组件及其连接关系的数据结构。它被广泛用于嵌入式 Linux 系统,尤其是针对使用多种不同架构和平台的嵌入式系统。它是一种与硬件描述相关的中间表示形式,将硬件信息抽象成一种可移植的格式,使得操作系统和引导加载程序能够在不同的硬件平台上运行,而无需硬编码特定的硬件配置信息。

树状结构:设备树是一个层次结构,由节点和属性组成。节点可以有子节点,形成树状结构。
节点类型:设备节点(device node)描述硬件组件,属性(property)提供有关硬件配置的详细信息。

设备树的主要作用包括:

描述硬件设备信息:将硬件设备的属性和配置信息以标准格式描述出来,包括设备类型、地址、中断等。
实现硬件平台的可移植性:将硬件描述与操作系统和引导加载程序分离,使得相同的软件可以在不同的硬件平台上运行。
简化内核配置和维护:通过设备树,内核可以动态地识别和管理硬件设备,而不需要硬编码在内核中,简化了内核的配置和维护工作。

设备树的一些知识点

DTS、DTB 和 DTC区别

DTS 是设备树源码文件,DTB 是将DTS 编译以后得到的二进制文件。将.dts 编译为.dtb需要用到 DTC 工具,DTC 工具源码在 Linux 内核的 scripts/dtc 目录下。

在arch/arm/boot/dts/Makefile

dtb-$(CONFIG_SOC_IMX6SLL) += \
imx6sll-lpddr2-arm2.dtb \
imx6sll-lpddr3-arm2.dtb \

在此处添加自己的设备树文件
要编译 DTS 文件的话只需要进入到 Linux 源码根目录下,然后执行如下命令:

make all
#或者
make dtbs

和 C 语言一样,设备树也支持头文件,设备树的头文件扩展名为.dtsi,.dtsi 文件用于描述 SOC 的内部外设信息,比如 CPU 架构、主频、外设寄存器地址范围。比如串口,SPI等等。imx6ull.dtsi文件部分内容如下

#include <dt-bindings/clock/imx6ul-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "imx6ull-pinfunc.h"
#include "imx6ull-pinfunc-snvs.h"
#include "skeleton.dtsi"/ {aliases {can0 = &flexcan1;can1 = &flexcan2;ethernet0 = &fec1;ethernet1 = &fec2;gpio0 = &gpio1;gpio1 = &gpio2;gpio2 = &gpio3;gpio3 = &gpio4;gpio4 = &gpio5;i2c0 = &i2c1;i2c1 = &i2c2;i2c2 = &i2c3;i2c3 = &i2c4;mmc0 = &usdhc1;mmc1 = &usdhc2;serial0 = &uart1;serial1 = &uart2;serial2 = &uart3;serial3 = &uart4;serial4 = &uart5;serial5 = &uart6;serial6 = &uart7;serial7 = &uart8;spi0 = &ecspi1;spi1 = &ecspi2;spi2 = &ecspi3;spi3 = &ecspi4;usbphy0 = &usbphy1;usbphy1 = &usbphy2;};cpus {#address-cells = <1>;#size-cells = <0>;cpu0: cpu@0 {compatible = "arm,cortex-a7";device_type = "cpu";reg = <0>;clock-latency = <61036>; /* two CLK32 periods */operating-points = </* kHz	uV */996000	1275000792000	1225000528000	1175000396000	1025000198000	950000>;fsl,soc-operating-points = </* KHz	uV */996000	1175000792000	1175000528000	1175000396000	1175000198000	1175000>;fsl,low-power-run;clocks = <&clks IMX6UL_CLK_ARM>,<&clks IMX6UL_CLK_PLL2_BUS>,<&clks IMX6UL_CLK_PLL2_PFD2>,<&clks IMX6UL_CA7_SECONDARY_SEL>,<&clks IMX6UL_CLK_STEP>,<&clks IMX6UL_CLK_PLL1_SW>,<&clks IMX6UL_CLK_PLL1_SYS>,<&clks IMX6UL_PLL1_BYPASS>,<&clks IMX6UL_CLK_PLL1>,<&clks IMX6UL_PLL1_BYPASS_SRC>,<&clks IMX6UL_CLK_OSC>;clock-names = "arm", "pll2_bus",  "pll2_pfd2_396m", "secondary_sel", "step","pll1_sw", "pll1_sys", "pll1_bypass", "pll1", "pll1_bypass_src", "osc";};};
....

设备节点

设备节点是Linux系统中一个重要的概念,它是用户程序和内核驱动之间的纽带。设备节点通常位于/dev目录下,并以文件的形式存在,每个设备节点都对应着一个特定的设备。通过打开设备节点,用户程序可以获取设备的句柄,从而与设备进行通信和控制。

标准属性

节点是由一堆的属性组成,节点都是具体的设备,不同的设备需要的属性不同,用户可以自定义属性。除了用户自定义属性,有很多属性是标准属性。
compatible 属性
compatible 属性也叫做“兼容性”属性,这是重要的属性。compatible 属性的值是一个字符串列表,compatible 属性用于将设备和驱动绑定起来。格式如下

"manufacturer,model"

I.MX6U-ALPHA 开发板上的音频芯片采用的欧胜(WOLFSON)出品的 WM8960,sound 节点的 compatible 属性值如下:

compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";

model 属性
model 属性值也是一个字符串,一般 model 属性描述设备模块信息。

model = "wm8960-audio";

status 属性
status 属性是和设备状态有关的,status 属性值也是字符串。

描述
disabled表明设备是可操作的
okay表明设备当前是不可操作的,但是在未来可以变为可操作的,比如热插拔设备插入以后。至于 disabled 的具体含义还要看设备的绑定文档
fail表明设备不可操作,设备检测到了一系列的错误,而且设备也不大可能变得可操作。
fail-sss含义和“fail”相同,后面的 sss 部分是检测到的错误内容
reg 属性
reg 属性的值一般是(address,length)对。reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息。

ranges 属性
ranges属性值可以为空或者按照(child-bus-address,parent-bus-address,length)格式编写的数字矩阵。
ranges 属性每个项目由子地址、父地址和地址空间长度
这三部分组成:child-bus-address:子总线地址空间的物理地址,由父节点的#address-cells 确定此物理地址所占用的字长。parent-bus-address:父总线地址空间的物理地址,同样由父节点的#address-cells 确定此物理地址所占用的字长。length:子地址空间的长度,由父节点的#size-cells 确定此地址长度所占用的字长。

在Linux设备树中增加设备节点的步骤通常包括以下几个步骤:

确定设备信息:包括设备的名称、兼容性、模型等。这些信息通常在设备规格书或数据手册中可以找到。
编辑设备树源文件:设备树的信息通常存储在一个设备树源文件(.dts)中。你需要打开这个文件,并在适当的位置添加你的设备节点。设备节点通常包含设备的名称、兼容性、模型以及任何特定于设备的属性或子节点。
编译设备树:一旦你添加了设备节点并保存了设备树源文件,你需要使用设备树编译器(dtc)将其编译为设备树二进制文件(.dtb)。这个文件可以在引导时被内核使用。
更新引导加载程序:需要将新的设备树二进制文件添加到引导加载程序(如U-Boot)的配置中,以便在引导时加载它。具体的步骤取决于你使用的引导加载程序。
更新内核配置:可能还需要更新内核的配置,以启用对新设备的支持。这通常涉及编辑内核配置文件(.config),然后重新编译内核。
测试:最后,需要在目标硬件上测试更改,以确保新设备能够正确识别并工作。

相关文章:

  • php 数组函数
  • 关于jupyter的一些小笔记
  • Linux第48步_编译正点原子的出厂Linux内核源码
  • 【精选】Java面向对象进阶——接口细节:成员特点和接口的各种关系
  • 随想录刷题笔记 —二叉树篇7 617合并二叉树 700二叉搜索树中的搜索 98验证二叉搜索树
  • C++数据结构与算法——双指针法
  • python-使用ffmpeg批量修改文件的后缀名
  • vue自定义指令(图文示例)
  • Leetcode3026. 最大好子数组和
  • 基于BP算法的SAR成像matlab仿真
  • Sora时代,我们的AI应该何去何从?——关于Sora大模型的思考
  • IIC--集成电路总线
  • C++ 多起点的bfs(五十九)【第六篇】
  • 文生图提示词:天气条件
  • 数据结构之时空复杂度
  • @jsonView过滤属性
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • 3.7、@ResponseBody 和 @RestController
  • Angular6错误 Service: No provider for Renderer2
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • Docker容器管理
  • js中的正则表达式入门
  • MD5加密原理解析及OC版原理实现
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • vue-loader 源码解析系列之 selector
  • 从0到1:PostCSS 插件开发最佳实践
  • 飞驰在Mesos的涡轮引擎上
  • 观察者模式实现非直接耦合
  • 简单易用的leetcode开发测试工具(npm)
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 设计模式 开闭原则
  • 通信类
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #mysql 8.0 踩坑日记
  • #pragma once与条件编译
  • (4)logging(日志模块)
  • (BFS)hdoj2377-Bus Pass
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (一)插入排序
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .NET DataGridView数据绑定说明
  • .net 发送邮件
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】