ARM Linux 驱动开发篇---GPIO子系统详解-- Ubuntu20.04

ARM Linux 驱动开发篇---GPIO子系统详解-- Ubuntu20.04
🎬 渡水无言个人主页渡水无言

专栏传送门: 《linux专栏》   《嵌入式linux驱动开发》《freertos专栏
⭐️流水不争先,争的是滔滔不绝

 📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生

| 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生

在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连

目录

前言

一、GPIO 子系统核心定位

二、IMX6ULL 的 GPIO 子系统实战(设备树 + 驱动)

2.1、配置设备树中的 GPIO

2.1.1、pinctrl 配置

2.1.2、在设备节点中指定 GPIO

2.1.3、GPIO 控制器节点

2.2、GPIO 驱动程序简介

2.2.1、驱动匹配

2.2.2、驱动入口

2.2.3、核心结构体(gpio_chip)

总结


前言

上一节我们讲解了pinctrl子系统,其核心作用是配置 PIN 的复用功能电气属性。若pinctrl将某个 PIN 复用为 GPIO,后续对 GPIO 的操作(输入 / 输出、读写电平)就需要依靠GPIO 子系统来完成。

GPIO 子系统的设计目标是简化 GPIO 的驱动开发,这样我们只需在设备树中配置 GPIO 相关信息,无需直接操作底层寄存器,即可通过内核提供的 API 函数轻松操控 GPIO。

本文基于 IMX6ULL 开发板,从「子系统简介→设备树配置→驱动原理」逐步拆解,详细讲解了GPIO 子系统。


一、GPIO 子系统核心定位

GPIO 子系统是 Linux 内核针对 GPIO 外设封装的标准化框架,核心职责包括:
        初始化 GPIO 控制器(解析设备树 GPIO 节点信息);
        提供统一的 GPIO 操作 API(申请、释放、输入 / 输出配置、电平读写);
        屏蔽不同 SOC 的 GPIO 硬件差异(如 IMX6ULL 与 STM32 的 GPIO 寄存器差异)。
简单来说,pinctrl负责 “把 PIN 变成 GPIO”,GPIO 子系统负责 “把 GPIO 用起来”,二者协同工作,构成 GPIO 驱动的完整链路。

二、IMX6ULL 的 GPIO 子系统实战(设备树 + 驱动)

以 IMX6ULL 开发板的「SD 卡检测引脚」为例(UART1_RTS_B 复用为 GPIO1_IO19),介绍 GPIO 子系统的设备树配置和驱动底层原理。

2.1、配置设备树中的 GPIO

GPIO 的设备树配置主要分为两步:

1、通过 pinctrl 配置 PIN 复用。

2、在设备节点中指定 GPIO 信息

2.1.1、pinctrl 配置

打开开发板专属的设备树文件imx6ull-alientek-emmc.dts,可以看到在&iomuxc节点的imx6ul-evk子节点中,已存在 SD 卡检测引脚的 pinctrl 配置:

