国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Linux|Centos|Ubuntu|系統(tǒng)進(jìn)程|Fedora|注冊表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務(wù)器之家 - 服務(wù)器系統(tǒng) - Linux - 手把手教你中斷喚醒系統(tǒng)

手把手教你中斷喚醒系統(tǒng)

2021-12-28 23:45嵌入式Linux系統(tǒng)開發(fā)Jasonangel Linux

中斷喚醒系統(tǒng)和普通的驅(qū)動區(qū)別在于,多了兩個函數(shù):suspend 和 resume,在 suspend 函數(shù)中,調(diào)用 enable_irq_wake,表示該中斷號在系統(tǒng)休眠時也是 enable 狀態(tài),可以觸發(fā)中斷。

手把手教你中斷喚醒系統(tǒng)

在消費類電子中,功耗是很重要的,甚至項目后期一直在調(diào)功耗,看看哪里還可以再省電。由此就有了 Linux 電源管理子系統(tǒng),該子系統(tǒng)包含很多方面:什么時候可以降幀、什么時候可以關(guān)掉其他 CPU core、系統(tǒng)運行時如果某外設(shè)很少用需要讓它運行時休眠、系統(tǒng)休眠時要保證哪些外設(shè)可以喚醒系統(tǒng)。

博主今天要討論的,就是一個按鍵如何喚醒系統(tǒng),類似于手機(jī)的電源鍵。

這個功能并不是新功能,所以 Linux 內(nèi)部有一個 demo 可以使用,先教大家如何使用該 demo,然后較大家如何撰寫中斷喚醒系統(tǒng)驅(qū)動。

官方 demo

demo 目錄:/kernel4.14/drivers/input/keyboard/gpio_keys.c

該驅(qū)動是專門為按鍵準(zhǔn)備的,是一個身經(jīng)百戰(zhàn)的驅(qū)動,任何時候測試按鍵中斷或者中斷喚醒系統(tǒng)都可以用它,很多時候比自己寫的驅(qū)動靠譜。

要想使用該驅(qū)動,首先在該目錄的 Makefile 中增加:

  1. obj-y += gpio_keys.o

設(shè)備樹中增加:

  1. gpio-keys {
  2. compatible = "gpio-keys";
  3. #address-cells = <1>;
  4. #size-cells = <0>;
  5. autorepeat;
  6. key0 {
  7. label = "GPIO Key Enter";
  8. linux,code = ;
  9. gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
  10. gpio-key,wakeup;
  11. };
  12. };

compatible 屬性是 “gpio-keys”,gpio_keys.c 文件的674行會匹配這個屬性,匹配到了該驅(qū)動就會運行。

linux,code 屬性是按鍵值,Linux 對所有按鍵事件都有編號,所以KEY_ENTER 實際是一個數(shù)字,是驅(qū)動向上層報告的一個按鍵值。

gpios 屬性是標(biāo)明哪一個 GPIO 口,低電平觸發(fā),大家可以自己選一個 GPIO。

gpio-key,wakeup 是代表此GPIO支持中斷喚醒,你也可以寫成:wakeup-source。新老版本而已。

修改就是這么簡單,不過語法要符合各位手中的開發(fā)板平臺。然后編譯出內(nèi)核和設(shè)備樹文件,下載到板子中。(Linux 內(nèi)核根目錄會有 .config 文件,確保 CONFIG_PM_SLEEP=y 有打開)

如果驅(qū)動加載成功,在 /proc/interrupts 中可以看到:

手把手教你中斷喚醒系統(tǒng)

從左往右第一列是軟件中斷號(唯一)。

第二列是 CPU,表示該中斷在該CPU上觸發(fā)了多少次,多核會有多列。

第三列是中斷控制器,imx6ull開發(fā)板根中斷控制器是GPC,外部中斷控制器是gpio-mxc,兩者是級聯(lián)關(guān)系。

第四列是硬件中斷號,也就是GPIO口編號。

第五列表示該中斷是邊沿觸發(fā)還是電平觸發(fā)。

第六列是中斷名稱,可以找到一個 GPIO Key Enter,如果驅(qū)動加載成功就能看到,如果失敗就看不到。

驗證方法

