Linux GPIO驱动怎么写?gpio_desc、of_get_named_gpio、sysfs怎么用?嵌入式Linux面试

浏览量:7
时间: 2026-10-10 23:10:38
一句话答案

Linux GPIO 驱动用 gpiod 接口(新)或 legacy gpio 接口(旧);设备树里定义 gpios 属性,驱动用 devm_gpiod_get 获取 gpio_desc,gpiod_direction_input/output 设置方向,gpiod_get_value/set_value 读写;旧接口用 of_get_named_gpio+gpio_request+gpio_direction_*;用户态通过 sysfs(/sys/class/gpio/export)或 libgpiod(gpiodetect/gpioget)访问。

本文概述

GPIO 是 Linux 最基础驱动,面试常考:gpiod 接口、设备树、sysfs、libgpiod。回答要给新旧接口对比和代码。

核心要点

  • 新接口 gpiod(Linux 4.8+):devm_gpiod_get 获取描述符,gpiod_get_value/set_value 读写

  • 旧接口 legacy:of_get_named_gpio 获取编号,gpio_request 申请,gpio_set_value 读写

  • 设备树:gpios = <&gpioX Y GPIO_ACTIVE_HIGH>; 或 named-gpios

  • 用户态:sysfs(/sys/class/gpio,已弃用但仍常用)、libgpiod(gpiodetect/gpioget/gpioset,新)

  • 中断:gpio_to_irq 获取中断号,request_irq 注册;或 gpiod_to_irq

Linux 终端显示 GPIO 驱动代码,gpio_desc、of_get_named_gpio、sysfs,开发板 LED 和按键

面试官:Linux GPIO 驱动怎么写?gpiod 和 legacy 接口区别?用户态怎么控制 GPIO?

面试官考察点

Linux 驱动基础题。面试官看你是否写过 GPIO 驱动。重点听:gpiod 接口、设备树、用户态。

回答思路

讲 gpiod 新接口和 legacy 旧接口,设备树绑定,用户态访问,中断。

参考回答

gpiod 新接口(推荐,Linux 4.8+)。

// 设备树
my_device {
  compatible = "vendor,mydevice";
  led-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
  key-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
};

// 驱动 probe
struct gpio_desc *led = devm_gpiod_get(dev, "led", GPIOD_OUT_LOW);
struct gpio_desc *key = devm_gpiod_get(dev, "key", GPIOD_IN);
gpiod_set_value(led, 1); // 点亮 LED
int val = gpiod_get_value(key); // 读按键

  • devm_gpiod_get 自动管理资源(remove 时自动释放),不需要手动 gpiod_put;

  • 第二个参数是设备树里 gpios 属性的前缀("led" 对应 led-gpios);

  • 方向参数:GPIOD_IN、GPIOD_OUT_LOW、GPIOD_OUT_HIGH;

  • gpiod_set_value / gpiod_get_value 读写;

  • gpiod_direction_input / gpiod_direction_output 改方向。

legacy 旧接口(仍大量存在)。

int led_gpio = of_get_named_gpio(np, "led-gpios", 0);
gpio_request(led_gpio, "my_led");
gpio_direction_output(led_gpio, 0);
gpio_set_value(led_gpio, 1);
gpio_free(led_gpio); // remove 时释放

  • of_get_named_gpio 从设备树获取 GPIO 编号(整数);

  • gpio_request 申请,gpio_free 释放(必须配对,否则泄漏);

  • gpio_direction_input/output 设置方向;

  • gpio_get_value/set_value 读写;

  • 旧接口已被标记弃用,但很多老驱动还在用,新代码用 gpiod。

gpiod vs legacy。

项目gpiod(新)legacy(旧)
句柄gpio_desc 指针int 编号
资源管理devm 自动释放手动 gpio_free
极性处理自动(ACTIVE_LOW 自动翻转)手动处理
获取函数devm_gpiod_getof_get_named_gpio + gpio_request
状态推荐弃用但兼容

用户态访问 GPIO。

  • sysfs(旧,已弃用):
    echo 3 > /sys/class/gpio/export
    echo out > /sys/class/gpio/gpio3/direction
    echo 1 > /sys/class/gpio/gpio3/value
    简单但慢、无并发保护,新内核可能默认关闭;

  • libgpiod(新,推荐):
    gpiodetect(列出 GPIO 控制器)
    gpioinfo(查看引脚状态)
    gpioset gpiochip1 3=1(设置输出)
    gpioget gpiochip2 5(读取输入)
    C 库 libgpiod 可直接在程序里调用;

  • 设备驱动+字符设备:驱动创建 cdev,用户态 read/write/ioctl,适合复杂逻辑。

GPIO 中断。

// gpiod 接口
int irq = gpiod_to_irq(key);
request_irq(irq, my_irq_handler, IRQF_TRIGGER_FALLING, "my_key", dev);

// 设备树里可以定义中断
key-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
interrupt-parent = <&gpio2>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;

  • 按键、传感器中断常用 GPIO 中断;

  • 触发方式:上升沿、下降沿、双边沿、高电平、低电平;

  • 中断处理函数要快(顶半部分),耗时工作用 workqueue/threaded_irq。

