嵌入式Linux设备树驱动GPIO实现
1. 设备树节点配置
在设备树文件中添加设备节点描述:
gpio-device {
compatible = "custom-gpio-driver";
gpios = <&gpio0 12 0>, // 使用GPIO0组第12脚
<&gpio1 3 1>; // 使用GPIO1组第3脚,高电平有效
led-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
};
关键参数说明:
gpio0
:SOC内置GPIO控制器节点- 数字编号:引脚序号
- 标志位:指定有效电平状态
2. 驱动实现关键函数
#include <linux/gpio/consumer.h>
struct gpio_desc *gpio;
int value;
// 获取GPIO资源
gpio = gpiod_get(dev, "led", 0);
// 配置为输出模式
gpiod_direction_output(gpio, 0);
// 设置电平状态
gpiod_set_value(gpio, 1);
// 读取输入状态
value = gpiod_get_value(gpio);
// 释放资源
gpiod_put(gpio);
3. 完整驱动框架示例
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
struct custom_gpio_data {
struct gpio_desc *led_pin;
};
static int gpio_probe(struct platform_device *pdev)
{
struct custom_gpio_data *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
data->led_pin = gpiod_get(&pdev->dev, "led", GPIOD_OUT_LOW);
if (IS_ERR(data->led_pin)) {
dev_err(&pdev->dev, "无法获取GPIO\n");
return PTR_ERR(data->led_pin);
}
// 设置初始电平
gpiod_set_value(data->led_pin, 1);
platform_set_drvdata(pdev, data);
return 0;
}
static const struct of_device_id gpio_dt_ids[] = {
{ .compatible = "custom-gpio-driver" },
{}
};
MODULE_DEVICE_TABLE(of, gpio_dt_ids);
static struct platform_driver gpio_driver = {
.driver = {
.name = "custom-gpio",
.of_match_table = gpio_dt_ids,
},
.probe = gpio_probe,
};
module_platform_driver(gpio_driver);
4. 验证流程
- 编译设备树:
dtc -I dts -O dtb -o myboard.dtb myboard.dts
- 加载设备树:
fdtput /boot/myboard.dtb /gpio-device status "okay"
- 查看GPIO状态:
cat /sys/kernel/debug/gpio
- 用户空间测试:
echo 1 > /sys/class/gpio/gpio12/value
5. 注意事项
- 引脚复用配置需正确设置pinctrl
- 注意GPIO电气特性配置(上拉/下拉)
- 多个GPIO操作需考虑并发控制
- 使用gpiod_*系列API替代已废弃的gpio_*函数
数学关系表示:
当配置GPIO方向时,存在状态关系:
方向模式
=
{
0
输入模式
1
输出模式
\text{方向模式} = \begin{cases} 0 & \text{输入模式} \\ 1 & \text{输出模式} \end{cases}
方向模式={01输入模式输出模式
电平状态满足:
V
o
u
t
=
{
V
D
D
当
value
=
1
0
V
当
value
=
0
V_{out} = \begin{cases} V_{DD} & \text{当} \quad \text{value} = 1 \\ 0V & \text{当} \quad \text{value} = 0 \end{cases}
Vout={VDD0V当value=1当value=0