在 Linux 内核中,有专门用于控制 GPIO(General - Purpose Input/Output,通用输入输出)输出的函数。

4.8 之前的内核

在较旧的 Linux 内核版本中,使用的是传统的 GPIO 接口。相关函数主要定义在 <linux/gpio.h> 头文件中。

1、请求GPIO

在使用 GPIO 之前,需要先请求该 GPIO 资源,以确保不会与其他驱动冲突。

1
2
3
#include <linux/gpio.h>

int gpio_request(unsigned gpio, const char *label);

2、设置GPIO方向输出

1
int gpio_direction_output(unsigned gpio, int value);
  • gpio:要设置的 GPIO 编号。
  • value:初始输出电平,0 表示低电平,1 表示高电平。
    返回值:成功时返回 0,失败时返回负数错误码。

3、设置 GPIO 输出电平

1
void gpio_set_value(unsigned gpio, int value);
  • gpio:要设置的 GPIO 编号。
  • value:要设置的输出电平,0 表示低电平,1 表示高电平。

4、读取 GPIO 输入电平

1
int gpio_get_value(unsigned gpio);
  • gpio:要读取的 GPIO 编号。
  • 返回值:成功时返回 0 或 1,表示输入电平的高或低电平。失败时返回负数错误码。

5、释放 GPIO

1
void gpio_free(unsigned gpio);
  • gpio:要释放的 GPIO 编号。

例程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>

#define MY_GPIO_PIN 17

static int __init my_gpio_init(void)
{
int ret;

ret = gpio_request(MY_GPIO_PIN, "my_gpio");
if (ret) {
printk(KERN_ERR "Failed to request GPIO %d\n", MY_GPIO_PIN);
return ret;
}

ret = gpio_direction_output(MY_GPIO_PIN, 1);
if (ret) {
printk(KERN_ERR "Failed to set GPIO %d as output\n", MY_GPIO_PIN);
gpio_free(MY_GPIO_PIN);
return ret;
}

gpio_set_value(MY_GPIO_PIN, 0);
printk(KERN_INFO "GPIO %d set to low level\n", MY_GPIO_PIN);

return 0;
}

static void __exit my_gpio_exit(void)
{
gpio_free(MY_GPIO_PIN);
printk(KERN_INFO "GPIO %d freed\n", MY_GPIO_PIN);
}

module_init(my_gpio_init);
module_exit(my_gpio_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ygc");

4.8之后的内核改动

从 Linux 内核 4.8 版本开始,引入了更现代的 GPIO 子系统,使用 gpiod_* 系列函数,相关函数定义在 <linux/gpio/consumer.h> 头文件中

1、获取 GPIO 描述符

1
2
3
#include <linux/gpio/consumer.h>

struct gpio_desc *gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags);
  • dev:关联的设备结构体指针。
  • con_id:GPIO 控制器的连接标识符。
  • flags:标志位,例如 GPIOD_OUT_LOW 或 GPIOD_OUT_HIGH 用于设置初始输出电平。
    返回值:成功时返回 GPIO 描述符指针,失败时返回 ERR_PTR。

2、设置 GPIO 输出电平

1
void gpiod_set_value(struct gpio_desc *desc, int value);
  • desc:GPIO 描述符指针。
  • value:要设置的输出电平,0 表示低电平,1 表示高电平。

3、释放 GPIO 描述符

1
void gpiod_put(struct gpio_desc *desc);

释放 GPIO 描述符,释放 GPIO 描述符后,GPIO 描述符将不再可用。

例程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio/consumer.h>

static struct gpio_desc *my_gpio_desc;

static int __init my_gpio_init_new(void)
{
my_gpio_desc = gpiod_get(NULL, "my_gpio", GPIOD_OUT_LOW);
if (IS_ERR(my_gpio_desc)) {
printk(KERN_ERR "Failed to get GPIO descriptor\n");
return PTR_ERR(my_gpio_desc);
}

gpiod_set_value(my_gpio_desc, 1);
printk(KERN_INFO "GPIO set to high level\n");

return 0;
}

static void __exit my_gpio_exit_new(void)
{
gpiod_put(my_gpio_desc);
printk(KERN_INFO "GPIO descriptor freed\n");
}

module_init(my_gpio_init_new);
module_exit(my_gpio_exit_new);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("YGC");