Linux内核的GPIO子系统驱动框架详解

news2025/1/17 3:07:11

目录

1 引入

2 GPIO子系统的层次

3 gpio子系统驱动程序流程

4 gpio子系统的中药数据结构

5 gpio子系统函数调用的详细细节

6 GPIO子系统的sysfs接口

6.1有哪些gpio控制器

6.2每个gpio控制器的详细信息

6.3查看gpio使用情况

6.4通过SYSFS使用GPIO

6.4.1 确定GPIO编号

6.4.2 导出、设置方向、读写值

7 费曼学习法:于是我录制了一个讲解gpio子系统的学习视频


1 引入

当我们想用某个引脚控制LED灯的亮灭时,一般来说我们需要使能时钟,然后将引脚配置为GPIO功能,然后配置电气属性,然后配置GPIO为输出,最后根据控制GPIO的输出电平,其中配置GPIO的方向以及电平是由GPIO子系统来做的。

2 GPIO子系统的层次

上图就是gpio子系统的层次结构图,在其他的驱动程序里面,我们可以直接用gpiod_set_value这种函数来设置引脚的值,这个函数是在gpio库里面定义的,gpio库起到一个承上启下的作用,然后这个gpiod_set_value函数最终调用的是chip->set(chip, gpio_chip_hwgpio(desc), value)函数,这里的chip就是在gpio驱动程序里面注册的结构体,这个结构体体里面就包含了一些对gpio的操作函数。

3 gpio子系统驱动程序流程

上图是我根据Linux内核源码画的一个GPIO驱动程序流程图,我们在设备树中的gpio控制器节点里面的compatible为fsl,imx35-gpio,然后我们在内核源码中搜索,可以找到匹配的驱动为mxc_gpio_driver,然后当device和driver相匹配之后,会调用驱动程序里面的probe函数,在这里也就是mxc_gpio_probe函数,然后在这个mxc_gpio_probe函数里面其实就是做了下面三个工作

  • 分配结构体
  • 设置结构体
  • 注册结构体

mxc_gpio_probe函数具体做的工作:首先调用了mxc_gpio_get_hw函数,这个函数是获取了gpio寄存器组的偏移地址,然后还一个platform_get_resource函数,这个platform_get_resource函数是得到了gpio的寄存器的基地址,然后调用了devm_kzalloc分配了一个mxc_gpio_port结构体,

struct mxc_gpio_port {
    struct list_head node;
    struct clk *clk;
    void __iomem *base;
    int irq;
    int irq_high;
    struct irq_domain *domain;
    struct gpio_chip gc;
    u32 both_edges;
    int saved_reg[6];
    bool gpio_ranges;
};

然后这个mxc_gpio_port结构体里面有一个重要的gpio_chip结构体成员。

struct gpio_chip {
    const char      *label;
    struct gpio_device  *gpiodev;
    struct device       *parent;
    struct module       *owner;
    ...省略一些...
    int         (*direction_input)(struct gpio_chip *chip,
                        unsigned offset);
    int         (*direction_output)(struct gpio_chip *chip,
                        unsigned offset, int value);
    int         (*get)(struct gpio_chip *chip,
                        unsigned offset);
    void            (*set)(struct gpio_chip *chip,
                        unsigned offset, int value);
     ...省略一些...
                        enum single_ended_mode mode);
    int         (*to_irq)(struct gpio_chip *chip,
                        unsigned offset);
    void            (*dbg_show)(struct seq_file *s,
                        struct gpio_chip *chip);
     ...省略一些...
};

这个gpio_chip里面就是各种操作函数。

然后probe函数里面又调用了下面这个函数

    err = bgpio_init(&port->gc, &pdev->dev, 4,
             port->base + GPIO_PSR,
             port->base + GPIO_DR, NULL,
             port->base + GPIO_GDIR, NULL,
             BGPIOF_READ_OUTPUT_REG_SET);
这里的参数    
port->base + GPIO_PSR,
port->base + GPIO_DR, 
port->base + GPIO_GDIR, 
就是寄存器地址
设置完结构体之后,这个结构体里面有寄存器值也有操作函数。

在这个bgpio_init函数里面主要调用了下面三个函数

bgpio_setup_io(gc, dat, set, clr, flags);
bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN,
                    flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
bgpio_setup_direction(gc, dirout, dirin, flags);

然后这三个函数里面就是gpio的各种操作函数。然后调用了err = devm_gpiochip_add_data(&pdev->dev, &port->gc, port);函数,这个函数里面是分配了gpio_device结构体,然后gpio_device结构体里面的chip成员就是前面分配设置的gpio_chip结构体。

4 gpio子系统的中药数据结构

我们前面说过,我们要分配设置注册一个gpio_chip结构体,然后我们用gpiochip_add_data(chip, data);函数注册了一个gpio_device结构体,然后这个gpio_device结构体里面就包含gpio_chip结构体,然后这个gpio_device结构体里面除了chip成员外,还有descs成员,这个是用来表示引脚的,每一个引脚都有一个descs结构体,然后descs结构体里面有一个gdev成员,我们可以根据这个gdev成员找到这个引脚属于哪一个gpio控制器。

