全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 嵌入式技术 >

中断唤醒系统demo

时间:2023-07-30 16:06

人气:

作者:admin

标签: demo  系统 

导读:博主写的 demo 博主下面给的是简化版,并且自测OK,分享给大家,以后如果需要可以copy xxx.c # include # include # include # include # include # include # include # include # include # include # include # include...

博主写的 demo

博主下面给的是简化版,并且自测OK,分享给大家,以后如果需要可以copy xxx.c

#include < linux/module.h >
#include < linux/i2c.h >
#include < linux/interrupt.h >
#include < linux/delay.h >
#include < linux/uaccess.h >
#include < linux/pm.h >
#include < linux/slab.h >
#include < linux/sysctl.h >
#include < linux/proc_fs.h >
#include < linux/delay.h >
#include < linux/platform_device.h >
#include < linux/input.h >
#include < linux/gpio_keys.h >
#include < linux/workqueue.h >
#include < linux/gpio.h >
#include < linux/of.h >
#include < linux/of_platform.h >
#include < linux/of_gpio.h >
#include < linux/of_irq.h >
#include < linux/spinlock.h >
#include < linux/cdev.h >

static int gpionum = 0;
static int irqnum = 0;

static irqreturn_t my_handler(int irq, void *dev_id)
{
 printk("%srn",__FUNCTION__);
 return IRQ_HANDLED;
}

static int gpio_keys_probe(struct platform_device *pdev)
{
 int ret = 0;
 struct device_node *node = NULL;; /* 设备节点*/
 
 node = of_find_compatible_node(NULL,NULL,"atkalpha-key");
 if (node == NULL){
  printk("%s:atkalpha-key node not find!rn",__FUNCTION__);
  return -EINVAL;
 }
 
 /* 提取 GPIO */
 gpionum = of_get_named_gpio(node,"key-gpio", 0);
 if (gpionum < 0) {
   printk("of_get_named_gpio can't get keyrn");
 }
 
 /* 初始化 key 所使用的 IO,并且设置成中断模式 */
 gpio_request(gpionum, "key-gpio");
 gpio_direction_input(gpionum); 
 
 irqnum = gpio_to_irq(gpionum);
 
 ret = request_irq(irqnum,my_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "my-key", NULL);
 if(ret < 0){
  printk("irq %d request failed!rn", irqnum);
  return -EFAULT;
 }
 return 0;
}


static const struct of_device_id gpio_keys_of_match[] = {
 { .compatible = "atkalpha-key", },
 { },
};
MODULE_DEVICE_TABLE(of, gpio_keys_of_match);

static int gpio_keys_remove(struct platform_device *pdev)
{
 return 0;
}

static int gpio_keys_suspend(struct device *dev)
{
 printk("%srn",__FUNCTION__);
 enable_irq_wake(irqnum);
 return 0;
}

static int gpio_keys_resume(struct device *dev)
{
 printk("%srn",__FUNCTION__);
 disable_irq_wake(irqnum);
 return 0;
}

static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);

static struct platform_driver gpio_keys_device_driver = {
 .probe  = gpio_keys_probe,
 .remove  = gpio_keys_remove,
 .driver  = {
  .name = "my-key",
  .pm = &gpio_keys_pm_ops,
  .of_match_table = of_match_ptr(gpio_keys_of_match),
 }
};

static int __init gpio_keys_init(void)
{
 return platform_driver_register(&gpio_keys_device_driver);
}

static void __exit gpio_keys_exit(void)
{
 platform_driver_unregister(&gpio_keys_device_driver);
}

module_init(gpio_keys_init);
module_exit(gpio_keys_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jason");
MODULE_DESCRIPTION("Keyboard driver for GPIOs");
MODULE_ALIAS("platform:gpio-keys");

xxx.dts

key {
  #address-cells = < 1 >;
  #size-cells = < 1 >;
  compatible = "atkalpha-key";
  key-gpio = < &gpio1 18 GPIO_ACTIVE_LOW >; /* KEY0 */
  interrupt-parent = < &gpio1 >;
  interrupts = < 18 IRQ_TYPE_EDGE_BOTH >; /* FALLING RISING */
  gpio-key,wakeup;
  status = "okay";
};

最后再总结一下:中断唤醒系统和普通的驱动区别在于,多了两个函数:suspend 和 resume,在suspend 函数中,调用 enable_irq_wake,表示该中断号在系统休眠时也是 enable 状态,可以触发中断。在 resume 函数中,调用 disable_irq_wake ,恢复原始的中断触发路径。

然后使用 SIMPLE_DEV_PM_OPS 宏将 suspend 和 resume 函数注册到 gpio_keys_pm_ops 操作集,最终由 platform 注册到系统中。这样完成后,系统休眠过程中就会调用到设备注册的 suspend,系统唤醒过程中就会调用设备注册的 resume 函数。

note:该 demo 只用来唤醒系统,如果你的中断是在 I2C 等设备驱动中,唤醒系统后要立刻在中断处理函数中进行 I2C 通信,写法不太一样,但是框架相同。

另外,该驱动的中断处理函数中没做什么东西,因此唤醒后执行完中断处理函数后又会睡过去。如果你想要该中断唤醒系统后让系统一直处于唤醒状态,请在中断处理函数中使用 __pm_stay_awake() 和__pm_relax()函数。

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信