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

Linux驱动开发—设备树传递给内核,匹配驱动过程分析

文章目录

    • 总体流程图
    • 传递DTB过程
      • 编译设备树源文件
      • 将 `.dtb` 文件与内核或引导加载程序集成
    • 内核初始化阶段解析DTB
      • 内核启动阶段
      • 解析 DTB
      • 注册设备树节点
      • 驱动程序绑定

内核解析设备树二进制文件(DTB)的过程主要分为几个步骤,从设备树的传递到最终的硬件配置。这些步骤包括加载 DTB、解析和处理设备树节点和属性,以及将硬件信息传递给相应的驱动程序。

总体流程图

在这里插入图片描述

传递DTB过程

在系统启动时,引导加载程序(如 U-Boot)将 DTB 文件加载到内存,并将其位置传递给内核。对于 ARM 和 ARM64 平台,引导加载程序通常通过 r2 寄存器传递 DTB 的内存地址。

编译设备树源文件

设备树源文件(.dts)需要编译成设备树二进制文件(.dtb):

dtc -I dts -O dtb -o my_device_tree.dtb my_device_tree.dts

.dtb 文件与内核或引导加载程序集成

a. 将 .dtb 文件与内核镜像一起打包

在一些平台上,.dtb 文件被包含在内核镜像中。这通常通过内核构建系统中的配置来完成。例如,在 arm 平台上,可以通过以下步骤进行配置:

  • 确保内核配置中启用了设备树支持(CONFIG_OF)。
  • 将设备树二进制文件指定为内核构建的一部分,通常通过内核的 MakefileKconfig 文件。

b. 通过引导加载程序加载设备树

引导加载程序(例如 U-Boot)负责加载内核,并在加载内核之前传递设备树:

  1. 引导加载程序首先加载设备树二进制文件(.dtb)。
  2. 然后,引导加载程序将设备树传递给内核。

在 U-Boot 中,这通常通过设置环境变量来实现:

setenv fdtfile my_device_tree.dtb
load mmc 0:1 ${fdt_addr} ${fdtfile}
bootz ${kernel_addr} - ${fdt_addr}

fdtfile 是设备树二进制文件的路径。

fdt_addr 是设备树加载到内存中的地址。

kernel_addr 是内核镜像的地址。

当内核启动时,它会从引导加载程序接收设备树

内核初始化阶段解析DTB

内核解析设备树二进制文件(DTB)的过程主要分为几个步骤,从设备树的传递到最终的硬件配置。这些步骤包括加载 DTB、解析和处理设备树节点和属性,以及将硬件信息传递给相应的驱动程序

内核启动阶段

内核启动时,会在启动代码中处理传递过来的 DTB 地址,并将其保存在全局变量中。以 ARM64 为例,启动代码会保存 DTB 地址,并在后续初始化过程中使用:

void __init setup_arch(char **cmdline_p)
{// 保存 DTB 地址initial_boot_params = __va(FDT_START);
}

解析 DTB

内核在初始化过程中会调用设备树相关的函数来解析 DTB。主要函数如下:

a. 在imx_4.14.98_2.0.0_ga/arch/arm64/kernel 中setup.c 中early_init_dt_scan()

static void __init setup_machine_fdt(phys_addr_t dt_phys)
{void *dt_virt = fixmap_remap_fdt(dt_phys);const char *name;if (!dt_virt || !early_init_dt_scan(dt_virt)) {pr_crit("\n""Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n""The dtb must be 8-byte aligned and must not exceed 2 MB in size\n""\nPlease check your bootloader.",&dt_phys, dt_virt);while (true)cpu_relax();}name = of_flat_dt_get_machine_name();if (!name)return;pr_info("Machine model: %s\n", name);dump_stack_set_arch_desc("%s (DT)", name);
}

内核首先调用 early_init_dt_scan() 来扫描和验证设备树的基本结构、总大小和根节点:

