资讯动态

pinctrl 子系统、GPIO 子系统、非阻塞 IO

发布时间:2026/10/15 10:37:26 来源:尧图企业网站定制
一、Linux 驱动底层核心思想1. 面向对象万物皆对象完成从抽象到具体的描述。2. 设备与驱动分离硬件信息放在设备树驱动代码独立。内核运行时由设备树向驱动传递硬件资源降低移植难度减少重复代码编写。3. 驱动分层思想内核采用面向对象设计同类设备定义基类子类可继承基类函数也可重写覆盖同名函数依靠多态提升代码复用。内核拆分为多个独立子系统协同工作pinctrl、GPIO、I2C、SPI 等子系统各司其职。二、pinctrl 子系统1. 基本概念Pin controller devices引脚控制器对应 IOMUX管理引脚复用功能、电气特性配置寄存器信息由芯片厂商预先写好。Pinctrl client devicespinctrl 的客户端即使用 pinctrl 引脚配置的外设设备。作用在设备树中配置引脚无需手动读写 IOMUX 寄存器。2. 设备树 DTS 编写i.MX6ULL1iomux 控制器节点iomuxc020e0000compatible 属性fsl,imx6ul-iomuxc对应内核源码drivers/pinctrl/freescale/pinctrl-imx6ul.c模块通过arch_initcall初始化。2自定义引脚组使用标签分组如pinctrl_ledfsl,pins存放引脚宏与电气参数引脚宏定义在imx6ul-pinfunc.h。每个引脚条目格式为mux_reg conf_reg input_reg mux_mode input_val分别对应复用寄存器偏移、配置寄存器偏移、输入寄存器偏移、复用模式和输入值。3外设节点引用pinctrl-names引脚状态列表默认default还可定义sleep、idle等状态pinctrl-0引用预先定义的引脚配置对应 default 状态pinctrl-1可引用另一组引脚配置对应 sleep 等状态statusokay启用设备disabled禁用设备。4参考文档路径内核中 pinctrl 设备树绑定规范文档Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt飞思卡尔 i.MX 系列 pinctrl 绑定说明Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt通用 pinctrl 设备树绑定规范示例/* 引脚分组节点定义LED引脚复用与电气属性 */ pinctrl_led: ledgrp { fsl,pins MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0电气特性的配置 */ ; }; /* LED外设设备节点引用上面pinctrl引脚配置 */ gpioleds { #address-cells 1; #size-cells 1; compatible pute-gpioleds; pinctrl-names default; // 定义引脚的状态名称列表引脚默认状态 pinctrl-0 pinctrl_led; // 引用pinctrl_led引脚配置节点 led-gpio gpio1 3 GPIO_ACTIVE_LOW; // 自定义属性低电平有效 status okay; // okay启用、disabled禁用、reserved保留 };3. pinctrl 开发流程1在 iomuxc 节点内添加引脚分组配置引脚复用、电气属性2在设备节点引用 pinctrl 配置3编译生成 dtb 设备树二进制文件下载至开发板4修改驱动代码删除手动 ioremap 映射 IOMUX 寄存器的旧代码5调试验证查看/sys/firmware/devicetree确认设备树节点加载加载驱动模块后查看 sysfs 属性上层应用测试。三、GPIO 子系统1. 设备树 DTS 编写1GPIO 控制器节点compatible 属性匹配芯片 GPIO 驱动包含寄存器基地址、中断相关属性添加gpio-controller标识。2外设节点通过gpios属性指定使用的 GPIO 编号与有效电平GPIO_ACTIVE_LOW代表低电平有效。2. GPIO 常用内核 API函数功能返回值说明of_get_named_gpio从设备树节点解析获取 GPIO 编号成功返回 GPIO 号失败返回负数gpio_request申请 GPIO 硬件资源成功返回 0失败负数 (常见 - EBUSY)devm_gpio_request申请 GPIO 资源设备卸载自动释放资源成功 0失败负数gpio_free手动释放 GPIO 资源无返回gpio_direction_output设置 GPIO 为输出模式成功 0失败负数gpio_direction_input设置 GPIO 为输入模式成功 0失败负数gpio_set_value设置 GPIO 输出高低电平无返回gpio_get_value读取 GPIO 输入引脚电平0 低电平1 高电平gpio_to_irq由 GPIO 编号获取对应的中断号成功返回中断号失败负数说明devm_gpio_request是gpio_request的资源管理版本驱动卸载或 probe 失败时内核自动释放无需手动调用gpio_free推荐在 probe 函数中使用。此外新内核推荐使用gpiod_系列 API基于描述符如devm_gpiod_get、gpiod_set_value与设备树gpios属性配合更安全。3. GPIO 开发步骤删除旧驱动中 ioremap 映射 GPIO 寄存器、手动配置 PDIR 等寄存器代码使用of_get_named_gpio解析设备树拿到 GPIO 编号调用gpio_request申请 GPIO 资源设置 GPIO 输入 / 输出方向输出可设置默认电平输入可读取引脚状态使用完毕调用gpio_free释放 GPIO 资源。4. pinctrl 与 GPIO 子系统关系pinctrl第一步配置引脚复用功能把引脚设置为 GPIO 功能配置引脚电气属性。GPIO 子系统第二步引脚已经复用为 GPIO 后控制引脚输入输出、读写高低电平。顺序pinctrl 配置引脚功能 → GPIO 子系统操作引脚。四、非阻塞 IO按键驱动案例1. 阻塞 IO 与非阻塞 IO 概念阻塞 IO应用调用 read 等函数若无数据进程休眠等待直到有数据返回后唤醒。非阻塞 IO调用 read 时如果没有数据驱动不休眠立刻返回错误应用程序不会挂起。应用需要循环轮询持续查询设备状态。2. 非阻塞 IO 驱动开发要点应用打开设备时传入O_NONBLOCK标记驱动通过file-f_flags识别该标志。read 函数内判断如果没有按键数据并且是非阻塞模式直接返回 - EAGAIN不进入休眠。阻塞模式下无数据时调用wait_event_interruptible进入等待队列休眠。按键中断触发采集按键状态唤醒等待队列应用读取按键值。read 返回时使用copy_to_user将按键数据拷贝到用户空间并检查返回值若拷贝失败返回 - EFAULT。注意非阻塞 IO 需要应用层不断轮询会占用 CPU 资源适合简单场景。若需更高效的事件通知机制可配合poll/epoll接口使用驱动实现poll操作函数在等待队列上注册应用通过select/epoll等待可读事件避免忙轮询。3. 开发整体流程按键驱动设备树添加 pinctrl 引脚配置在按键节点定义 gpios 属性驱动代码通过 of 接口解析设备树申请 GPIO 资源配置引脚为输入注册 GPIO 中断按键触发中断记录按键状态在 read 接口判断O_NONBLOCK标志区分阻塞 / 非阻塞模式应用 open 时传入 O_NONBLOCK循环 read 轮询读取按键。五、整体总结基于设备树开发驱动利用 pinctrl 完成引脚复用配置再通过 GPIO 子系统操作引脚。pinctrl、GPIO 子系统依托 Linux 驱动分层、设备驱动分离思想将硬件描述放到设备树驱动只处理业务逻辑。在按键这类输入设备中可结合非阻塞 IO应用轮询查询设备状态无数据时驱动不阻塞进程实现非阻塞读取。三个子系统协作关系清晰pinctrl 负责引脚复用与电气属性配置GPIO 子系统负责引脚电平读写非阻塞 IO 机制负责应用与驱动之间的高效数据交互。理解这一链路是掌握 Linux 字符设备驱动开发的关键基础。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