GPIO按键无法唤醒Standby模式下的嵌入式Linux系统求助
GPIO唤醒Standby/SDR模式失败排查问题
基于启用电源管理的Linux内核v5.10.24开发,期望通过GPIO在系统进入Standby/SDR模式时唤醒系统,但测试发现该GPIO无法完成唤醒操作。
DTS配置
gpio_keys: gpio_keys { compatible = "gpio-keys"; gpioa { label = "gpioa"; linux,code = <KEY_WAKEUP>; gpios = <&gpa 3 GPIO_ACTIVE_HIGH CHRP_GPIO_NOBIAS>; gpio-key,wakeup; wakeup-source; }; };
自定义驱动代码
#include <linux/init.h> ..... #include <linux/interrupt.h> static int gpio_wake = 0; static int irq = 0; struct gpio_keys_platform_data { const char *label; }; static irqreturn_t gpio_keys_irq(int irq, void *dev_id) { return IRQ_HANDLED; } static int gpio_keys_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct gpio_keys_platform_data pdata; enum of_gpio_flags flags; int ret; struct device_node *child = of_get_child_by_name(node, "gpioa"); if (!child) { dev_err(&pdev->dev, "Failed to find gpioa node\n"); return -ENOENT; } ret = of_property_read_string(child, "label", &pdata.label); if (ret) { dev_err(&pdev->dev, "Failed to read gpioa label property\n"); return ret; } gpio_wake = of_get_named_gpio_flags(child, "gpios", 0, &flags); if (!gpio_is_valid(gpio_wake)) gpio_wake = -1; if (gpio_request(gpio_wake, "gpio-wake") < 0) return -ENODEV; if (gpio_direction_input(gpio_wake) < 0) return -ENODEV; irq = gpio_to_irq(gpio_wake); ret = request_irq(irq, gpio_keys_irq, IRQF_TRIGGER_HIGH, "GPIOWAKE", NULL); if (ret < 0) return -ENODEV; device_init_wakeup(&pdev->dev, 1); return 0; } static int gpio_keys_remove(struct platform_device *pdev) { ... device_init_wakeup(&pdev->dev, 0); dev_info(&pdev->dev, "GPIO keys driver removed\n"); ... return 0; } static int gpio_suspend(struct platform_device *pdev, pm_message_t state) { if (gpio_wake >= 0) enable_irq_wake(irq); return 0; } static int gpio_resume(struct platform_device *pdev) { if (gpio_wake >= 0) disable_irq_wake(irq); return 0; } static const struct of_device_id gpio_keys_of_match[] = { { .compatible = "gpio-keys" }, {}, }; MODULE_DEVICE_TABLE(of, gpio_keys_of_match); static struct platform_driver gpio_keys_driver = { .suspend = gpio_suspend, .resume = gpio_resume, .probe = gpio_keys_probe, .remove = gpio_keys_remove, .driver = { .name = "gpio-keys", .of_match_table = gpio_keys_of_match, .owner = THIS_MODULE, }, }; module_platform_driver(gpio_keys_driver); MODULE_AUTHOR("MinoltaFan"); MODULE_DESCRIPTION("TestGPIO Driver"); MODULE_LICENSE("GPL");
测试现象
- 内核模块可正常加载,
/proc/interrupts中显示GPIOWAKE条目; - 拉高GPIO后,该条目计数增加,说明中断触发正常;
- 执行
echo standby > /sys/power/state使系统进入Standby模式,内核日志显示系统进入pm状态且CPU冻结,但拉高GPIO触发中断无法唤醒系统,多次尝试均失败。
更新尝试
将中断触发方式修改为:
ret = request_irq(irq, gpio_keys_irq, IRQF_TRIGGER_RISING, "GPIOWAKE", NULL);
但结果仍相同,系统无法被该GPIO唤醒。
核心疑问
- 配置GPIO唤醒电源管理模式下Linux系统的必要步骤有哪些?
- 当前驱动代码中是否存在遗漏或错误?
- 未使用Linux输入系统,仅通过最简配置实现GPIO唤醒功能是否可行?
内容的提问来源于stack exchange,提问作者wangt13
相关产品推荐
相关产品推荐