void __init early_init_dt_scan(void *params)
{if (fdt_check_header(params))panic("Invalid device tree blob");// 解析根节点和基本属性early_init_dt_verify(params);early_init_dt_reserve_memory();unflatten_device_tree();
}

b.在drivers/of/fdt.c 中定义了如何解析为树状结构函数 : unflatten_device_tree()

unflatten_device_tree() 函数将设备树的扁平结构转换为内核使用的树形结构:

/*** __unflatten_device_tree - create tree of device_nodes from flat blob** unflattens a device-tree, creating the* tree of struct device_node. It also fills the "name" and "type"* pointers of the nodes so the normal device-tree walking functions* can be used.* @blob: The blob to expand* @dad: Parent device node* @mynodes: The device_node tree created by the call* @dt_alloc: An allocator that provides a virtual address to memory* for the resulting tree** Returns NULL on failure or the memory chunk containing the unflattened* device tree on success.*/
void *__unflatten_device_tree(const void *blob,struct device_node *dad,struct device_node **mynodes,void *(*dt_alloc)(u64 size, u64 align),bool detached)
{int size;void *mem;pr_debug(" -> unflatten_device_tree()\n");if (!blob) {pr_debug("No device tree pointer\n");return NULL;}pr_debug("Unflattening device tree:\n");pr_debug("magic: %08x\n", fdt_magic(blob));pr_debug("size: %08x\n", fdt_totalsize(blob));pr_debug("version: %08x\n", fdt_version(blob));if (fdt_check_header(blob)) {pr_err("Invalid device tree blob header\n");return NULL;}/* First pass, scan for size */size = unflatten_dt_nodes(blob, NULL, dad, NULL);if (size < 0)return NULL;size = ALIGN(size, 4);pr_debug("  size is %d, allocating...\n", size);/* Allocate memory for the expanded device tree */mem = dt_alloc(size + 4, __alignof__(struct device_node));if (!mem)return NULL;memset(mem, 0, size);*(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);pr_debug("  unflattening %p...\n", mem);/* Second pass, do actual unflattening */unflatten_dt_nodes(blob, mem, dad, mynodes);if (be32_to_cpup(mem + size) != 0xdeadbeef)pr_warning("End of tree marker overwritten: %08x\n",be32_to_cpup(mem + size));if (detached && mynodes) {of_node_set_flag(*mynodes, OF_DETACHED);pr_debug("unflattened tree is detached\n");}pr_debug(" <- unflatten_device_tree()\n");return mem;
}

c. early_init_dt_scan_nodes()

这个函数扫描设备树的所有节点,并将其转换为内核中的数据结构:

void __init early_init_dt_scan_nodes(void)
{/* Retrieve various information from the /chosen node */of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);/* Initialize {size,address}-cells info */of_scan_flat_dt(early_init_dt_scan_root, NULL);/* Setup memory, calling early_init_dt_add_memory_arch */of_scan_flat_dt(early_init_dt_scan_memory, NULL);
}

注册设备树节点

内核将解析的设备树节点注册到设备模型中,通常通过位于drivers/of/platform.c的 of_platform_populate() 函数完成:

int __init of_platform_populate(void)
{struct device_node *root;root = of_find_node_by_path("/");of_platform_default_populate(root, NULL, NULL);return 0;
}

驱动程序绑定

设备树解析后,内核会根据设备树中的信息来匹配相应的驱动程序,并进行设备初始化。驱动程序通常通过 of_match_table 表来匹配设备树中的节点

static const struct of_device_id my_driver_of_match[] = {{ .compatible = "my_vendor,my_device", },{ }
};
MODULE_DEVICE_TABLE(of, my_driver_of_match);

驱动程序通过 of_device 结构体访问设备树节点和属性:

static int my_driver_probe(struct platform_device *pdev)
{struct device_node *np = pdev->dev.of_node;// 读取属性并初始化设备return 0;
}

相关文章:

Linux驱动开发—设备树传递给内核,匹配驱动过程分析

