0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

中斷喚醒系統(tǒng)demo

麥辣雞腿堡 ? 來源:嵌入式Linux系統(tǒng)開發(fā) ? 作者:嵌入式Linux系統(tǒng)開 ? 2023-07-30 16:06 ? 次閱讀

博主寫的 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;; /* 設(shè)備節(jié)點(diǎn)*/
 
 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,并且設(shè)置成中斷模式 */
 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";
};

最后再總結(jié)一下:中斷喚醒系統(tǒng)和普通的驅(qū)動(dòng)區(qū)別在于,多了兩個(gè)函數(shù):suspend 和 resume,在suspend 函數(shù)中,調(diào)用 enable_irq_wake,表示該中斷號(hào)在系統(tǒng)休眠時(shí)也是 enable 狀態(tài),可以觸發(fā)中斷。在 resume 函數(shù)中,調(diào)用 disable_irq_wake ,恢復(fù)原始的中斷觸發(fā)路徑。

然后使用 SIMPLE_DEV_PM_OPS 宏將 suspend 和 resume 函數(shù)注冊到 gpio_keys_pm_ops 操作集,最終由 platform 注冊到系統(tǒng)中。這樣完成后,系統(tǒng)休眠過程中就會(huì)調(diào)用到設(shè)備注冊的 suspend,系統(tǒng)喚醒過程中就會(huì)調(diào)用設(shè)備注冊的 resume 函數(shù)。

note:該 demo 只用來喚醒系統(tǒng),如果你的中斷是在 I2C 等設(shè)備驅(qū)動(dòng)中,喚醒系統(tǒng)后要立刻在中斷處理函數(shù)中進(jìn)行 I2C 通信,寫法不太一樣,但是框架相同。

另外,該驅(qū)動(dòng)的中斷處理函數(shù)中沒做什么東西,因此喚醒后執(zhí)行完中斷處理函數(shù)后又會(huì)睡過去。如果你想要該中斷喚醒系統(tǒng)后讓系統(tǒng)一直處于喚醒狀態(tài),請?jiān)谥袛嗵幚砗瘮?shù)中使用 __pm_stay_awake() 和__pm_relax()函數(shù)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5054

    文章

    18917

    瀏覽量

    301003
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11182

    瀏覽量

    208524
  • 系統(tǒng)
    +關(guān)注

    關(guān)注

    1

    文章

    1006

    瀏覽量

    21277
