You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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唤醒。

核心疑问

  1. 配置GPIO唤醒电源管理模式下Linux系统的必要步骤有哪些?
  2. 当前驱动代码中是否存在遗漏或错误?
  3. 未使用Linux输入系统,仅通过最简配置实现GPIO唤醒功能是否可行?

内容的提问来源于stack exchange,提问作者wangt13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:47:02