Page tree
Skip to end of metadata
Go to start of metadata

GPIO操作在Linux系统上是常用功能,STM32MP1芯片平台也同样支持。不同于其他平台,STM32MP1平台使用了新的操作方式——GPIO字符设备。这个特性是在linux v4.8版本的时候被合并到内核主线,不再使用以前SYSFS方式的操作方式来操作GPIO,而是,基于"文件描述符"的字符设备,每个GPIO组在"/dev"下有一个对应的gpiochip文件,例如"/dev/gpiochip0, /dev/gpiochip1"。使用常规的LInux文件操作方式即可操作这些gpiochip文件,基本可以概括为open() + ioctl() + poll() + read() + close()。


STM32MP1平台的gpiochip文件描述

字符设备描述
/dev/gpiochip0GPIOA
/dev/gpiochip1GPIOB
/dev/gpiochip2GPIOC
/dev/gpiochip3GPIOD
/dev/gpiochip4GPIOE
/dev/gpiochip5GPIOF
/dev/gpiochip6GPIOG
/dev/gpiochip7GPIOH
/dev/gpiochip8GPIOI
/dev/gpiochip9GPIOJ
/dev/gpiochip10GPIOK
/dev/gpiochip11GPIOZ


Libgpiod

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


以下是使用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;
}
  • No labels