文章目录 总体流程图传递DTB过程编译设备树源文件将 .dtb 文件与内核或引导加载程序集成 内核初始化阶段解析DTB内核启动阶段解析 DTB注册设备树节点驱动程序绑定 内核解析设备树二进制文件&#xff08;DTB&#xff09;的过程主要分为几个步骤&#xff0c;从设备树的传递到最终…...

深入理解 Go 语言信号量 Semaphore

1. 什么是信号量 信号量的概念是荷兰计算机科学家 Edsger Wybe Dijkstra 在 1963 年左右提出来的,被广泛应用在不同的操作系统中。在操作系统中,会给每一个进程分配一个信号量,代表每个进程目前的状态。未得到控制权的进程,会在特定的地方被迫停下来,等待可以继续进行的信…...

git——删除远程仓库中的文件或文件夹步骤图解(只是从远程仓库中删除,本地文件不受影响、不会被删除)

目录 一、删除远程仓库中的文件或文件夹1.1、 以删除远程仓库jetcache-demo项目中的logs文件夹为例1.2、 删除远程仓库jetcache-demo项目中的logs文件夹步骤图解 一、删除远程仓库中的文件或文件夹 1.1、 以删除远程仓库jetcache-demo项目中的logs文件夹为例 删除远程仓库jet…...

详解贪心算法

贪心算法&#xff08;Greedy Algorithm) 概述&#xff1a; 贪心算法是一种在求解最优化问题时采取的一种常用算法策略。贪心算法的基本思想是&#xff0c;每次选择当前情况下的局部最优解&#xff0c;并相信这个局部最优解能够导致全局最优解。贪心算法通过迭代的方式一步步地…...

LabVIEW工件表面瑕疵识别系统

开发了一种利用LabVIEW和IMAQ Vision视觉工具进行工件表面瑕疵识别的系统。该系统通过图像处理技术识别并分类工件表面的裂纹、划痕等缺陷&#xff0c;从而提升生产线的分拣效率和产品质量。 项目背景 工业生产中&#xff0c;工件表面的缺陷直接影响产品质量和生产效率。传统人…...

LabVIEW水下根石监测系统

开发了一种基于LabVIEW平台开发的水下根石监测系统。该系统利用高精度姿态传感器与位移传感器&#xff0c;实现了水下根石状态的实时自动监测&#xff0c;提高了水利工程安全管理的现代化和精细化水平&#xff0c;具有高精度、高稳定性和良好的操作性。 项目背景&#xff1a; …...

探索全光网技术 | 全光网络技术方案选型建议三(医院场景)

目录 一、场景设计需求二、医院场景拓扑三、部署方式四、产品相关规格说明五、方案优势与特点 注&#xff1a;本文章参考资料为&#xff1a;华三官方资料 - “新华三全光网络3.0解决方案&#xff08;教育&#xff09;”与 锐捷官方资料 - “【锐捷】高校极简以太全光3.X方案设计…...

【C++语言】vector迭代器与常见oj题

vector迭代器的失效问题 接上篇vector的介绍和使用中最后提到的vector迭代器&#xff0c;我们继续来看vector迭代器的失效问题。 以下代码的功能是删除vector中所有的偶数&#xff0c;请问那个代码是正确的&#xff0c;为什么&#xff1f; #include <iostream> using na…...

高职物联网智慧农业实训室建设方案

一、项目概述 随着物联网技术的迅猛发展及其在农业领域的广泛应用&#xff0c;智慧农业已经成为推动农业现代化的关键力量。近年来&#xff0c;国家高度重视物联网技术在农业领域的应用与发展&#xff0c;出台了一系列相关政策支持智慧农业建设。如《数字乡村发展战略纲要》明…...

Pytorch 高效快速加载大规模数据集

一、前言 最近遇到一个多模态学习任务,原始数据为HDF5 格式,遇到主要两个问题:一是数据量过大无法直接加载到内存,二是HDF5 是基于关键值索引,索引速度非常慢。在使用Pytorch 训练模型时,数据加载速度跟不上模型训练速度,导致GPU使用率低。阅读OLMO 框架关于数据集加载…...