5 gpio子系统函数调用的详细细节

上图是gpio子系统的函数调用具体细节,我们一个gpio控制器就对应一个gpio_device结构体,然后这个结构体里面有

  • base成员,base成员是这个gpio控制器里面引脚的起始标号,
  • ngpio是引脚的个数,
  • descs成员是一个结构体数组,里面每一项都是一个gpio_desc结构体,都表示一个引脚。

然后加入我们设备树里面有一个

myled{
        compatible = "cumtchw"
        led-gpios = <&gpio1  10  GPIO_ACTIVE_LOW>        
};

那么当我们调用led_gpio = gpiod_get(&pdev->dev, &quot;led&quot;, 0);函数时,那么就是根据led-gpios = <&gpio1 10 GPIO_ACTIVE_LOW> 可以得到是gpio1控制器里面的第10项,那么led_gpio就指向descs数组里面的第10项,然后我们这个desc其实就可找到这个引脚对应的控制器,然后那么当我们用gpiod_set_value(led_gpio, status);这个函数去设置引脚的时候就会找到控制器里面的chip->set(chip, gpio_chip_hwgpio(desc), value);然后这个函数的第二个参数是指设置这个控制器的第几个引脚,这里的第二个参数是这么得到的

static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc)
{
    return desc - &desc->gdev->descs[0];
}  这里就是10

6 GPIO子系统的sysfs接口

驱动程序为`drivers\gpio\gpiolib-sysfs.c`,

6.1有哪些gpio控制器

/sys/bus/gpio/devices`目录下,列出了所有的GPIO控制器:

6.2每个gpio控制器的详细信息

 /sys/class/gpio/gpiochipXXX`下,有这些信息:

 base     // 这个GPIO控制器的GPIO编号
device
label    // 名字
ngpio    // 引脚个数
power
subsystem
uevent

6.3查看gpio使用情况

 cat /sys/kernel/debug/gpio

6.4通过SYSFS使用GPIO

如果只是简单的引脚控制(比如输出、查询输入值),可以不编写驱动程序。

但是涉及中断的话,就需要编写驱动程序了。

6.4.1 确定GPIO编号

查看每个`/sys/class/gpio/gpiochipXXX`目录下的label,确定是你要用的GPIO控制器,也称为GPIO Bank。

根据它名字gpiochipXXX,就可以知道基值是XXX。

基值加上引脚offset,就是这个引脚的编号。

6.4.2 导出、设置方向、读写值

echo 509 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio509/direction
echo 1 > /sys/class/gpio/gpio509/value
echo 509 > /sys/class/gpio/unexport

echo 509 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio509/direction
cat /sys/class/gpio/gpio509/value
echo 509 > /sys/class/gpio/unexport

7 费曼学习法:于是我录制了一个讲解gpio子系统的学习视频

 

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

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

相关文章

Hadoop的第二个核心组件:MapReduce框架第一节

Hadoop的第二个核心组件&#xff1a;MapReduce框架第一节 一、基本概念二、MapReduce的分布式计算核心思想三、MapReduce程序在运行过程中三个核心进程四、如何编写MapReduce计算程序&#xff1a;&#xff08;编程步骤&#xff09;1、编写MapTask的计算逻辑2、编写ReduceTask的…

Linux命令行

目录 CLI GUI 命令行界面 图形界面 命令行提示符 # $ ​编辑 命令一般由三个部分组成 历史命令&#xff0c;使用上下键&#xff0c;或者使用history&#xff0c;ctrlr搜索历史命令 通配符 *,? 切换用户 su 作业管理 &&#xff0c;jobs,bg,fg CLI GUI 命令行界面 …

基于SSM的健身房管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

第一天 关于项目遇到的问题和缺少的知识点

1.配置静态资源映射 配置文件使用的都是配置类方式 创建配置类WebMvcConfig,设置静态资源映射 用于在Springboot项目中, 默认静态资源的存放目录为 : "classpath:/resources/", "classpath:/static/", "classpath:/public/" ; 而在我们的项目中静…

黑客是如何“免费”坐飞机的?

对于爱好飞行的“空中飞人”来说&#xff0c;航空里程早已不是什么新鲜话题。如何利用航司的各种会员等级福利&#xff1f;如何积累里程&#xff1f;如何兑换航线&#xff1f;这些与里程相关的研究和分析&#xff0c;甚至发展成了非常成熟的社区文化。 航空里程也在不断的发展…

AI云服务平台大全:GPU租用 | App托管 | MLOps平台

我们搜集整理了国内外主要的深度学习云服务商&#xff0c;包括云GPU供应商、WebApp托管商和MLOps平台商。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 1、云GPU供应商 只有一台笔记本电脑&#x1f4bb;不足以运行你的AI模型&#xff0c;忘记它吧&#xff0c;使用云 …

【网易云信】音画同步测试方法的研究与实践

概述 随着移动互联网的普及和网络带宽的提高&#xff0c;音视频通话越来越成为人们生活和工作中不可或缺的一部分。音画同步是音视频体验的一个重要指标&#xff0c;在音视频传输过程中&#xff0c;由于不同的传输策略因为网络的干扰&#xff0c;音频和视频往往难以同时到达&a…

