Linux内核如何和设备树协同工作的?

news2025/3/12 8:42:44

1.编写设备树

cd arch/riscv/boot/dts/

再cd到厂商,例如下述内容。

2.编译设备树(dts->dtb)通过dtc命令来转换

3.解析设备树

例如上述内容,都是对设备树的解析。

这里重点说一下内核对设备树的处理吧,因为这个内容是设备树的重点了。

从源代码文件 dts 文件开始,设备树的处理过程为:

dts PC 机上被编译为 dtb 文件;
u-boot dtb 文件传给内核;
内核解析 dtb 文件,把每一个节点都转换为 device_node 结构体;
对于某些 device_node 结构体,会被转换为 platform_device 结构体。
dtb 中每一个节点都被转换为 device_node 结构体
根节点被保存在全局变量 of_root 中,从 of_root 开始可以访问到任意节点。
哪些设备树节点会被转换为 platform_device
根节点下含有 compatile 属性的 子节点
含有特定 compatile 属性的节点的 子节点
如果一个节点的 compatile 属性,它的值是这 4 者之一: "simple
bus","simple-mfd","isa","arm,amba-bus", 那 么 它 的 子结点 ( 需 含
compatile 属性 ) 也可以转换为 platform_device
        总线 I2C SPI 节点下的子节点: 不转换 platform_device。
某个总线下到子节点,应该交给对应的总线驱动程序来处理, 它们不应该被转换为 platform_device。
比如以下的节点中:
/mytest 会被转换为 platform_device, 因为它兼容 "simple-bus";
        它的子节点/mytest/mytest@0 也会被转换为 platform_device
/i2c 节点一般表示 i2c 控制器 , 它会被转换为 platform_device, 在内核中有对应的 platform_driver;
/i2c/at24c02 节点不会被转换为 platform_device, 它被如何处理完全由父节点的 platform_driver 决定 , 一般是被创建为一个 i2c_client
类似的也有 /spi 节点 , 它一般也是用来表示 SPI 控制器 , 它会被转换为platform_device, 在内核中有对应的 platform_driver; /spi/flash@0 节点不会被转换为 platform_device, 它被如何处理完全由父节点的 platform_driver 决定 , 一般是被创建为一个 spi_device
怎么转换为 platform_device
内核处理设备树的函数调用过程,这里不去分析;我们只需要得到如下结论:
platform_device 中含有 resource 数组 , 它来自 device_node 的 reg, interrupts 属性 ;
platform_device.dev.of_node 指向 device_node, 可以通过它获得其他属性;
platform_device 如何与 platform_driver 配对
最先比较:是否强制选择某个 driver
然后比较:设备树信息
接下来比较: platform_device_id
platform_device.name platform_driver.driver.name
platform_driver.id_table 可能为空,
这 时 可 以 根 据 platform_driver.driver.name 来 寻 找 同 名 的
platform_device
内核里操作设备树的常用函数
内核源码中 include/linux/ 目录下有很多 of 开头的头文件, of 表示“ open
firmware ”即开放固件。
设备树的处理过程是: dtb -> device_node -> platform_device
处理 DTB
of_fdt.h // dtb 文件的相关操作函数, 我们一般用不到, 
// 因为 dtb 文件在内核中已经被转换为 device_node 树(它更易于使用)

处理 device_node
of.h // 提供设备树的一般处理函数, 
// 比如 of_property_read_u32(读取某个属性的 u32 值),
// of_get_child_count(获取某个 device_node 的子节点数)
of_address.h // 地址相关的函数, 
// 比如 of_get_address(获得 reg 属性中的 addr, size 值)
// of_match_device (从 matches 数组中取出与当前设备最匹配的一项)
of_dma.h // 设备树中 DMA 相关属性的函数
of_gpio.h // GPIO 相关的函数
of_graph.h // GPU 相关驱动中用到的函数, 从设备树中获得 GPU 信息
of_iommu.h // 很少用到
of_irq.h // 中断相关的函数
of_mdio.h // MDIO (Ethernet PHY) API
of_net.h // OF helpers for network devices. 
of_pci.h // PCI 相关函数
of_pdt.h // 很少用到
of_reserved_mem.h // reserved_mem 的相关函数

处理 platform_device
 
