Linux 内核 GPIO 用户空间接口

Linux GPIO架构

GPIO是通用输入/输出的缩写,是嵌入式Linux系统中最常用的外设之一。

在内部,Linux 内核对 GPIO 的访问方法可以参考如下内容

GPIO Driver Interface — The Linux Kernel documentation

GPIO Descriptor Consumer Interface — The Linux Kernel documentation

为了管理 GPIO 注册和分配,Linux 内核中有一个名为 gpiolib 的框架。此框架为在内核空间和用户空间应用程序中运行的设备驱动程序提供 API。

旧的方法:sysfs 接口

在 Linux 版本 4.7 之前,在用户空间中管理 GPIO 行的接口始终通过导出在 /sys/class/gpio 中的文件在 sysfs 中。例如,如果我想设置GPIO,我必须:

  1. 确定GPIO线的编号。
  2. 导出 GPIO,将其编号写入 /sys/class/gpio/export
  3. 将 GPIO 行配置为输出输出到 /sys/class/gpio/gpioX/direction
  4. 将 GPIO 写入 1 设置为 /sys/class/gpio/gpioX/value

举个实际的例子,要从用户空间设置 GPIO 504,我们必须执行以下命令:

# echo 504 > /sys/class/gpio/export
# echo out > /sys/class/gpio/gpio504/direction
# echo 1   > /sys/class/gpio/gpio504/value

这个界面非常简单,运行良好,但有一些不足:

  • GPIO 的分配不绑定到任何进程,因此,如果使用 GPIO 的进程结束执行或崩溃,则 GPIO 行可能保持导出状态。
  • 我们可以让多个进程访问同一 GPIO 行,因此并发可能是一个问题。
  • 写入多个引脚需要对大量文件(导出方向等)进行 open()/read()/write()/close() 操作。
  • 捕获事件(来自 GPIO 线路的中断)的轮询过程不可靠。
  • 没有用于配置GPIO线路的接口(开源、开漏等)。
  • 分配给 GPIO 线路的编号不稳定。

新的方法:chardev 接口

从 Linux 版本 4.8 开始,GPIO sysfs 接口被弃用,如果想要在4.8版本以后仍然使用旧的版本,可以在Linux config中将如下开关配置为Y

 CONFIG_GPIO_SYSFS =Y

新的方法基于字符设备的新 API,可以从用户空间访问 GPIO 。