智能小车—PWM方式实现小车调速和转向

目录 1. 让小车动起来 2. 串口控制小车方向 3. 如何进行小车PWM调速 4. PWM方式实现小车转向 1. 让小车动起来 电机模块开发 L9110s概述 接通VCC&#xff0c;GND 模块电源指示灯亮&#xff0c; 以下资料来源官方&#xff0c;具体根据实际调试 IA1输入高电平&#xff0c…

上海控安SmartRocket系列产品推介(六):SmartRocket PeneX汽车网络安全测试系统

产品概述 上海控安汽车网络安全测试系统PeneX&#xff08;Penetrator X&#xff09;是一款支持对整车及车辆零部件及子系统实施网络安全测试的系统&#xff0c;其包含硬件安全、软件系统安全、车内通信及车外通信四大安全测试系统&#xff1b;支持合规性测试&#xff0c;包含国…

《TCP/IP网络编程》阅读笔记--基于 TCP 的半关闭

目录 1--基于TCP的半关闭 1-1--TCP单方面完全断开的问题 1-2--shutdown()函数 1-3--半关闭的必要性 2--基于半关闭的文件传输程序 1--基于TCP的半关闭 1-1--TCP单方面完全断开的问题 Linux 系统中的 close 函数会将 TCP Socket 的连接完全断开&#xff0c;这意味着不能收…

项目(智慧教室)第四部分,页面交互功能

一。页面构思 1.标题栏 大标题&#xff1a;智慧教室管理系统 小标题&#xff1a;灯光&#xff0c;报警&#xff0c;风扇&#xff0c;温度&#xff0c;湿度&#xff0c;光照 2.样式设计 背景设置。字体设置&#xff08;字体大小&#xff0c;格式&#xff0c;颜色&#xff09; 3.…

算法之双指针题型:

双指针例题小总结&#xff1a; 力扣27&#xff1a; 移除元素 力扣题目链接 双指针分为&#xff1a; 快慢双指针&#xff1a;同一个起点&#xff0c;同向出发 相向双指针&#xff1a;从两端出发&#xff0c;方向相反&#xff0c;终会相遇 经典的双指针&#xff08;快慢双指…

ESP32用作经典蓝牙串口透传模块与手机进行串口通信

ESP32用作经典蓝牙串口透传模块与手机进行串口通信 简介ESP32开发板Arduino程序手机与ESP32开发板进行蓝牙串口透传通信总结 简介 ESP32-WROOM-32模组集成了双模蓝牙包括传统蓝牙&#xff08;BR/EDR&#xff09;、低功耗蓝牙&#xff08;BLE&#xff09;和 Wi-Fi&#xff0c;具…

python实现三维应力云图

要画三维的应力分布云图&#xff0c;包括深度&#xff08;Z轴&#xff09;、X轴、Y轴&#xff0c;可以使用Matplotlib库中的mplot3d子库来实现 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D# 生成示例数据 x np.linspace(0,…

利用细胞流式术测定基因组大小和倍性

在denovo基因组测序中&#xff0c;通常会先预估基因组大小&#xff0c;杂合度等信息&#xff0c;根据基因组大小和复杂度来判断测序数据的深度&#xff0c;组装基因组的难易程度等。 预测基因组大小的方法主要有两种&#xff0c;基于Kmer频率的survey分析和基于流式细胞术&…

“指针跃动”受邀参加全球贸易服务峰会

“指针跃动”受邀参加全球贸易服务峰会 有“服”同享 共赢未来 引子 在全球化日益盛行的今天&#xff0c;贸易不再仅仅是物质的交流&#xff0c;更涉及到服务、理念、文化和科技的共享。中国国际服务贸易交易会全球贸易服务峰会&#xff0c;就是这个趋势的集中体现。在这次峰会…

连接虚拟机报错 Could not connect to ‘192.168.xxx.xxx‘ (port 22): Connection failed.

使用xshell连接虚拟机报错 Connecting to 192.168.204.129:22… Could not connect to ‘192.168.204.129’ (port 22): Connection failed. Type help’ to learn how to use Xshell prompt. 按网上的方法 是否能ping通内外网 ping www.baidu.com防火墙是否关闭 firewal…

数据分析综述

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

PyCharm 虚拟环境搭建

Anaconda搭建虚拟环境 安装 前往Anaconda官网&#xff08;https://www.anaconda.com/products/individual&#xff09;&#xff0c;下载适合您操作系统的Anaconda版本&#xff0c;建议下载最新的稳定版。这里可以直接进入这个&#xff1a;https://repo.anaconda.com/archive/ …

【python技巧】替换文件中的某几行

【python技巧】替换文件中的某几行 1. 背景描述2. 单行修改-操作步骤3. 多行修改-操作步骤 1. 背景描述 最近在写一个后端项目&#xff0c;主要的操作就是根据用户的前端数据&#xff0c;在后端打开项目中的代码文件&#xff0c;修改对应位置的参数&#xff0c;因为在目前的后…