在內(nèi)核中,休眠方式有很多種,可以通過下面命令查看

  1. # cat /sys/power/state

常用的休眠方式有freeze、standby、mem、disk

freeze:凍結(jié)I/O設(shè)備,將它們置于低功耗狀態(tài),使處理器進(jìn)入空閑狀態(tài),喚醒最快,耗電比其它standby, mem, disk方式高

standby:除了凍結(jié)I/O設(shè)備外,還會暫停系統(tǒng),喚醒較快,耗電比其它 mem, disk方式高

mem:將運行狀態(tài)數(shù)據(jù)存到內(nèi)存,并關(guān)閉外設(shè),進(jìn)入等待模式,喚醒較慢,耗電比disk方式高

disk:將運行狀態(tài)數(shù)據(jù)存到硬盤,然后關(guān)機(jī),喚醒最慢

示例:

  1. # echo mem > /sys/power/state

系統(tǒng)進(jìn)入睡眠后,基本都會停掉UI、停掉串口,串口無法操作,如圖:

手把手教你中斷喚醒系統(tǒng)

按下按鍵,系統(tǒng)恢復(fù):

手把手教你中斷喚醒系統(tǒng)

當(dāng)然這里的 log 并不完整,輸入 dmesg 可以看到完整 log:

手把手教你中斷喚醒系統(tǒng)

PM:power manager

具體干了什么,圖中有解釋,分為 suspend 過程和 resume 過程。

其實一個中斷讓它支持喚醒系統(tǒng),最主要是多了兩個函數(shù):suspend、resume。

suspend 函數(shù)在系統(tǒng)整體 suspend 的時候,會調(diào)用每個外設(shè)注冊的 suspend,我們在這個函數(shù)中調(diào)用 enable_irq_wake,表示該中斷在系統(tǒng)休眠時是 enable 狀態(tài)。

resume 函數(shù)在系統(tǒng)整體 resume 的時候,會調(diào)用每個外設(shè)注冊的 resume 函數(shù),在 resume 函數(shù)中調(diào)用 disable_irq_wake ,表示該中斷在系統(tǒng)運行時不需要。兩者成對使用。

具體參看下面文章,寫的很好:

http://www.wowotech.net/irq_subsystem/irq_handle_procedure.html

大家也可以研究一下 gpio_keys.c,該驅(qū)動看起來比較復(fù)雜,但是很完善,畢竟身經(jīng)百戰(zhàn),什么因素都考慮到了,測試就用它!

博主寫的 demo

博主下面給的是簡化版,并且自測OK,分享給大家,以后如果需要可以copy

xxx.c

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include
  10. #include
  11. #include
  12. #include
  13. #include
  14. #include
  15. #include
  16. #include of.h>
  17. #include
  18. #include
  19. #include
  20. #include
  21. #include
  22. static int gpionum = 0;
  23. static int irqnum = 0;
  24. static irqreturn_t my_handler(int irq, void *dev_id)
  25. {
  26. printk("%s\r\n",__FUNCTION__);
  27. return IRQ_HANDLED;
  28. }
  29. static int gpio_keys_probe(struct platform_device *pdev)
  30. {
  31. int ret = 0;
  32. struct device_node *node = NULL;; /* 設(shè)備節(jié)點*/
  33. node = of_find_compatible_node(NULL,NULL,"atkalpha-key");
  34. if (node == NULL){
  35. printk("%s:atkalpha-key node not find!\r\n",__FUNCTION__);
  36. return -EINVAL;
  37. }
  38. /* 提取 GPIO */
  39. gpionum = of_get_named_gpio(node,"key-gpio", 0);
  40. if (gpionum < 0) {
  41. printk("of_get_named_gpio can't get key\r\n");
  42. }
  43. /* 初始化 key 所使用的 IO,并且設(shè)置成中斷模式 */
  44. gpio_request(gpionum, "key-gpio");
  45. gpio_direction_input(gpionum);
  46. irqnum = gpio_to_irq(gpionum);
  47. ret = request_irq(irqnum,my_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "my-key", NULL);
  48. if(ret < 0){
  49. printk("irq %d request failed!\r\n", irqnum);
  50. return -EFAULT;
  51. }
  52. return 0;
  53. }
  54. static const struct of_device_id gpio_keys_of_match[] = {
  55. { .compatible = "atkalpha-key", },
  56. { },
  57. };
  58. MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
  59. static int gpio_keys_remove(struct platform_device *pdev)
  60. {
  61. return 0;
  62. }
  63. static int gpio_keys_suspend(struct device *dev)
  64. {
  65. printk("%s\r\n",__FUNCTION__);
  66. enable_irq_wake(irqnum);
  67. return 0;
  68. }
  69. static int gpio_keys_resume(struct device *dev)
  70. {
  71. printk("%s\r\n",__FUNCTION__);
  72. disable_irq_wake(irqnum);
  73. return 0;
  74. }
  75. static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
  76. static struct platform_driver gpio_keys_device_driver = {
  77. .probe = gpio_keys_probe,
  78. .remove = gpio_keys_remove,
  79. .driver = {
  80. .name = "my-key",
  81. .pm = &gpio_keys_pm_ops,
  82. .of_match_table = of_match_ptr(gpio_keys_of_match),
  83. }
  84. };
  85. static int __init gpio_keys_init(void)
  86. {
  87. return platform_driver_register(&gpio_keys_device_driver);
  88. }
  89. static void __exit gpio_keys_exit(void)
  90. {
  91. platform_driver_unregister(&gpio_keys_device_driver);
  92. }
  93. module_init(gpio_keys_init);
  94. module_exit(gpio_keys_exit);
  95. MODULE_LICENSE("GPL");
  96. MODULE_AUTHOR("Jason");
  97. MODULE_DESCRIPTION("Keyboard driver for GPIOs");
  98. MODULE_ALIAS("platform:gpio-keys");