注意。

  • GPIO 编号不是全局唯一,不同控制器独立编号,用 gpio_chip 区分;

  • 设备树里 GPIO_ACTIVE_LOW 表示低电平有效,gpiod 接口自动处理极性;

  • 有些引脚复用为其他功能(I2C/SPI),要先确认 pinmux 配置为 GPIO;

  • 输出 GPIO 要考虑驱动能力(一般 mA 级),驱动 LED 要加限流电阻;

  • 输入 GPIO 要加上下拉(防止悬空),设备树或寄存器配置。

面试官可能追问

追问 1:devm_gpiod_get 找不到 GPIO 怎么办?
检查设备树属性名是否匹配(“led-gpios” 对应 devm_gpiod_get 的 “led” 参数),检查 gpio 控制器节点是否正确,检查 pinctrl 是否把引脚配置为 GPIO 模式。返回 -EPROBE_DEFER 说明控制器还没初始化,内核会重试 probe。
追问 2:sysfs 和 libgpiod 怎么选?
新代码用 libgpiod(sysfs 已弃用,Linux 5.x 后可能移除)。libgpiod 有命令行工具和 C 库,支持事件监听(gpioedge)、批量操作,并发安全。sysfs 简单但慢、无锁、已弃用。老系统如果没有 libgpiod 只能用 sysfs。
追问 3:GPIO_ACTIVE_LOW 是什么意思?
表示该 GPIO 低电平为有效状态。gpiod 接口会自动处理:gpiod_set_value(desc, 1) 会输出低电平(因为有效是低),gpiod_get_value 返回 1 表示引脚为低(有效)。legacy 接口不自动处理,要手动翻转。这样代码逻辑不用关心实际电平。
追问 4:GPIO 中断和按键消抖?
GPIO 中断响应快但按键有抖动(ms级),会触发多次中断。消抖方法:①中断里启动定时器(jiffies+20ms),定时器里读 GPIO 确认;②用 gpio-keys 驱动(设备树定义,内核自带消抖);③硬件加 RC 滤波。不要在中断里延时消抖。
追问 5:pinctrl 和 GPIO 关系?
pinctrl 子系统配置引脚复用(mux)和电气特性(上下拉、驱动强度)。GPIO 是引脚的一种功能。使用 GPIO 前 pinctrl 要把该引脚配置为 GPIO 模式(而不是 I2C/SPI 等)。设备树里 pinctrl-0 引用 pinctrl 状态,probe 时自动切换。

常见失分表达

✗ 新代码用 legacy gpio 接口 — 已弃用,维护性差。
✗ gpio_request 后忘记 gpio_free — GPIO 资源泄漏,无法再次申请。
✗ 用户态用 sysfs 新项目 — 已弃用,新内核可能不支持。

准备动作

1
写过 GPIO 驱动(LED/按键)
2
了解 gpiod 和 legacy 接口
3
用过 sysfs 或 libgpiod

核心关键词

Linux GPIO驱动gpiodgpio_descof_get_named_gpiosysfslibgpiod设备树GPIO中断


声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。仅供学习交流使用,不构成商业目的。版权归原作者所有,如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时删除。侵权投诉
相关推荐HOT
继电器驱动电路怎么设计与保护?硬件工程师面试续流二极管与隔离

硬件设计中级技术基础题本文概述继电器驱动是硬件设计中的经典应用电路,面试中需要讲清继电器工作原理与关键参数(线圈电压/电流、触点容量、动作时间)、驱动方式选择(... 详情>>

2026-09-01 13:48:46
PCB表面处理工艺怎么选?沉金、喷锡、OSP与无铅焊接怎么取舍?PCB工程师面试

PCB设计中级技术基础题本文概述表面处理工艺决定焊盘的可靠性和产品寿命,是PCB工程师在投板阶段必须面对的选择,也是面试常考的基础题。面试官想听的不是“沉金最好... 详情>>

2026-09-09 13:30:31
硬件工程师面试如何回答技术选型问题?3种表达框架

分类:硬件工程师面试准备经验级别:中级难度:基础题型:表达技巧📖 本文概述面试中被问到"你当初为什么选这个芯片/器件"是硬件工程师的高频场景。本文提供3种表达... 详情>>

2026-08-04 15:55:43
单片机项目经验怎么讲才不显得太基础?工程师面试表达技巧

分类:单片机工程师面试准备经验级别:初-中级难度:基础题型:项目经验表达📖 本文概述很多单片机工程师做过的项目不少,但面试时讲出来总觉得很基础,好像就是点灯、... 详情>>

2026-08-06 17:05:51
为什么要采用Linux内核来构建嵌入式操作系统?

内核本身小而且简单,易于理解,易于维护。各种特殊的模块(如文件系统等)、设备驱动乃至中断处理程序,都可以作为独立的进程开发,既简单又容易调试,并 且容易在其他环... 详情>>

2024-03-27 11:29:34
开班信息