收藏 人收藏

    評論

    相關(guān)推薦

    stm32u535Rb LPTIM無法中斷喚醒怎么解決?

    求助 stm32u535RbLPTIM1無法中斷喚醒(ll庫非hal) 請問下有沒有相關(guān)demo例程,這個(gè)問題已經(jīng)困擾我?guī)滋炝?,多謝
    發(fā)表于 03-08 08:18

    操作FreeRTOS時(shí),執(zhí)行__WFI()導(dǎo)致系統(tǒng)滴答中斷無法喚醒設(shè)備怎么解決?

    1、在操作FreeRTOS時(shí),本想著是在空閑鉤子中執(zhí)行__WFI()以降低設(shè)備功耗,等系統(tǒng)滴答中斷自動(dòng)喚醒設(shè)備繼續(xù)執(zhí)行,運(yùn)行中發(fā)現(xiàn)執(zhí)行__WFI()之后設(shè)備無法喚醒,分析應(yīng)該是__WF
    發(fā)表于 04-24 08:29

    如何使用can rx中斷喚醒系統(tǒng)的休眠模式?

    你好,我使用CY8C5868 LTI-LP039。我想實(shí)現(xiàn)睡眠模式(LPM)。是否有可能使用CAN RX中斷喚醒系統(tǒng)?
    發(fā)表于 10-10 08:52

    GD32進(jìn)入深度睡眠后通過外部中斷喚醒發(fā)現(xiàn)系統(tǒng)時(shí)鐘變慢的原因

    一、問題1、進(jìn)入深度睡眠后,通過外部中斷喚醒,發(fā)現(xiàn)系統(tǒng)時(shí)鐘變慢。2、進(jìn)入休眠模式,通過任何中斷喚醒,系統(tǒng)
    發(fā)表于 01-26 07:43

    使用TimeR在中斷服務(wù)之前喚醒系統(tǒng)執(zhí)行主程序

    應(yīng)用程序:使用TimeR來喚醒系統(tǒng),在中斷服務(wù)之前,首先執(zhí)行主程序。 BSP 版本: M051系列 BSP CMSIS v3.01.002 硬件: Nutiny-EVB-M051_V3.0 在正常
    發(fā)表于 08-23 06:57

    LPC900系列單片機(jī)完全掉電模式下的外部中斷喚醒

    LPC900系列單片機(jī)完全掉電模式下的外部中斷喚醒
    發(fā)表于 01-08 14:27 ?15次下載

    如何利用利用TimerA及中斷實(shí)現(xiàn)RTC

    D13x Demo - 利用Timer_A及中斷實(shí)現(xiàn)RTC,觀察LED燈的閃爍頻率 // 描述:利用Timer_A及中斷實(shí)現(xiàn)RTC;通過 P1 異或 來取反 P1.5; // 系統(tǒng)
    發(fā)表于 11-26 14:59 ?1598次閱讀
    如何利用利用TimerA及<b class='flag-5'>中斷</b>實(shí)現(xiàn)RTC

    GD32低功耗:深度睡眠喚醒系統(tǒng)時(shí)鐘變慢問題

    一、問題1、進(jìn)入深度睡眠后,通過外部中斷喚醒,發(fā)現(xiàn)系統(tǒng)時(shí)鐘變慢。2、進(jìn)入休眠模式,通過任何中斷喚醒系統(tǒng)
    發(fā)表于 12-02 15:06 ?21次下載
    GD32低功耗:深度睡眠<b class='flag-5'>喚醒</b><b class='flag-5'>系統(tǒng)</b>時(shí)鐘變慢問題

    STM32 HAL庫初始化MPU6050低功耗 中斷喚醒

    @[TOC]STM32初始化MPU6050低功耗 中斷喚醒STM32初始化MPU6050低功耗 中斷喚醒代碼如下: 已親自測試(2021.2.4) (以下代碼 采樣率是20Hz)低功耗
    發(fā)表于 12-06 13:36 ?20次下載
    STM32 HAL庫初始化MPU6050低功耗 <b class='flag-5'>中斷</b><b class='flag-5'>喚醒</b>

    HS26Fxx-C_Demo_Code-中斷函數(shù)、中斷子函數(shù)的定義與使用

    HS26Fxx-C_Demo_Code-中斷函數(shù)、中斷子函數(shù)的定義與使用功能:定時(shí)器TC0中斷程序參考void __interrupt[0x08] Interrupt(void)//無
    發(fā)表于 12-27 19:25 ?9次下載
    HS26Fxx-C_<b class='flag-5'>Demo</b>_Code-<b class='flag-5'>中斷</b>函數(shù)、<b class='flag-5'>中斷</b>子函數(shù)的定義與使用

    STM32外部中斷、串口喚醒低功耗

    外部中斷或RTC喚醒待機(jī)模式-(standby):待機(jī)模式的功耗為2uA,TAMPER引腳不關(guān)斷,通過WKUP引腳喚醒在項(xiàng)目中綜合選擇了停止模式,在該模式下使用兩種喚醒方式:WKUP引
    發(fā)表于 12-31 19:05 ?29次下載
    STM32外部<b class='flag-5'>中斷</b>、串口<b class='flag-5'>喚醒</b>低功耗

    STM32 低功耗睡眠模式(SLEEP)中斷(INTERRUPT)喚醒實(shí)現(xiàn)及優(yōu)化

    STM32 低功耗睡眠模式(SLEEP)中斷(INTERRUPT)喚醒實(shí)現(xiàn)及優(yōu)化1. 介紹STM32具有多種低功耗模式,當(dāng)前以STM32L4系列的低功耗模式最為豐富,此處基于STM32L476
    發(fā)表于 12-31 19:09 ?38次下載
    STM32 低功耗睡眠模式(SLEEP)<b class='flag-5'>中斷</b>(INTERRUPT)<b class='flag-5'>喚醒</b>實(shí)現(xiàn)及優(yōu)化

    按鍵如何喚醒系統(tǒng)官方demo

    、系統(tǒng)運(yùn)行時(shí)如果某外設(shè)很少用需要讓它運(yùn)行時(shí)休眠、系統(tǒng)休眠時(shí)要保證哪些外設(shè)可以喚醒系統(tǒng)。 博主今天要討論的,就是一個(gè)按鍵如何喚醒
    的頭像 發(fā)表于 07-30 15:43 ?734次閱讀
    按鍵如何<b class='flag-5'>喚醒</b><b class='flag-5'>系統(tǒng)</b>官方<b class='flag-5'>demo</b>

    什么是LInux 操作系統(tǒng)中斷

    LInux 操作系統(tǒng)中斷 什么是系統(tǒng)中斷 這個(gè)沒啥可說的,大家都知道; CPU 在執(zhí)行任務(wù)途中接收到中斷請求,需要保存現(xiàn)場后去處理
    的頭像 發(fā)表于 11-10 11:29 ?540次閱讀
    什么是LInux 操作<b class='flag-5'>系統(tǒng)</b><b class='flag-5'>中斷</b>

    LInux 操作系統(tǒng)中斷介紹

    LInux 操作系統(tǒng)中斷 什么是系統(tǒng)中斷 這個(gè)沒啥可說的,大家都知道; CPU 在執(zhí)行任務(wù)途中接收到中斷請求,需要保存現(xiàn)場后去處理
    的頭像 發(fā)表于 11-13 11:36 ?822次閱讀
    LInux 操作<b class='flag-5'>系統(tǒng)</b><b class='flag-5'>中斷</b>介紹