xxx.dts

  1. key {
  2. #address-cells = <1>;
  3. #size-cells = <1>;
  4. compatible = "atkalpha-key";
  5. key-gpio = <&gpio1 18 GPIO_ACTIVE_LOW>; /* KEY0 */
  6. interrupt-parent = <&gpio1>;
  7. interrupts = <18 irq_type_edge_both="">; /* FALLING RISING */
  8. gpio-key,wakeup;
  9. status = "okay";
  10. };

最后再總結(jié)一下:中斷喚醒系統(tǒng)和普通的驅(qū)動區(qū)別在于,多了兩個函數(shù):suspend 和 resume,在 suspend 函數(shù)中,調(diào)用 enable_irq_wake,表示該中斷號在系統(tǒng)休眠時也是 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)休眠過程中就會調(diào)用到設(shè)備注冊的 suspend,系統(tǒng)喚醒過程中就會調(diào)用設(shè)備注冊的 resume 函數(shù)。

至于 probe 函數(shù)的書寫,我在 GPIO 子系統(tǒng)和中斷子系統(tǒng)系列文章都講過這些函數(shù)的使用,大家可以去我的網(wǎng)站查看:

http://www.linuxer.vip

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

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

原文鏈接:https://mp.weixin.qq.com/s/FooG30_Fr4svQcqbK9y_9g

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 一级黄片毛片 | 精品一区二区三区在线视频 | 一级毛片免费看 | 四虎网站 | 大片免费播放在线观看视频 | 欧美精品欧美精品系列 | 成人免费视频视频 | 午夜资源 | www.avtt天堂网 | 成人精品在线 | 久久国产精品免费一区二区三区 | 欧美高清视频在线观看 | 九九九九精品九九九九 | 亚洲国产第一页 | 欧美成人免费在线视频 | 色淫av | 青青草免费在线 | 91成人精品 | 国产一区 | 这里有精品视频 | 久久久一 | 久久久激情视频 | 亚洲伊人影院 | 日本欧美在线 | 日韩精品一区二区在线观看 | 日韩精品一区二区三区中文字幕 | 国产一区二区三区在线免费观看 | 久草 在线| 日韩精品在线观看免费 | 午夜精品电影 | 亚洲欧洲精品一区二区 | 精品国产乱码久久久久久1区2区 | 亚洲欧美在线视频 | 激情毛片 | 人人爽视频 | 激情综合丁香 | 九九在线国产视频 | 日韩高清国产一区在线 | 午夜免费福利视频 | a资源在线观看 | 紧缚调教一区二区三区视频 |