Linux GPIO 驱动开发实战:从入门到可部署
在嵌入式开发中,GPIO(通用输入输出口)作为与外设通信的关键接口,是驱动开发的基础能力之一。本文将带你从零开始编写一个 Linux 平台下的 GPIO 驱动模块,包括代码、Makefile 和测试方法,确保你可以实战部署。
一、环境准备
- 开发板:树莓派 / ARM Cortex-A 系列 / 开发板(含 GPIO 控制器)
- 内核版本:5.x 或以上(确保开启 GPIO 框架)
- 编译工具链:交叉编译工具(如 arm-linux-gnueabihf-gcc)
- 系统接口:使用 Linux 内核自带的 GPIO 子系统(gpiolib)
二、Linux GPIO 子系统简介
Linux 内核通过 gpiolib 框架提供统一接口,使得不同 SoC 的 GPIO 控制器能统一管理。
常见接口:
- gpio_request():申请 GPIO 引脚
- gpio_direction_input() / gpio_direction_output():设置引脚方向
- gpio_set_value() / gpio_get_value():读写 GPIO 值
- gpio_free():释放引脚
三、编写一个简单的 GPIO 控制驱动
1 驱动功能目标
- 控制 GPIO 输出电平
- 通过 /dev/gpio_demo 设备文件控制 GPIO 开关
- 使用 echo 1 > /dev/gpio_demo 开启,echo 0 > /dev/gpio_demo 关闭
2驱动代码:
gpio_demo.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <linux/cdev.h>
#define GPIO_DEMO_PIN 17 // 使用 GPIO17(树莓派)
#define DEVICE_NAME "gpio_demo"
static int major;
static struct class *gpio_class;
static struct cdev gpio_cdev;
static ssize_t gpio_write(struct file *file, const char __user *buf, size_t len, loff_t *off)
{
char val;
if (copy_from_user(&val, buf, 1))
return -EFAULT;
gpio_set_value(GPIO_DEMO_PIN, (val == '1') ? 1 : 0);
return len;
}
static int gpio_open(struct inode *inode, struct file *file)
{
return 0;
}
static int gpio_release(struct inode *inode, struct file *file)
{
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.write = gpio_write,
.open = gpio_open,
.release = gpio_release,
};
static int __init gpio_demo_init(void)
{
int ret;
dev_t dev;
// 分配主设备号
ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
if (ret)
return ret;
major = MAJOR(dev);
// 初始化字符设备
cdev_init(&gpio_cdev, &fops);
gpio_cdev.owner = THIS_MODULE;
cdev_add(&gpio_cdev, dev, 1);
// 创建设备节点
gpio_class = class_create(THIS_MODULE, "gpio_demo_class");
device_create(gpio_class, NULL, dev, NULL, DEVICE_NAME);
// 申请 GPIO 并设为输出
gpio_request(GPIO_DEMO_PIN, "gpio_demo");
gpio_direction_output(GPIO_DEMO_PIN, 0);
printk(KERN_INFO "GPIO demo module loaded\n");
return 0;
}
static void __exit gpio_demo_exit(void)
{
dev_t dev = MKDEV(major, 0);
gpio_set_value(GPIO_DEMO_PIN, 0);
gpio_free(GPIO_DEMO_PIN);
device_destroy(gpio_class, dev);
class_destroy(gpio_class);
cdev_del(&gpio_cdev);
unregister_chrdev_region(dev, 1);
printk(KERN_INFO "GPIO demo module unloaded\n");
}
module_init(gpio_demo_init);
module_exit(gpio_demo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("OpenAI");
MODULE_DESCRIPTION("Simple GPIO Control Driver");
Makefile 文件
obj-m += gpio_demo.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
四、驱动安装与测试
1 编译驱动
make
2 加载驱动模块
sudo insmod gpio_demo.ko
3 查看设备节点
ls /dev/gpio_demo
4 控制 GPIO
echo 1 | sudo tee /dev/gpio_demo # 设置高电平
echo 0 | sudo tee /dev/gpio_demo # 设置低电平
5 卸载驱动模块
sudo rmmod gpio_demo
五、验证逻辑
使用万用表或 LED 连接 GPIO17 引脚:
- echo 1:LED 亮
- echo 0:LED 灭
确保实物控制与代码一致。
六、实战建议
- 驱动中可集成中断响应(gpio_to_irq() + request_irq())
- 可结合 DTS(设备树)进行更灵活的管理
- 可对接平台驱动模型(platform_driver)
七、参考文档
- Linux Kernel Documentation: Documentation/gpio/
- LDD3(Linux Device Drivers 第三版)
- 官方驱动源码:drivers/gpio/
总结
本文展示了在 Linux 下开发一个简单 GPIO 控制驱动的完整过程,从源码、Makefile 到测试与部署,适合初学者或嵌入式项目开发者快速入门 GPIO 驱动实战。如果你想进一步掌握更复杂的中断、设备树、平台驱动集成,可在本项目基础上扩展!