Spring Boot集成protobuf快速入门Demo

1.什么是protobuf&#xff1f; Protobuf&#xff08;Protocol Buffers&#xff09;是由 Google 开发的一种轻量级、高效的数据交换格式&#xff0c;它被用于结构化数据的序列化、反序列化和传输。相比于 XML 和 JSON 等文本格式&#xff0c;Protobuf 具有更小的数据体积、更快…...

SpringBoot+Vue 简单小文章项目开发全过程

文章目录 一、项目介绍二、需求设计三、数据库设计四、项目构建项目技术选型:构建项目说明:项目架构mavenMySQLRedis 五、项目开发&#xff1a;项目开发思路&#xff1a;项目开发过程&#xff1a;1. 导入文件包/新建项目2. 新建子模块&#xff1a;common模块pojo模块server模块…...

如何将发明原理应用于产品设计的概念阶段?

众所周知&#xff0c;产品设计的概念阶段是创意孵化的关键时期&#xff0c;它决定了产品的方向、定位及核心卖点。在这一阶段&#xff0c;将发明原理融入其中&#xff0c;能够极大地拓宽思维边界&#xff0c;激发前所未有的设计灵感。具体步骤如深圳天行健企业管理咨询公司下文…...

【wsl】wsl + vscode 中使用 typora 打开 markdown 文件

vscode 连接好wsl 使用Open in External App 一个五星好评的插件Open in External App则可以在vscode中用typora打开md文件&#xff0c;不仅如此&#xff0c;还有设定其他应用打开相应的文件&#xff0c;比如chrome打开html。插件食用方法也比较简单&#xff0c;安装后&#…...

AutoDL下huggingface下载模型位置问题

AutoDL系统盘只有30G&#xff0c;数据盘有50G且可扩容&#xff0c;模型及数据集空间通常较大&#xff0c;为节省系统盘空间&#xff0c;我们将文件都存储于数据盘&#xff0c;在运行的代码最前端&#xff08;一定要在最前面&#xff09;添加 import os os.environ[HF_HOME] /…...

SpringBoot基础(一):快速入门

SpringBoot基础系列文章 SpringBoot基础(一)&#xff1a;快速入门 目录 一、SpringBoot简介二、快速入门三、SpringBoot核心组件1、parent1.1、spring-boot-starter-parent1.2、spring-boot-dependencies 2、starter2.1、spring-boot-starter-web2.2、spring-boot-starter2.3、…...

使用Weka进行数据挖掘与机器学习

在当前大数据时代&#xff0c;数据挖掘与机器学习已经成为了不可或缺的技术。而Weka是一个非常流行的机器学习软件&#xff0c;它提供了一整套的机器学习算法和数据处理工具。Weka不仅支持命令行操作和GUI&#xff0c;还提供了Java API&#xff0c;非常适合Java开发者进行数据挖…...

定时器知识点

#视频教程&#xff1a; 11.TIM定时中断 CSDN教程 知识点&#xff1a; 1.时钟源选择图 ![[Pasted Image 20240802103525_114.png]] 基本定时器 2个功能 &#xff1a;只能定时中断和主模式触发DAC的功能 知识点 1.时基单元&#xff1a;预分配器&#xff08;PSC&#xff09;、…...

桌面日历还能这样玩?这个日历太酷了吧!秒变桌面记事本!

大家应该有经常看日历的习惯&#xff0c;每个人都有不同的日历需求。特别是一些节假日&#xff0c;重要节日时候&#xff0c;大家看日历的频次就比较高了&#xff0c;如何选一款好用的日历&#xff1f;我们给大家展示一款非常不错的桌面日历&#xff0c;看下你喜不喜欢&#xf…...

基于深度学习的太阳暗条检测(2020年以来)

A universal method for solar filament detection from Hα observations using semi-supervised deep learning A&A, 686, A213 (2024) A universal method for solar filament detection from Hα observations using semi-supervised deep learning (aanda.org) ABS…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...