of_platform.h // 把 device_node 转换为 platform_device 时用到的函数, 
 // 比如 of_device_alloc(根据 device_node 分配设置 platform_device), 
 // of_find_device_by_node (根据 device_node 查找到 platform_device),
 // of_platform_bus_probe (处理 device_node 及它的子节点)
of_device.h // 设备相关的函数, 比如 of_match_device
platform_device 相关的函数
of_platform.h 中声明了很多函数,但是作为驱动开发者,我们只使用其中的 1 2 个。其他的都是给内核自己使用的,内核使用它们来处理设备树,转换得到 platform_device
of_find_device_by_node
函数原型为:
extern struct platform_device *of_find_device_by_node(struct device_node *np);
设备树中的每一个节点,在内核里都有一个 device_node ;你可以使用device_node 去找到对应的 platform_device
platform_get_resource
这 个 函 数 跟 设 备 树 没 什 么 关 系 , 但 是 设 备 树 中 的 节 点 被 转 换 为platform_device 后,设备树中的 reg 属性、 interrupts 属性也会被转换为 “resource”。 这时,你可以使用这个函数取出这些资源。
/**
* platform_get_resource - get a resource for a device
* @dev: platform device
* @type: resource type // 取哪类资源?IORESOURCE_MEM、IORESOURCE_REG
* // IORESOURCE_IRQ 等
* @num: resource index // 这类资源中的哪一个?
*/
struct resource *platform_get_resource(struct platform_device *dev,
 unsigned int type, unsigned int num);
对于设备树节点中的 reg 属性,它对应 IORESOURCE_MEM 类型的资源;
对于设备树节点中的 interrupts 属性,它对应 IORESOURCE_IRQ 类型的资
源。
有些节点不会生成 platform_device ,怎么访问它们
内核会把 dtb 文件解析出一系列的 device_node 结构体,我们可以直接访
问这些 device_node
内核源码 incldue/linux/of.h 中声明了 device_node 和属性 property 的操作函数
of_find_node_by_path of_find_node_by_name 等等都可以。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2313658.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LLM中的transformer结构学习(二 完结 Multi-Head Attention、Encoder、Decoder)

文章目录 LLM中的transformer结构学习(二 完结 Multi-Head Attention、Encoder、Decoder)Self-Attention (自注意力机制)结构多头注意力 EncoderAdd & Norm 层Feed Forward 层 EncoderDecoder的第一个Multi-Head AttentionMas…

高效编程指南:PyCharm与DeepSeek的完美结合

DeepSeek接入Pycharm 前几天DeepSeek的充值窗口又悄悄的开放了,这也就意味着我们又可以丝滑的使用DeepSeek的API进行各种辅助性工作了。本文我们来聊聊如何在代码编辑器中使用DeepSeek自动生成代码。 注:本文适用于所有的JetBrains开发工具&#xff0c…

爱可以传递,幸福可以具象化

遇到什么:晚上上课学生吵吵吵,把学生手机全部收了,放讲台上。 感受到的情绪:很烦躁。 反思:收手机也不是长久之计,可是物理有什么翻转课堂呢? 明天的待办事项:早上高数选修课&#x…

力扣-数组-367 有效的完全平方数