pinctrl_hog_1: hoggrp-1 { fsl,pins = < MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD 引脚,复用为GPIO1_IO19 */ // 其他PIN配置... >; };

上述代码就是将 UART1_RTS_B 引脚复用为 GPIO1_IO19,并配置电气属性,和上一期博客里的 pinctrl 配置逻辑完全一致。

2.1.2、在设备节点中指定 GPIO

SD 卡挂载在 IMX6ULL 的usdhc1接口上,usdhc1节点就是 SD 卡的设备树节点。我们需要在该节点中添加cd-gpios属性,这样便能让驱动知道SD 卡检测引脚使用的是哪个 GPIO:

&usdhc1 { pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_usdhc1>; pinctrl-1 = <&pinctrl_usdhc1_100mhz>; pinctrl-2 = <&pinctrl_usdhc1_200mhz>; cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; /* SD卡检测GPIO:GPIO1_IO19,低电平有效 */ keep-power-in-suspend; enable-sdio-wakeup; vmmc-supply = <&reg_sd1_vmmc>; status = "okay"; };
cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>

此行代码就是添加的描述 SD 卡的 CD 引脚 pinctrl 信息所在的子节点。

        &gpio1:指定 GPIO 所属的控制器(GPIO1 控制器);
        19:指定 GPIO1 控制器的第 19 号引脚(即 GPIO1_IO19);
        GPIO_ACTIVE_LOW:指定 GPIO 低电平有效,也就是检测到低电平时,表示 SD 卡插入,若改为GPIO_ACTIVE_HIGH则为高电平有效。

根据上面这些信息,SD 卡驱动程序就可以使用 GPIO1_IO19 来检测 SD 卡的 CD 信号了。

2.1.3、GPIO 控制器节点

打开imx6ull.dtsi,可找到 GPIO1 控制器的节点定义,这是 GPIO 子系统工作的基础:

gpio1: gpio@0209c000 { compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio"; /* 驱动匹配标识 */ reg = <0x0209c000 0x4000>; /* GPIO1控制器寄存器基地址+长度 */ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* 中断配置 */ gpio-controller; /* 标识此节点是GPIO控制器 */ #gpio-cells = <2>; /* GPIO属性的cell数量,固定为2 */ interrupt-controller; /* 标识此节点是中断控制器 */ #interrupt-cells = <2>; };

gpio1 节点信息描述了 GPIO1 控制器的所有信息,重点就是 GPIO1 外设寄存器基地址以及兼容 属 性。

gpio1 节点的 compatible 属性有两个,分别为“fsl,imx6ul-gpio”和“fsl,imx35- gpio”,在 Linux 内核中搜索这两个字符串就可以找到 I.MX6UL 的 GPIO 驱动程序。

reg 属性设置了 GPIO1 控制器的寄存器基地址为 0X0209C000,从I.MX6ULL 参考手册中可以看到GPIO1 控制器的基地址就是 0X0209C000,如下图所示:

gpio-controller:必须添加,表明该节点是一个 GPIO 控制器;
#gpio-cells = <2>:指定描述一个 GPIO 时需要 2 个参数(第一个是 GPIO 编号,第二个是电平极性,如 0 = 高电平有效,1 = 低电平有效);

2.2、GPIO 驱动程序简介

IMX6ULL 的 GPIO 驱动文件是drivers/gpio/gpio-mxc.c,该驱动是典型的平台设备驱动,核心逻辑是解析设备树 GPIO 节点、初始化 GPIO 控制器,并向内核注册 GPIO 操作接口。

2.2.1、驱动匹配

gpio-mxc.c中,通过of_device_id结构体数组与设备树的compatible属性匹配:

static const struct of_device_id mxc_gpio_dt_ids[] = { { .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], }, { .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], }, /* 匹配GPIO1节点 */ { /* 哨兵节点 */ } };

设备树中 GPIO1 节点的compatible = "fsl,imx35-gpio",因此该驱动会被匹配执行。

因此 gpio-mxc.c 就是 I.MX6ULL 的 GPIO 控制器驱动文件。gpio-mxc.c 所在的目录为drivers/gpio,打开这个目录可以看到很多芯片的 gpio 驱动文件, “gpiolib”开始的文件是 gpio 驱动的核心文件。

2.2.2、驱动入口

驱动匹配成功后,mxc_gpio_probe函数会被调用,核心工作的是:

  1. 读取设备树中 GPIO 控制器的reg属性(寄存器基地址),并进行内存映射;
  2. 初始化 GPIO 寄存器(关闭中断、清除状态等);
  3. 初始化gpio_chip结构体(封装 GPIO 操作函数,如输入 / 输出配置、电平读写);
  4. 通过gpiochip_add函数向内核注册 GPIO 控制器,供上层 API 调用。

2.2.3、核心结构体(gpio_chip)

gpio_chip是 GPIO 子系统的核心结构体,封装了所有 GPIO 操作函数,内核通过该结构体提供统一的 GPIO API:

struct gpio_chip { const char *label; struct device *dev; int (*request)(struct gpio_chip *chip, unsigned offset); /* GPIO申请 */ void (*free)(struct gpio_chip *chip, unsigned offset); /* GPIO释放 */ 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); /* 读取GPIO电平 */ void (*set)(struct gpio_chip *chip, unsigned offset, int value); /* 设置GPIO电平 */ // 其他成员... };

半导体厂商已在驱动中实现了这些函数,我们无需关心底层寄存器操作,直接使用内核提供的 API 即可。


总结

本期博客详细讲解了GPIO 子系统。

Read more

[安卓] Kotlin中的架构演进:从MVC到MVVM

