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

Linux驱动13 --- 多节点设备树

目录

一、多节点

1.1 介绍

二、设备树

2.1 设备树的概念

2.2 设备树的作用

2.3 设备树的位置

2.4 设备树文件

2.5 设备树节点

2.6 新增设备树节点

2.7 编译内核

2.8 烧录内核

2.9 设备树相关 API

        获取设备树节点

        获取节点的 GPIO 属性

        获取 GPIO 电平状态

注意


一、多节点

1.1 介绍

        当前还没有同时生成多个设备文件,一直是单个设备文件 ,而在后续的开发中,可能会遇到多个设备文件的情况

        例如:每一个 LED 灯

        当前的控制逻辑是通过 1,2,3,4 控制两个灯不同的状态

                但是,就要用 1 控制灯的亮,用 0 控制灯的灭

                这个就需要每一个 LED 灯都生成一个设备文件

        现在有 4 个 LED 灯,需要 4 个设备文件

                创建 4 个设备文件 --- 最简单的就是写 4 个.ko

        但是如果要一个 ko 生成 4 个设备文件

        多节点的目的在于在同一个.ko 文件中区分不同的设备文件

        当前要明确目标:写一个.c 编译成为一个.ko,生成 4 个设备文件,并且每个设备文件要相互独立

        多节点的核心是 struct inode、struct file 这两个结构体

        明确:设备号是设备文件的唯一标识

                所以区分不同的设备文件通过设备号区分

        当前使用文件接口的设备号存在于 struct inode 的一个成员:

                dev_t i_rdev;

        但是 struct inode 这个结构体存在于极少的文件接口

        几乎所有的文件接口都有形参 struct file

                在这个结构体中存在着一个成员:void *private_data

        就可以使用 private_data 去承接 i_rdev,就可以在其它文件接口做多节点区分

二、设备树

当下主流的开发方式

2.1 设备树的概念

        设备树是嵌入式系统中用于描述硬件配置的层次化数据结构,通过节点属性

硬件设备参数及连接关系。其核心作用是将硬件描述与操作系统内核解耦,取代传

统硬编码方式实现跨平台兼容性。设备树文件经编译生成二进制格式,由引导程序加

载至内存供内核解析,支持动态更新硬件配置。

2.2 设备树的作用

        设备树是存放设备信息的一个集合,为了解决内核冗余问题

                内核冗余问题:内核需要适配开发板

                适配板子的硬件信息

                但是,多数的硬件信息,对于内核启动来说是没用的

                        如果将这些硬件都初始化完加入内核,就会导致内核变得及其庞大

                在设备树中将硬件信息都加上,但是只使用内核需要的

        设备树和内核相辅相成:设备树其实就是内核的一部分

任何一方有问题都会直接导致系统无法启动

2.3 设备树的位置

        在内核中的位置

        当前板子设备树在 SDK 下的路径

        一般情况下设备树在 SDK 下的路径

                kernel/arch/arm/boot/dts

        在板子中的位置

        这个路径存放了所有的设备树节点信息

2.4 设备树文件

        dts:一般情况下就是存放节点信息 --- 类似 C 语言的源文件

        dtsi:一般情况下就是存放节点的依赖 --- 类似 C 语言的头文件

        dtb:和内核共同运行的二进制文件

        一般情况下我们都是修改的 dts 文件

        如何找到 dts 文件 → 通过 dtb 文件去找

si

2.5 设备树节点

        主要有这几个名词

        /                 --- 根节点 --- 一切节点的开始

        父节点         --- 当前节点的上一个节点

        兄弟节点         --- 和当前节点同一级的

        普通节点

                一个节点包含了以下内容

                节点的名字,节点的属性,节点的属性值

        下方就是一个普通节点的示例:

wireless_wlan: wireless-wlan {compatible = "wlan-platdata";wifi_chip_type = "rtl8852be";pinctrl-names = "default";pinctrl-0 = <&wifi_host_wake_irq>/*, <&wifi_poweren_gpio>*/;WIFI,host_wake_irq = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;//WIFI,poweren_gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;status = "okay";}; 

        设备树节点真正的名字是:在板子的/proc/device-tree

        节点的属性:就是花括号中,等号左边的内容

                重要的属性

                        compatible:是在驱动开发中用于匹配设备树节点的关键属性

                                                和节点名字共同作用,去匹配设备树中的设备节点

                        WIFI,host_wake_irq:用来定义 GPIO 

                                        这个属性的名字我们可以自由发挥 --- 自己定义

                        status:状态 ,节点有两个状态 --- okay,disabled

        节点的属性值:就是花括号中,等号右边的内容

                 重要的属性值

                        compatible = "wlan-platdata"; --- 属性的值,开发者可以自己更改

                                                更改的依据 --- 和设备树中的原始节点保持相似

                        WIFI,host_wake_irq = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;

                                        &gpio0:表示的是看到的 GPIO 口

                                        RK_PA0:RK_P 必须保持一致,A0 我们可以按照自己的 GPIO 去改

                                        GPIO_ACTIVE_HIGH:表示的是有效电平

                                                        GPIO_ACTIVE_LOW

2.6 新增设备树节点

        节点的新增方式:1、百度 --- 需要考虑你的内核版本,板子等等

                                     2、照搬,修改当前已经存在的节点

                

                保存,退出

2.7 编译内核

                编译成功

2.8 烧录内核

        挂起虚拟机

2.9 设备树相关 API

        关键字:of

        头文件:#include <linux/of.h>

        #include <linux/of_gpio.h>

        获取设备树节点

        函数原型

                struct device_node *of_find_node_by_name(struct device_node *from, const char *name)

        函数参数

                struct device_node *from:节点从哪里来 ,填 NULL 表示从根节点开始找

                name:节点的名字

        函数返回值

                成功返回节点核心结构体,失败返回 NULL

        函数原型

                struct device_node *of_find_node_by_path(const char *path)

        函数参数

                节点的路径

        函数返回值

                成功返回节点核心结构体,失败返回 NULL

        获取节点的 GPIO 属性

        函数原型

                int of_get_named_gpio(struct device_node *np, const char *propname, int index)

        函数参数

                np:设备节点核心结构体

                propname:GPIO 的节点属性

                        定义的节点属性名 --- gpios

                index:获取属性的第几个值

                        当前只有一个值,填 0

        函数返回值

                成功返回 GPIO 号,失败返回负数

        获取 GPIO 电平状态

        函数原型

                int of_get_named_gpio_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags)

        函数参数

                np:设备树节点核心结构体

                list_name:属性名字

                index:下标,获取第几个属性值

                flags:OF_GPIO_ACTIVE_LOW --- 指的是有效电平低

        函数返回值

                成功返回获取到的 GPIO 号

                失败返回负数

注意

卸载函数如果不写/没有卸载模块直接重启,会出现问题 :

        生成的设备文件没有被释放

        会导致如果你下次使用的是相同的文件名

        文件还停留在之前的功能

        出现这个情况,就用卸载函数卸载,如果卸载无法完成

        通过指令删除对应的设备文件,然后重启板子

http://www.dtcms.com/a/283221.html

相关文章:

  • MySQL主键策略解析:自增ID与UUID的优劣及选择建议
  • 7.17 滑动窗口 | assign
  • Docker容器访问挂载文件权限问题
  • MPPT电路设计
  • vue中后端返回数据流,前端实现导出下载
  • 等价关系与不变量
  • Web3:Solidity入门到精通
  • cdr序列化与反序列化
  • SenseGlove力反馈手套:医疗、生产制造、军事模拟与远程机器人控制新革命
  • 【AI交叉】化学:人工智能如何重塑现代化学研究?
  • 谷歌引入开源全栈 AI 代理栈:借助 Gemini 2.5 和 LangGraph 实现多步网络搜索、反思与综合
  • NMS代码详解(数据维度变换解析)
  • 格密码--Ring-SIS和Ring-LWE
  • 架构解密|一步步打造高可用的 JOCR OCR 识别服务
  • oracle会话控制和存储状态查询
  • pyqt当中splitter.setSizes()不生效
  • C++中vector和list的优缺点对比以及deque
  • PowerJob集群机器数为0问题
  • Python第八章作业(初级)
  • 如何使用VScode使用ssh连接远程服务器不需要输入密码直接登录
  • 27.Hamming 距离
  • transformers基础Data Collator
  • 教程:如何快速查询 A 股实时 K线和5档盘口
  • 今日行情明日机会——20250716
  • Redis深度解析:从缓存到分布式系统的核心引擎
  • 用python实现自动化布尔盲注
  • pytest--1--pytest-mock常用的方法
  • 代码随想录day36dp4
  • 震坤行获取商品SKU操作详解
  • 16路串口光纤通信FPGA项目实现指南