当前位置:首页>Linux>来稿选登:Linux gpiod方式操作gpio

来稿选登:Linux gpiod方式操作gpio

  • 2026-09-04 18:21:20
来稿选登:Linux gpiod方式操作gpio

Linux gpiod(GPIO Character Device Interface)的支持是在Linux内核4.8版本中正式引入的,当前M300的SDK已经适配了Linux5.10以及Linux6.6版本,所以之后的两个版本都是支持gpiod。

这一更新标志着GPIO的用户空间操作接口从旧的sysfs方式,向更便捷,更安全的字符设备方式转变;实测gpiod方式操作gpio的效率介于devmem用户态映射和sysfs之间,如果指望使用gpiod实现某些高速功能,可能是不太现实的,但是gpiod所提供的工具命令,在我们调试gpio过程中,能够直观展示gpio的使用状况和很便捷的操作方式,避免了sysfs的繁杂操作。

为了适应排版,本文对原始文章进行了版面重排。

内核是否支持gpiod

查看设备目录/dev/下是否有gpiochip字符设备:

系统是否支持gpiod

系统下使用gpiod需要有相关库和执行命令的支持,可以在系统下执行gpio并使用tab补全,查看是否支持,如下:

并执行gpioinfo命令,查看libgpiod是否支持。

如果通过以上测试,并不能正常使用gpiod。就需要进行对应的内核以及文件系统的配置。

内核配置
在SDK根目录下运行make kernel-menuconfig,在Device Drivers > GPIO Support中:
确保charactor device选中。
buildroot配置

在SDK根目录下运行make buildroot-menuconfig,在Target packages → Libraries → Hardware handling中:

勾选libgpiod和install tools,选择完成后,编译烧录开发板。

gpiod的使用方式

gpiod的使用方式,主要包含两种。一种是使用gpiod相关tools,在系统下进行调试验证等工作;还有就是基于libgpiod编程,使用libgpiod提供的相关C接口,可用于在用户程序中进行低速的gpio操作,也可以基于它开发I2C、SPI、MDIO等低速接口。

如果使用python开发,也可以安装python3-libgpiod,同样可以实现基于python的命令和程序开发。

gpiod tools的使用

gpiod tools一共支持以下几种:

gpiodetect  gpiofind    gpioget     gpioinfo    gpiomon     gpioset

由于接触的使用场景有限,仅做个人经验分享。

gpiodetect简介

此工具的功能是列出所有的gpio芯片,无论是SOC内部的gpio还是通过其它方式拓展的gpio;例如在M300上执行此命令,可以看到一共支持5组gpio。

而在ubuntu桌面主机上,安装gpiod的支持并插入cp2112这类USB转gpio、i2c等芯片,执行可以看到:

root@cduguobin-VMware-Virtual-Platform:/# gpiodetectgpiochip0 [cp2112_gpio] (8 lines)

它对外挂的gpio芯片也能完美支持。

gpioinfo简介

查看指定芯片的所有引脚,可以直接执行,也可以带参数执行。

直接执行会将所有的gpio芯片信息dump出来,参数为gpiodetect中探测到的gpio芯片索引如下:

将该芯片下所有的gpio信息全部展示出来,包含输入输出状态,有无驱动注册,也能在此体现出来。

gpioset简介

用于设置gpio的值,根据帮助说明,此工具有很多功能的支持,但是更多受限于gpio芯片的设计以及驱动的支持。我们常用的功能还是一些基础的拉高拉低等操作。

例如需要设置一个gpio输出高:

也可以设置同一组gpio芯片的多个gpio:

还有一些高级操作,具体使用还需看帮助手册:

gpioset --mode=time --sec=1 1 0=1 #设置为高电平,并持续1gpioset 1 0=1                     #立即设置为低

gpioget简介

见名知意,即为获取gpio线的状态:

gpiomon简介

这个功能没用过,介绍说的是可以监控gpio的事件,如边沿事件等,在测试场景用的较少。需要用的时候在研究。

C语言编程接口

gpiolib提供的相关接口都在gpiod.h头文件中定义,使用时需要#include <gpiod.h>包含这个头文件。并在编译时-lgpiod库文件。以下是AI写的一个简单例程,gpiod.h中包含的功能很多,这里只能抛砖引玉,使用的时候再仔细研究。

#include<gpiod.h>#include<stdio.h>#include<unistd.h>intmain(void){    const char *chipname = "gpiochip0";    struct gpiod_chip *chip;    struct gpiod_line *line;    int ret, val;    // 打开GPIO芯片    chip = gpiod_chip_open_by_name(chipname);    if (!chip) {        perror("Open chip failed");        return 1;    }    // 获取GPIO线(引脚17)    line = gpiod_chip_get_line(chip, 17);    if (!line) {        perror("Get line failed");        gpiod_chip_close(chip);        return 1;    }    // 配置为输入模式    ret = gpiod_line_request_input(line, "example");    if (ret < 0) {        perror("Request line as input failed");        gpiod_line_release(line);        gpiod_chip_close(chip);        return 1;    }    // 读取引脚值    val = gpiod_line_get_value(line);    printf("GPIO 17 value: %d\n", val);    // 配置为输出模式    ret = gpiod_line_request_output(line, "example"0);    if (ret < 0) {        perror("Request line as output failed");        gpiod_line_release(line);        gpiod_chip_close(chip);        return 1;    }    // 设置引脚值    gpiod_line_set_value(line, 1);    sleep(1);    gpiod_line_set_value(line, 0);    // 监控事件    struct gpiod_line_request_config config = {        .consumer = "example",        .request_type = GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES,    };    ret = gpiod_line_request(line, &config, 0);    if (ret < 0) {        perror("Request event failed");    } else {        struct gpiod_line_event event;        ret = gpiod_line_event_wait(line, NULL);        if (ret > 0) {            ret = gpiod_line_event_read(line, &event);            printf("Event type: %d\n", event.event_type);        }    }    // 清理资源    gpiod_line_release(line);    gpiod_chip_close(chip);    return 0;}

总结

和传统的sysfs接口相比,gpiod的方式明显更直观和更高效。解决了sysfs接口的目录层级太多,且都需要以字符串的方式进行操作。而且提供了libgpiod的库,让用户实现一些基础的gpio功能,也不用再去研究数据手册中的gpio寄存器,可以更安全的操作gpio。

尾声

作者原始链接:https://ima.qq.com/note/share/_AwZNLSM8gqfLZoXbl5lNA?channel=4

最新文章

随机文章