从Java到Kotlin,不仅仅是语法的升级,更是架构思维的进化。本文将带你全面掌握Kotlin在Android开发中三种核心架构模式:MVC、MVP、MVVM,揭示如何用Kotlin特性写出更优雅的架构代码。 引言:为什么Android开发者需要架构模式? 如果你有过Java Android开发经验,一定遇到过这些问题:Activity/Fragment代码臃肿(动辄上千行)、业务逻辑与UI逻辑混杂、测试困难、代码难以维护。架构模式正是为了解决这些问题而生的。而Kotlin,以其简洁的语法和强大的特性,让这些架构模式的实现变得更加优雅。 让我们从一个真实案例开始——用户登录模块,看看在不同架构模式下的演变: // 糟糕的无架构代码(Java风格)class BadLoginActivity :AppCompatActivity(){privatelateinitvar editUsername: EditText privatelateinitvar editPassword: EditText privatelateinitvar buttonLogin: Button

By Ne0inhk
【Kafka进阶篇】深入Kafka内部:日志存储的设计思路,藏着中间件高性能的真相

【Kafka进阶篇】深入Kafka内部:日志存储的设计思路,藏着中间件高性能的真相

🍃 予枫:个人主页 📚 个人专栏: 《Java 从入门到起飞》《读研码农的干货日常》 💻 Debug 这个世界,Return 更好的自己! 引言 做分布式开发的同学,几乎都用过Kafka,但多数人只停留在“生产者发消息、消费者收消息”的表层使用,很少深究:百万级消息并发下,Kafka如何快速定位目标消息?底层的.log、.index、.timeindex文件各司其职,又是如何配合实现高效读写的?今天就从物理层面拆解Kafka日志存储与索引机制,吃透这部分,不仅能搞定面试难点,更能在生产环境中精准优化Kafka性能。 文章目录 * 引言 * 一、前言:为什么要搞懂Kafka日志与索引机制? * 二、核心前提:Kafka日志的“分段存储”设计 * 三、深度拆解:三种核心文件的作用与结构 * 3.1 .log文件:消息的“真正存储载体” * 关键细节: * 3.2

By Ne0inhk

PostgreSQL:详解 PostGIS 地理信息数据处理

更多内容请见: 《深入掌握PostgreSQL数据库》 - 专栏介绍和目录 文章目录 * 一、PostGIS 简介 * 1.1 什么是 PostGIS? * 1.2 PostGIS 能做什么? * 二、安装与启用 PostGIS * 2.1 安装方式(以 Ubuntu 为例) * 2.2 验证安装 * 三、核心数据类型 * 3.1 geometry(几何类型) * 3.2 geography(地理类型) * 3.3 常见几何子类型(OGC 标准) * 四、空间数据表示与输入 * 4.1 WKT(Well-Known Text)

By Ne0inhk
Flutter 组件 fam 适配鸿蒙 HarmonyOS 实战:文件资产监控,构建分布式媒体管理与全场景资源分发治理架构

Flutter 组件 fam 适配鸿蒙 HarmonyOS 实战:文件资产监控,构建分布式媒体管理与全场景资源分发治理架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 fam 适配鸿蒙 HarmonyOS 实战:文件资产监控,构建分布式媒体管理与全场景资源分发治理架构 前言 在鸿蒙(OpenHarmony)生态迈向万物智联、涉及海量分布式文件同步、社交应用图片即时刷新及严苛的沙箱存储审计背景下,如何实现一套既能覆盖系统级文件变动感知、又能保障低功耗运行且具备“亚秒级”事件回调能力的“文件监控中心”,已成为决定应用数据发现速率与存储交互稳健性的基石。在鸿蒙设备这类强调分布式文件系统(HMDFS)协同且存储分区高度隔离的场景下,如果应用依然采用低效的定时轮询扫描,由于由于 I/O 资源的无效损耗,极易由于由于“电量泄露”导致鸿蒙应用在后台由于由于由于由于后台任务限制而被系统强制挂起。 我们需要一种能够解耦物理路径、支持递归监听且符合鸿蒙事件驱动模型的文件监控方案。 fam(File Asset Monitor)为 Flutter 开发者引入了“存储感知”范式。它不是简单的 File 操作扩展,

By Ne0inhk