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

Linux GPIO驱动开发实战:从传统接口到新式gpiod

一、顶级架构一句话总结设备树(gpio描述) → GPIO子系统 → gpiod接口 → 硬件引脚控制GPIO是嵌入式开发中最基础的外设接口Linux提供了新旧两套API新式gpiod接口更安全、更简洁。二、GPIO子系统架构架构层次┌─────────────────────────────────────────────────────────┐ │ GPIO子系统架构 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 用户空间 /sys/class/gpio/ 或 /dev/gpiochipX │ │ ↓ │ │ GPIO核心层 gpiolib.c (统一抽象层) │ │ ↓ │ │ GPIO控制器 gpio_chip (厂商驱动) │ │ ↓ │ │ 硬件层 GPIO寄存器操作 │ │ │ └─────────────────────────────────────────────────────────┘GPIO控制器结构structgpio_chip{constchar*label;// 控制器名称structgpio_device*gpiodev;// GPIO设备structdevice*parent;// 父设备structmodule*owner;// 所属模块int(*request)(structgpio_chip*chip,unsignedoffset);void(*free)(structgpio_chip*chip,unsignedoffset);int(*get_direction)(structgpio_chip*chip,unsignedoffset);int(*direction_input)(structgpio_chip*chip,unsignedoffset);int(*direction_output)(structgpio_chip*chip,unsignedoffset,intvalue);int(*get)(structgpio_chip*chip,unsignedoffset);void(*set)(structgpio_chip*chip,unsignedoffset,intvalue);// ...};三、新旧API对比接口对比表功能旧接口(整数型)新接口(描述符型)获取GPIOgpio_request()gpiod_get()释放GPIOgpio_free()gpiod_put()设置方向gpio_direction_input/output()gpiod_direction_input/output()读写值gpio_get_value() / gpio_set_value()gpiod_get_value() / gpiod_set_value()获取中断号gpio_to_irq()gpiod_to_irq()为什么推荐新接口特性旧接口新接口类型安全无整数有结构体指针方向管理手动自动错误处理返回值返回值ERR_PTR设备树集成需手动解析自动解析资源管理手动释放devm自动释放四、新式gpiod接口详解1. 头文件#includelinux/gpio/consumer.h#includelinux/gpio/driver.h2. 获取GPIO描述符// 从设备树获取单个GPIOstructgpio_desc*gpiod_get(structdevice*dev,constchar*con_id,enumgpiod_flagsflags);// 获取多个GPIOstructgpio_descs*gpiod_get_array(structdevice*dev,constchar*con_id,enumgpiod_flagsflags);// 获取索引GPIOstructgpio_desc*gpiod_get_index(structdevice*dev,constchar*con_id,unsignedintidx,enumgpiod_flagsflags);// 可选获取不存在不报错structgpio_desc*gpiod_get_optional(structdevice*dev,constchar*con_id,enumgpiod_flagsflags);3. 标志位enumgpiod_flags{GPIOD_ASIS0,// 不改变当前状态GPIOD_INGPIOD_FLAGS_BIT_DIR_SET,// 输入GPIOD_OUT_LOWGPIOD_FLAGS_BIT_DIR_SET|// 输出低GPIOD_FLAGS_BIT_DIR_OUT|GPIOD_FLAGS_BIT_DIR_VAL,GPIOD_OUT_HIGHGPIOD_FLAGS_BIT_DIR_SET|// 输出高GPIOD_FLAGS_BIT_DIR_OUT,};4. 释放GPIO// 释放单个GPIOvoidgpiod_put(structgpio_desc*desc);// 释放多个GPIOvoidgpiod_put_array(structgpio_descs*descs);// devm自动释放版本structgpio_desc*devm_gpiod_get(structdevice*dev,constchar*con_id,enumgpiod_flagsflags);voiddevm_gpiod_put(structdevice*dev,structgpio_desc*desc);5. 方向设置// 设置为输入intgpiod_direction_input(structgpio_desc*desc);// 设置为输出intgpiod_direction_output(structgpio_desc*desc,intvalue);// 设置为输出原始值不考虑active-lowintgpiod_direction_output_raw(structgpio_desc*desc,intvalue);6. 读写操作// 读取值考虑active-lowintgpiod_get_value(conststructgpio_desc*desc);// 读取原始值不考虑active-lowintgpiod_get_value_cansleep(conststructgpio_desc*desc);intgpiod_get_raw_value(conststructgpio_desc*desc);// 设置值考虑active-lowvoidgpiod_set_value(structgpio_desc*desc,intvalue);// 设置原始值voidgpiod_set_raw_value(structgpio_desc*desc,intvalue);// 设置多个GPIOvoidgpiod_set_array_value(unsignedintarray_size,structgpio_desc**desc_array,int*value_array);7. 获取中断号intgpiod_to_irq(conststructgpio_desc*desc);五、设备树配置GPIO设备树节点/ { my_device { compatible mycompany,mydevice; // 单个GPIO led-gpio gpio1 21 GPIO_ACTIVE_LOW; // 多个GPIO gpios gpio1 21 GPIO_ACTIVE_LOW, gpio1 22 GPIO_ACTIVE_HIGH, gpio2 10 GPIO_ACTIVE_LOW; // 带名称的GPIO reset-gpios gpio1 5 GPIO_ACTIVE_LOW; enable-gpios gpio1 6 GPIO_ACTIVE_HIGH; }; };GPIO标志说明标志说明GPIO_ACTIVE_HIGH高电平有效GPIO_ACTIVE_LOW低电平有效GPIO_OPEN_DRAIN开漏输出GPIO_OPEN_SOURCE开源输出GPIO_PULL_UP内部上拉GPIO_PULL_DOWN内部下拉六、完整驱动示例LED控制驱动#includelinux/module.h#includelinux/platform_device.h#includelinux/gpio/consumer.h#includelinux/of.h#includelinux/delay.hstructled_data{structgpio_desc*led_gpio;constchar*name;};staticintled_probe(structplatform_device*pdev){structled_data*data;structdevice*devpdev-dev;intret;datadevm_kzalloc(dev,sizeof(*data),GFP_KERNEL);if(!data)return-ENOMEM;// 获取GPIO自动设置为输出高电平data-led_gpiodevm_gpiod_get(dev,led,GPIOD_OUT_HIGH);if(IS_ERR(data-led_gpio)){dev_err(dev,Failed to get LED GPIO\n);returnPTR_ERR(data-led_gpio);}// 获取名称of_property_read_string(dev-of_node,label,data-name);platform_set_drvdata(pdev,data);dev_info(dev,LED %s initialized\n,data-name);return0;}staticintled_remove(structplatform_device*pdev){structled_data*dataplatform_get_drvdata(pdev);// 关闭LEDgpiod_set_value(data-led_gpio,0);dev_info(pdev-dev,LED removed\n);return0;}// LED闪烁函数staticvoidled_blink(structled_data*data,inttimes){inti;for(i0;itimes;i){gpiod_set_value(data-led_gpio,1);msleep(500);gpiod_set_value(data-led_gpio,0);msleep(500);}}staticconststructof_device_idled_of_match[]{{.compatiblemycompany,led,},{}};MODULE_DEVICE_TABLE(of,led_of_match);staticstructplatform_driverled_driver{.probeled_probe,.removeled_remove,.driver{.nameled_driver,.of_match_tableled_of_match,},};module_platform_driver(led_driver);MODULE_LICENSE(GPL);MODULE_AUTHOR(Driver Developer);按键输入驱动#includelinux/module.h#includelinux/platform_device.h#includelinux/gpio/consumer.h#includelinux/interrupt.h#includelinux/of.h#includelinux/input.hstructbutton_data{structgpio_desc*button_gpio;intirq;structinput_dev*input;};staticirqreturn_tbutton_irq_handler(intirq,void*dev_id){structbutton_data*datadev_id;intstate;// 读取按键状态stategpiod_get_value(data-button_gpio);// 上报按键事件input_report_key(data-input,KEY_ENTER,!state);input_sync(data-input);pr_info(Button %s\n,state?released:pressed);returnIRQ_HANDLED;}staticintbutton_probe(structplatform_device*pdev){structbutton_data*data;structdevice*devpdev-dev;intret;datadevm_kzalloc(dev,sizeof(*data),GFP_KERNEL);if(!data)return-ENOMEM;// 获取GPIO设置为输入data-button_gpiodevm_gpiod_get(dev,button,GPIOD_IN);if(IS_ERR(data-button_gpio))returnPTR_ERR(data-button_gpio);// 获取中断号data-irqgpiod_to_irq(data-button_gpio);if(data-irq0)returndata-irq;// 申请输入设备data-inputdevm_input_allocate_device(dev);if(!data-input)return-ENOMEM;data-input-namemy-button;input_set_capability(data-input,EV_KEY,KEY_ENTER);retinput_register_device(data-input);if(ret)returnret;// 注册中断retdevm_request_irq(dev,data-irq,button_irq_handler,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,button_irq,data);if(ret)returnret;platform_set_drvdata(pdev,data);dev_info(dev,Button initialized\n);return0;}staticconststructof_device_idbutton_of_match[]{{.compatiblemycompany,button,},{}};MODULE_DEVICE_TABLE(of,button_of_match);staticstructplatform_driverbutton_driver{.probebutton_probe,.driver{.namebutton_driver,.of_match_tablebutton_of_match,},};module_platform_driver(button_driver);MODULE_LICENSE(GPL);七、用户空间GPIO操作sysfs接口旧方式# 导出GPIOecho21/sys/class/gpio/export# 设置方向echoout/sys/class/gpio/gpio21/directionechoin/sys/class/gpio/gpio21/direction# 读写值echo1/sys/class/gpio/gpio21/valuecat/sys/class/gpio/gpio21/value# 释放GPIOecho21/sys/class/gpio/unexportlibgpiod工具新方式# 安装工具aptinstallgpiod-tools# 查看GPIO控制器gpiodetect# 查看GPIO状态gpioinfo gpiochip0# 设置GPIO值gpioset gpiochip0211# 读取GPIO值gpioget gpiochip021# 监控GPIO事件gpiomon gpiochip021八、常见问题与解决方案问题原因解决方案gpiod_get返回错误设备树配置错误检查gpio-*属性名和引用GPIO无法控制方向未设置或权限问题使用正确的flags参数中断不触发触发类型错误检查IRQF_TRIGGER_*标志值读取不正确active-low配置检查设备树GPIO_ACTIVE_*九、终极总结GPIO驱动 嵌入式开发的基础技能新接口优势类型安全、自动管理、设备树集成核心APIgpiod_get/put、gpiod_direction_*、gpiod_set/get_value设备树配置使用gpio-*属性描述GPIO最佳实践优先使用devm_前缀的资源管理API掌握GPIO驱动就掌握了嵌入式开发的基础

相关文章:

Linux GPIO驱动开发实战:从传统接口到新式gpiod

一、顶级架构一句话总结 设备树(gpio描述) → GPIO子系统 → gpiod接口 → 硬件引脚控制 GPIO是嵌入式开发中最基础的外设接口,Linux提供了新旧两套API,新式gpiod接口更安全、更简洁。二、GPIO子系统架构 架构层次 ┌─────────────────…...

强化学习(3)--最优状态价值最优策略

说明:本系列文章是我在学习了西湖大学赵世钰老师的《Mathematical Foundations of Reinforcement Learning》一书后的学习笔记,在B站上有赵老师的完整课程视频。 课程视频链接 PDF教材链接 本文代码链接 一、最优状态价值和最优策略 定义&#xff1a…...

MySQL 运算符详解

MySQL 运算符详解 MySQL 作为一款功能强大的关系型数据库管理系统,其运算符的使用贯穿于 SQL 语句的各个部分。本文将详细介绍 MySQL 中常用的运算符,包括算术运算符、比较运算符、逻辑运算符等,旨在帮助读者全面理解并掌握 MySQL 运算符的使用。 一、算术运算符 算术运算…...

Redis 服务器:全面解析与应用实践

Redis 服务器:全面解析与应用实践 引言 Redis(Remote Dictionary Server)是一款开源的、高性能的键值存储数据库。它采用内存作为存储介质,能够提供极快的读写速度,常用于缓存、会话管理、消息队列等领域。本文将全面解析Redis服务器的原理、配置、应用场景以及实践操作…...

机械臂+强化学习

机械臂 经典机械臂控制方法 运动学 动力学 基于...

DVWA——SQL Injection学习笔记

文章目录前言一、是什么&#xff1f;二、步骤1.Low2.Medium3.High4.Impossible代码核心功能安全特性总结总结手工注入&#xff1a;前言 一、是什么&#xff1f; 二、步骤 1.Low 代码如下&#xff1a; <?phpif( isset( $_REQUEST[ Submit ] ) ) {// Get input$id $_REQU…...

2026中国大模型市场火爆!阿里字节抢人才,年薪百万Offer等你来!

最新数据显示&#xff0c;2024年中国大模型市场规模已达294.16亿元&#xff0c;其中多模态大模型贡献156.3亿元&#xff0c;数字人、游戏等场景应用增长迅猛&#xff1b;更有预测指出&#xff0c;2026年这一市场规模将突破700亿元大关。图源自36氪研究院 市场竞争梯队也逐渐清晰…...

Vibe Coding 详细介绍

什么是 Vibe Coding&#xff1f;Vibe Coding&#xff08;氛围编程&#xff09;是由 AI 专家 Andrej Karpathy 在 2024 年初提出的新编程范式——一种"用自然语言编程"的开发方式。你描述"想要什么"&#xff0c;AI 来写代码。核心理念&#xff1a;"You…...

子系统是啥?---总线架构的实例化

目录 一、新手容易踩的认知坑 二、历史演变&#xff1a;从硬编码到子系统设备树的转变 &#xff08;1&#xff09;原始裸奔时代&#xff1a;无结构体、无设备树、无总线架构 &#xff08;2&#xff09;结构体封装时代&#xff1a;有结构体、无设备树、有总线架构 &…...

【Kali Linux】 2026.1 新功能详解

2026年3月24日发布&#xff0c;基于 2025.4 的更新&#xff0c;带来全新视觉体验和多项新工具&#xff01;&#x1f3a8; 2026 年度主题更新每年惯例的主题大换血&#xff0c;覆盖全流程&#xff1a;组件更新内容引导动画修复了实时镜像卡在第一帧的问题&#xff0c;循环更流畅…...

Java RAG入门基础教程(非常详细),用LangChain4j构建问答系统看这篇就够了!

1. 引言&#xff1a;为什么需要 RAG 1.1 大模型的局限性 在使用大语言模型&#xff08;LLM&#xff09;时&#xff0c;我们常常遇到以下问题&#xff1a; ❌ 问题 1&#xff1a;模型不知道企业内部信息用户&#xff1a;我们公司的年假政策是什么&#xff1f;AI&#xff1a;抱…...

C语言学习的第一周

1.自我介绍我姓马&#xff0c;来自成都的一个双非一本&#xff0c;目前大一&#xff0c;神秘专业&#xff0c;目前学c语言是兴趣使然和为了未来转码作铺垫&#xff0c;多项技能傍身也没错嘛2.学习目标打下c语言的坚实基础&#xff0c;方向初步是逐步从c语言到c再到更深度的知识…...

简易数据采集与分析系统

我用 Trae&#xff08;SOLO Coder&#xff09; 自主开发了这款专为硬件工程师打造的数据分析工具&#xff0c;无需懂代码&#xff0c;点点鼠标即可完成采集卡数据全流程分析。核心功能一键导入采集卡原始 ADC 数据&#xff0c;自动适配 12/16 位分辨率&#xff0c;精准转换为真…...

CSS如何利用Less快速生成颜色渐变背景_使用混合函数生成多样渐变

用带参数的.gradient-bg()混合函数&#xff0c;支持start-color、end-color、direction及透明度微调&#xff0c;避免硬编码&#xff1b;多色用.gradient-bg-stops()&#xff1b;注意转义方向值、变量定义顺序、CSS变量分层及Safari渲染兼容性。Less混合函数怎么写才能生成可复…...

别再让图片拖慢你的多模态模型了:手把手教你用Q-Former和PruMerge压缩视觉Token(附代码)

视觉Token压缩实战&#xff1a;用Q-Former和PruMerge提升多模态模型效率 当你在深夜调试一个多模态问答系统时&#xff0c;突然收到告警——GPU显存爆了。查看日志发现&#xff0c;一张用户上传的4K产品图片生成了超过3万个视觉Token&#xff0c;直接拖垮了整个推理流程。这不是…...

深入解析MCU:从哈佛架构到智能家居应用

1. MCU的哈佛架构揭秘 第一次拆开智能音箱时&#xff0c;我盯着那块指甲盖大小的芯片发愣——这就是控制所有功能的"大脑"&#xff1f;后来才知道&#xff0c;这种叫MCU的微型计算机&#xff0c;核心秘密藏在它的哈佛架构里。想象你同时用两只手写字&#xff1a;左手…...

微信聊天记录导出终极指南:如何快速安全备份你的珍贵回忆

微信聊天记录导出终极指南&#xff1a;如何快速安全备份你的珍贵回忆 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾经因为手机丢失或系统升级&#xff0c;担心…...

HsMod:革新性炉石传说增强工具,全方位提升游戏体验

HsMod&#xff1a;革新性炉石传说增强工具&#xff0c;全方位提升游戏体验 【免费下载链接】HsMod Hearthstone Modification Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod 一、你是否也面临这些游戏痛点&#xff1f; 当你兴致勃勃地开启…...

Linux学习进展 计算机基本硬件结构

学习Linux系统&#xff0c;本质上是掌握“软件如何操控硬件”的逻辑——Linux作为开源操作系统&#xff0c;其内核与硬件的深度绑定的特性&#xff0c;决定了我们必须先理解计算机基本硬件结构&#xff0c;才能更清晰地明白Linux内核的调度机制、资源管理逻辑&#xff0c;以及后…...

Excel文件压缩难?这4个方法让文件秒变小,传输再也不卡壳!

在数据驱动的办公场景中&#xff0c;Excel文件的"臃肿"问题越来越普遍。比如财务部门每月导出的销售报表&#xff0c;因包含近百张动态图表和历史数据&#xff0c;文件大小可能达到几十MB&#xff1b;市场调研团队收集的问卷数据&#xff0c;若未做图片压缩&#xff…...

基于springboot+vue高校物资信息采购系统hx0807

文章目录详细视频演示技术介绍功能介绍核心代码系统效果图源码获取详细视频演示 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 技术介绍 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomca…...

【2026春招必看】MiniMax大模型算法岗面试深度解析:薪资福利+核心考点+项目经验!手把手教你冲刺高薪Offer!

今天给大家梳理出来minmax的福利待遇&#xff0c;顺便分享面试大模型算法岗的面试题。喜欢本文记得收藏、关注、点赞。 废话不多说&#xff0c;我们要开车了。 薪资介绍 月薪&#xff08;base&#xff09; 应届/初级&#xff08;1–2年&#xff09;&#xff1a;35K–50K / 月中…...

十大AI写作工具迎来深度评测,AIGC论文助手从功能性、稳定性等维度出发,量化分析其核心表现。

工具名称 核心优势 适用场景 aicheck 快速降AIGC率至个位数 AIGC优化、重复率降低 aibiye 智能生成论文大纲 论文结构与内容生成 askpaper 文献高效整合 开题报告与文献综述 秒篇 降重效果显著 重复率大幅降低 一站式论文查重降重 查重改写一站式 完整论文优化…...

5分钟搞懂LLM、Token、Agent,解锁AI核心价值!

本文深入浅出地解析了AI核心概念&#xff0c;从基础的大语言模型&#xff08;LLM&#xff09;到Token、Tools、Skills、MCP&#xff0c;再到智能体&#xff08;Agent&#xff09;的演进。强调了AI虽擅长语言生成但缺乏实际操作能力&#xff0c;并通过工具和接口&#xff08;Too…...

MTK平台Camera移植避坑指南:从驱动添加到DWS配置的完整流程(基于Kernel 4.19)

MTK平台Camera移植避坑指南&#xff1a;从驱动添加到DWS配置的完整流程&#xff08;基于Kernel 4.19&#xff09; 在嵌入式设备开发中&#xff0c;Camera模块的移植往往是系统集成中最具挑战性的环节之一。特别是基于MTK平台的Android设备&#xff0c;Camera驱动的移植涉及从内…...

从LLM到A2A:AI工程师必备7大核心概念解析,掌握AI未来!

从 LLM 到 A2A&#xff1a;AI 工程师必须掌握的七个核心概念 大模型 API Agent MCP Skill A2A 全景解析 你是否曾经困惑&#xff1a;调用一个大模型 API 和「部署一个 Agent」到底有什么本质区别&#xff1f;MCP 和 Skill 都是「能力扩展」&#xff0c;为什么需要两套机制…...

5分钟上手libhv:用自带httpd和curl工具快速搭建本地测试服务

5分钟实战libhv&#xff1a;零配置构建高效本地HTTP测试环境 第一次听说libhv时&#xff0c;我正被一个紧急的前后端联调任务逼得焦头烂额。当时需要快速搭建一个模拟API服务&#xff0c;但Node.js环境配置卡在了权限问题上&#xff0c;Python的SimpleHTTPServer又无法满足复杂…...

Python 办公自动化封神篇:PDF+Word 全自动处理,从此告别复制粘贴!

前言每天对着一堆 PDF 合并拆分、Word 改格式、手动做报表&#xff1f;重复操作又累又容易错&#xff0c;Python 几行代码就能全自动搞定&#xff01;这篇不讲废话、不搞应试&#xff0c;全是能直接用在工作 / 学习 / 小项目的干货&#xff0c;从读取、创建、批量生成到美化排版…...

数字后端 | Innovus 中解决 Congestion 的常用方法

前言 Congestion&#xff08;布线拥塞&#xff09;是数字后端实现中常见的问题。当局部区域标准单元过密、pin 密度过高或走线方向冲突时&#xff0c;就会出现 Congestion&#xff0c;最终可能导致 DRC 违例增多甚至布线失败。本文介绍在 Innovus 中如何查看和分析 Congestion&…...

Polars 2.0大规模清洗踩坑实录:3类隐性OOM陷阱+4步零拷贝修复法,DBA紧急封存的内部手册

第一章&#xff1a;Polars 2.0大规模清洗踩坑实录&#xff1a;3类隐性OOM陷阱4步零拷贝修复法&#xff0c;DBA紧急封存的内部手册三类隐性OOM陷阱真实复现 在处理12TB电商日志&#xff08;单文件超80GB Parquet&#xff09;时&#xff0c;Polars 2.0默认配置下静默触发OOM——非…...