每个 GPIO 控制器 (gpiochip) 在 /dev 中都有一个字符设备,我们可以使用文件操作 (open(), read(), write(), ioctl(), poll(), close( 来管理 GPIO 行并与之交互:

# ls /dev/gpiochip*
/dev/gpiochip0  /dev/gpiochip2  /dev/gpiochip4  /dev/gpiochip6
/dev/gpiochip1  /dev/gpiochip3  /dev/gpiochip5  /dev/gpiochip7

尽管这个新的 char 设备接口可以防止使用 echo 和 cat 等标准命令行工具操作 GPIO,但与 sysfs 接口相比,它具有一些优势,包括:

  • GPIO 的分配与使用它的进程相关联,从而改进了对用户空间进程使用哪些 GPIO 行的控制。
  • 可以一次读取或写入多个GPIO线。
  • 可以按名称查找GPIO控制器和GPIO线路。
  • 可以配置引脚的状态(开源、漏极开路等)。
  • 捕获事件(来自 GPIO 线路的中断)的轮询过程是可靠的。

示例C代码:具体参照  libgpiod 项目

#include <stdio.h>
#include <gpiod.h>int main() {// 打开 GPIO 控制器struct gpiod_chip *chip;chip = gpiod_chip_open("/dev/gpiochip0");// 设置要控制的 GPIO 线路编号int gpioLine = 17;// 获取指定线路的 GPIO 行对象struct gpiod_line *line;line = gpiod_chip_get_line(chip, gpioLine);// 设置 GPIO 行为输出模式int ret = gpiod_line_request_output(line, "example", 0);if (ret < 0) {printf("无法设置 GPIO 行为输出模式\n");return 1;}// 将 GPIO 置高gpiod_line_set_value(line, 1);// 延时一段时间usleep(1000000);// 将 GPIO 置低gpiod_line_set_value(line, 0);// 释放 GPIO 行对象gpiod_line_release(line);// 关闭 GPIO 控制器gpiod_chip_close(chip);return 0;
}

库和工具

为了使用这个新的 char 设备接口,libgpiod 项目提供了一个库和一组工具。

例如,以下 C 语言程序使用 libgpiod 读取 GPIO 行:

int main() {struct gpiod_chip *chip;struct gpiod_line *line;int req, value;chip = gpiod_chip_open("/dev/gpiochip0");if (!chip)return -1;line = gpiod_chip_get_line(chip, 3);if (!line) {gpiod_chip_close(chip);return -1;}req = gpiod_line_request_input(line, "gpio_state");if (req) {gpiod_chip_close(chip);return -1;}value = gpiod_line_get_value(line);printf("GPIO value is: %d\n", value);gpiod_chip_close(chip);
}

该库是 C 语言,但有其他语言(如 C++ 和 Python)的绑定。

如果要从终端管理 GPIO 行并与之交互,可以使用 libgpiod 提供的命令行工具。

gpiodetect 命令将列出所有 gpiochip、labels和 GPIO  lines:

# gpiodetect
gpiochip0 [209c000.gpio] (32 lines)
gpiochip1 [20a0000.gpio] (32 lines)
gpiochip2 [20a4000.gpio] (32 lines)
gpiochip3 [20a8000.gpio] (32 lines)
gpiochip4 [20ac000.gpio] (32 lines)
gpiochip5 [20b0000.gpio] (32 lines)
gpiochip6 [20b4000.gpio] (32 lines)
gpiochip7 [mcp23s08.0] (8 lines)

gpioinfo 命令

# gpioinfo 0
gpiochip0 - 32 lines:line   0:      unnamed       unused   input  active-highline   1:      unnamed       unused   input  active-highline   2:      unnamed       unused   input  active-highline   3:      unnamed        "scl"  output  active-high [used open-drain]line   4:      unnamed       unused   input  active-highline   5:      unnamed       unused   input  active-highline   6:      unnamed        "sda"  output  active-high [used open-drain]line   7:      unnamed "Push Button"  input  active-low  [used]line   8:      unnamed       unused   input  active-highline   9:      unnamed          "?"  output  active-high [used]line  10:      unnamed       unused   input  active-highline  11:      unnamed       unused   input  active-high
[...]

 gpioset 命令  将gpiochip7组的第0个引脚电平设置为1

# gpioset gpiochip7 0=1

gpioget 命令  读取gpiochip7组的第0个引脚电平,取得值为1

# gpioget gpiochip7 0
1

gpiomon 命令 可以检测端子变化状态

# gpiomon 0 7
event: FALLING EDGE offset: 7 timestamp: [    4564.943435210]
event:  RISING EDGE offset: 7 timestamp: [    4565.072156210]
event: FALLING EDGE offset: 7 timestamp: [    4566.113641877]
event:  RISING EDGE offset: 7 timestamp: [    4566.366691877]

所有这些命令的源代码都可以在 libgpiod 存储库中找到。 

参照:Linux 内核 GPIO 用户空间接口 - sergioprado.blog

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 自动化之收发邮件(二)

发邮件之Windows进程监控 文章目录 发邮件之Windows进程监控前言一、基本内容二、基本结构三、库模块四、函数模块1.进程监控2.邮件发送 五、程序运行模块1.获取时间2.用户输入3.进程监控3.1进程启动发邮件3.2进程停止发邮件 总结 前言 上一篇简单写了一下如何进行邮件的收发操…

《使用ThinkPHP6开发项目》 - ThinkPHP6使用使用中间件验证登录Token

https://blog.csdn.net/centaury32/article/details/134997438 按照https://blog.csdn.net/centaury32/article/details/134999029的方法验证登录Token&#xff0c;那么每一步都需要写同样一段代码&#xff0c;这里可以结合中间件进行验证 一、创建中间件&#xff1a;php thi…

vue2 tailwindcss jit模式下热更新失效

按照网上教程安装的tailwindcss&#xff0c;但是修改类名后热更新的时候样式没有生效&#xff0c;参考了大佬的文章&#xff0c;解决了该问题。 安装cross-env 修改前 "dev": " vue-cli-service serve", 修改后 "dev": "cross-env TAILWIN…

python【matplotlib】鼠标拖动滚动缩放坐标范围和拖动图例共存

背景 根据前面的博文&#xff1a; python【matplotlib】画图鼠标缩放拖动动态改变坐标轴范围 和Python【Matplotlib】图例可拖动改变位置 两个博文&#xff0c;博主考虑了一下&#xff0c;如何将两者的功能结合起来&#xff0c;让二者共存。 只需根据Python【Matplotlib】鼠标…

基于BWA,Bowtie2,samtools、checkm等工具计算宏基因组学序列分析中Contigs与Genes在样品中的丰度,多种计算方式和脚本对比

计算contigs和genes相对丰度可以提供有关微生物群落结构和功能的信息。以下是计算这两个指标的意义&#xff1a; 1. Contigs的相对丰度&#xff1a;contigs是利用基因组测序技术获得的碎片序列&#xff0c;通过计算contigs的相对丰度可以了解微生物群落中不同菌种的相对丰度。…

centos下:mysql一些指令+mysql首次修改密码+mysql忘记密码修改

操作 查看mysql运行状态 systemctl status mysqld 停止mysql systemctl stop mysqld 启动mysql systemctl start mysqld 重启mysql systemctl restart mysqld 开启mysql开机自启动 systemctl enable mysqld 关闭mysql开机自启动 systemctl disable mysqld 查看具体的报错日…

t-io 程序执行后,jvm不退出的原因

基于t-io 1.7.3 版本分析源码 1、设定当前时间&#xff0c;每10毫秒执行一次 (非守护线程) 2、对应线程池的核心线程在AioServer启动时全部激活&#xff0c;并且添加空任务到阻塞队列&#xff0c;让核心线程(非守护线程)一直存活

如何使用ArcGIS Pro裁剪影像

对影像进行裁剪是一项比较常规的操作&#xff0c;因为到手的影像可能是多种范围&#xff0c;需要根据自己需求进行裁剪&#xff0c;这里为大家介绍一下ArcGIS Pro中裁剪的方法&#xff0c;希望能对你有所帮助。 数据来源 本教程所使用的数据是从水经微图中下载的影像和行政区…

nodejs微信小程序+python+PHP血液中心管理平台的设计与实现-计算机毕业设计推荐

在二十一世纪的今天&#xff0c;我国献血总量已经不容小觑&#xff0c;在全国人民的不懈努力下&#xff0c;贫血、缺血的病人已经有了足够的血液保障。与此同时&#xff0c;采血工作和血液入库、出库等工作也日愈繁重。为进一步提高采血工作和血液中心的工作效率&#xff0c;开…

锁--07_2---- index merge(索引合并)引起的死锁

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 案例分析生产背景死锁日志表结构执行计划 EXPLAN为什么会用 index_merge&#xff08;索引合并&#xff09;为什么用了 index_merge就死锁了解决方案注&#xff1a;M…

YOLOV8:最新探测物体状态综合指南

YLOLV8是最新的以YOO为基础的物体检测模型,提供最先进的性能。 利用前几部《yolo》,yolov8更快速更准确&#xff0c;同时为训练模式提供统一的框架 物体检测实例分割影像分类 到编写本文件时,许多功能还没有被添加到超催化剂YLOLV8存储库中。这包括训练有素的模型的一整套导…

【Trino权威指南(第二版)】Trino的架构、trino架构组件、 trino连接器架构的细节、trino的查询执行模型

文章目录 一. Trino架构1. 架构概览2. 协调器3. 发现服务4. 工作节点 二. 基于连接器的架构三. 查询执行模型1. 解析—>查询计划2. 查询计划 —> 分布式查询计划3. 运行阶段3.1. 基础概念切片&#xff1a;并行单元page 与 exchange算子pipeline切片的driverOperator 3.2.…