GPIO应用
GPIO操作在Linux系统上是常用功能,STM32MP1芯片平台也同样支持。从Linux 4.8版本开始,Linux引入了新的gpio操作方式,GPIO字符设备。不再使用以前SYSFS方式在"/sys/class/gpio"目录下来操作GPIO,而是,基于"文件描述符"的字符设备,每个GPIO组在"/dev"下有一个对应的gpiochip文件,例如"/dev/gpiochip0, /dev/gpiochip1"。使用常规的LInux文件操作方式即可操作这些gpiochip文件,基本可以概括为open() + ioctl() + poll() + read() + close()。
STM32MP1平台的gpiochip文件描述
| 字符设备 | 描述 | 
| /dev/gpiochip0 | GPIOA | 
| /dev/gpiochip1 | GPIOB | 
| /dev/gpiochip2 | GPIOC | 
| /dev/gpiochip3 | GPIOD | 
| /dev/gpiochip4 | GPIOE | 
| /dev/gpiochip5 | GPIOF | 
| /dev/gpiochip6 | GPIOG | 
| /dev/gpiochip7 | GPIOH | 
| /dev/gpiochip8 | GPIOI | 
| /dev/gpiochip9 | GPIOJ | 
| /dev/gpiochip10 | GPIOK | 
| /dev/gpiochip11 | GPIOZ | 
gpiochip 操作
gpio申请
flags: desired flags for the desired GPIO lines, such as GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW etc, OR:ed * together. Note that even if multiple lines are requested, the same flags * must be applicable to all of them, if you want lines with individual * flags set, request them one by one. It is possible to select * a batch of input or output lines, but they must all have the same * characteristics, i.e. all inputs or all outputs, all active low etc
lines: number of lines requested in this request, i.e. the number of valid fields in the above arrays, set to 1 to request a single line
struct gpiohandle_request {
	__u32 lineoffsets[GPIOHANDLES_MAX];
	__u32 flags;
	__u8 default_values[GPIOHANDLES_MAX];
	char consumer_label[32];
	__u32 lines;
	int fd;
};
#define GPIOHANDLES_MAX 64
#define GPIOHANDLE_REQUEST_INPUT (1UL << 0)
#define GPIOHANDLE_REQUEST_OUTPUT (1UL << 1)
#define GPIOHANDLE_REQUEST_ACTIVE_LOW (1UL << 2)
#define GPIOHANDLE_REQUEST_OPEN_DRAIN (1UL << 3)
#define GPIOHANDLE_REQUEST_OPEN_SOURCE (1UL << 4)gpio 操作数据
struct gpiohandle_data {
	__u8 values[GPIOHANDLES_MAX];
};gpio event的申请
handleflags: desired handle flags for the desired GPIO line, such as GPIOHANDLE_REQUEST_ACTIVE_LOW or GPIOHANDLE_REQUEST_OPEN_DRAIN
eventflags: desired flags for the desired GPIO event line, such as GPIOEVENT_REQUEST_RISING_EDGE or GPIOEVENT_REQUEST_FALLING_EDGE
struct gpioevent_request {
	__u32 lineoffset;
	__u32 handleflags;
	__u32 eventflags;
	char consumer_label[32];
	int fd;
};
#define GPIOEVENT_REQUEST_RISING_EDGE (1UL << 0)
#define GPIOEVENT_REQUEST_FALLING_EDGE (1UL << 1)
#define GPIOEVENT_REQUEST_BOTH_EDGES ((1UL << 0) | (1UL << 1))gpio event
struct gpioevent_data {
        __u64 timestamp;
        __u32 id;
};
#define GPIOEVENT_EVENT_RISING_EDGE 0x01
#define GPIOEVENT_EVENT_FALLING_EDGE 0x02
以下是使用C语言操作PZ0管脚的示例代码。
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/gpio.h>
int main(int argc, char **argv)
{
struct gpiohandle_request req;
struct gpiohandle_data data;
char chrdev_name[20];
int fd, ret;
strcpy(chrdev_name, "/dev/gpiochip11");
/* Open device: gpiochip11 for GPIO bank Z */
fd = open(chrdev_name, 0);
if (fd == -1) {
ret = -errno;
fprintf(stderr, "Failed to open %s\n", chrdev_name);
return ret;
}
/* request GPIO line: GPIO_Z_0 */
req.lineoffsets[0] = 0;
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
memcpy(req.default_values, &data, sizeof(req.default_values));
strcpy(req.consumer_label, "led_gpio_z_0");
req.lines = 1;
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
ret);
}
if (close(fd) == -1)
perror("Failed to close GPIO character device file");
/* Start led blinking */
while(1) {
data.values[0] = !data.values[0];
ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d)\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret);
}
sleep(1);
}
/* release line */
ret = close(req.fd);
if (ret == -1) {
perror("Failed to close GPIO LINEHANDLE device file");
ret = -errno;
}
return ret;
}将以上代码保存为gpio.c文件,然后加载SDK环境变量后,就可以编译了。
$CC gpio.c -o gpio编译后的gpio文件,可以拷贝到开发板上运行。
Libgpiod
由于gpiochip的方式,基于C语言,所以开发者实现了Libgpiod,提供了一些工具和更简易的C API接口。
Libgpiod (Library General Purpose Input/Output device)  提供了完整的API 给开发者,同时还提供了一些用户空间下的应用来操作GPIO。
- gpiodetect – list all gpiochips present on the system, their names, labels and number of GPIO lines 
- gpioinfo – list all lines of specified gpiochips, their names, consumers, direction, active state and additional flags 
- gpioget – read values of specified GPIO lines 
- gpioset – set values of specified GPIO lines, potentially keep the lines exported and wait until timeout, user input or signal 
- gpiofind – find the gpiochip name and line offset given the line name 
- gpiomon – wait for events on GPIO lines, specify which events to watch, how many events to process before exiting or if the events should be reported to the console 
仓库地址 git.kernel.org/pub/s... 
 API git.kernel.org/pub/s... 
libgpiod introduction video: www.youtube.com/watc...
最后编辑:SteveChen 更新时间:2024-10-18 15:16