思路和时间复杂度 思路:利用二分,确定区间是左闭右闭,然后根据大小进行二分时间复杂度: 代码 class Solution { public:bool isPerfectSquare(int num) {bool flag false;if(num 0 || num 1) return true;long long …

Java关键字与标识符

Java关键字是预定义的保留字,用于定义程序结构和语义,如if、for、class等,不能用作标识符。JDK 8有50个关键字,JDK 11引入var用于局部变量类型推断。标识符用于命名变量、类等,由字母、数字、_、$组成,不能…

【神经网络】python实现神经网络(二)——正向推理的模拟演练

一.神经网络假设 在开始讲解之前,首先我们假设有这样一套神经网络,一共有三层: 其中,关于神经网络的权重、偏置的符号定义如下(如果不知道什么是权重和偏置,可以参考我之前写过的一篇文章:【机器学习】机器学习是什么意思): 以下文章将沿用以上这个设…

DeepSeek模型本地化部署方案及Python实现

DeepSeek实在是太火了,虽然经过扩容和调整,但反应依旧不稳定,甚至小圆圈转半天最后却提示“服务器繁忙,请稍后再试。” 故此,本文通过讲解在本地部署 DeepSeek并配合python代码实现,让你零成本搭建自己的AI…

Houdini SOP层 Scatter节点

SOP 代表 Surface Operator(几何体操作节点),所有几何体的建模、变形、分布等操作都在此层级完成。 Scatter节点的作用就是 以不同的密度在模型表面撒点 Scatter 节点属于 SOP(几何体)层级: 进入 Geometr…

【网络安全工程】任务12:网络安全设备

目录 一、防火墙​ 1、作用​ 2、配置方式​ 3、存在的漏洞​ 二、入侵检测系统(IDS)和入侵防御系统(IPS)​ 1、作用​ 2、配置方式​ 3、存在的漏洞​ 三、防病毒网关​ ​1、作用​ 2、配置方式​ 3、存在的漏洞​ …

Linux 进程控制:创建、终止、等待与程序替换全解析

亲爱的读者朋友们😃,此文开启知识盛宴与思想碰撞🎉。 快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 目录 1.进程创建 1-1 fork函数初识​ 1-2 fork函数返回值​ 1-3…

SwiftUI 让视图自适应高度的 6 种方法(四)

概览 在 SwiftUI 的世界里,我们无数次都梦想着视图可以自动根据布局上下文“因势而变”‌。大多数情况下,SwiftUI 会将每个视图尺寸处理的井井有条,不过在某些时候我们还是得亲力亲为。 如上图所示,无论顶部 TabView 容器里子视图…

1035.不相交的线

1035.不相交的线 力扣题目链接(opens new window) 在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直线需要同时满足: nums1[i] nums2[j]且绘制的直线…

2001-2023年上市公司数字化转型年报词频统计(年报词频统计和MDA词频统计两种方式)(吴非、赵宸宇、甄红线300+关键词三种方法)

2001-2023年上市公司数字化转型年报词频统计(年报词频统计和MD&A词频统计两种方式)(吴非、赵宸宇、甄红线300关键词三种方法) 1、时间:2001-2023年 2、来源:上市公司年报 3、参考文献: …

IO多路复用实现并发服务器

一.select函数 select 的调用注意事项 在使用 select 函数时,需要注意以下几个关键点: 1. 参数的修改与拷贝 readfds 等参数是结果参数 : select 函数会直接修改传入的 fd_set(如 readfds、writefds 和 exceptfds&#xf…

C++20 模块:告别头文件,迎接现代化的模块系统

文章目录 引言一、C20模块简介1.1 传统头文件的局限性1.2 模块的出现 二、模块的基本概念2.1 模块声明2.2 模块接口单元2.3 模块实现单元 三、模块的优势3.1 编译时间大幅减少3.2 更好的依赖管理3.3 命名空间隔离 四、如何使用C20模块4.1 编译器支持4.2 示例项目4.3 编译和运行…

有必要使用 Oracle 向量数据库吗?

向量数据库最主要的特点是让传统的只能基于具体值/关键字的数据检索,进化到了可以直接基于语义的数据检索。这在AI时代至关重要! 回到标题问题:是否有必要使用 Oracle 向量数据库? 这实际还要取决于你的具体应用需求。 客观来讲…

小肥柴慢慢手写数据结构(C篇)(4-3 关于栈和队列的讨论)

小肥柴慢慢学习数据结构笔记(C篇)(4-3 关于栈和队列的讨论) 目录1 双端栈/队列2 栈与队列的相互转化2-1 栈转化成队列2-2 队列转化成栈 3 经典工程案例3-1 生产者和消费者模型(再次重温环形缓冲区)3-2 MapR…

java-单列模式-final-继承-多态

内存存储区域 引用变量和普通变量引用变量放在栈中,基本数据类型的内容是在堆内存中。 对象放在堆内存中,其引用变量放在栈中,指向堆内存存放对象的地址。 静态变量放在静态区中,静态变量在程序的执行始中中分配一次,…

基于杀伤链的勒索软件控制框架

40s说清楚勒索软件如何工作 基于杀伤链的勒索软件控制框架开发了4种缓解策略(预防、阻止、检测&响应、重建),覆盖18个控制域90项控制措施,以正确管理与勒索软件攻击杀伤链各阶段相关的风险。 注:本文节选出自《基于杀伤链的勒索软件防御指…

Windows编程----结束进程

进程有启动就有终止,通过CreateProcess函数可以启动一个新的子进程,但是如何终结子进程呢?主要有四种方法: 通过主线程的入口函数(main函数、WinMain函数)的return关键字终止进程 一个应用程序只有一个入…