在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

系統休眠過程中,如何suspend設備中斷(IRQ)?

454398 ? 來源:蝸窩科技 ? 作者:linuxer ? 2020-09-21 14:29 ? 次閱讀

一、設備IRQ的suspend和resume

本小節主要解決這樣一個問題:在系統休眠過程中,如何suspend設備中斷(IRQ)?在從休眠中喚醒的過程中,如何resume設備IRQ?

一般而言,在系統suspend過程的后期,各個設備的IRQ (interrupt request line)會被disable掉。具體的時間點是在各個設備的late suspend階段之后。代碼如下(刪除了部分無關代碼):

static int suspend_enter(suspend_state_t state, bool *wakeup)

{……

error = dpm_suspend_late(PMSG_SUSPEND);-----late suspend階段

error = platform_suspend_prepare_late(state);

下面的代碼中會disable各個設備的irq

error = dpm_suspend_noirq(PMSG_SUSPEND);----進入noirq的階段

error = platform_suspend_prepare_noirq(state);

……

}

在dpm_suspend_noirq函數中,會針對系統中的每一個device,依次調用device_suspend_noirq來執行該設備noirq情況下的suspend callback函數,當然,在此之前會調用suspend_device_irqs函數來disable所有設備的irq。

之所以這么做,其思路是這樣的:在各個設備驅動完成了late suspend之后,按理說這些已經被suspend的設備不應該再觸發中斷了。如果還有一些設備沒有被正確的suspend,那么我們最好的策略是mask該設備的irq,從而阻止中斷的遞交。此外,在過去的代碼中(指interrupt handler),我們對設備共享IRQ的情況處理的不是很好,存在這樣的問題:在共享IRQ的設備們完成suspend之后,如果有中斷觸發,這時候設備驅動的interrupt handler并沒有準備好。在有些場景下,interrupt handler會訪問已經suspend設備的IO地址空間,從而導致不可預知的issue。這些issue很難debug,因此,我們引入了suspend_device_irqs()以及設備noirq階段的callback函數。

系統resume過程中,在各個設備的early resume過程之前,各個設備的IRQ會被重新打開,具體代碼如下(刪除了部分無關代碼):

static int suspend_enter(suspend_state_t state, bool *wakeup)

{……

platform_resume_noirq(state);----首先執行noirq階段的resume

dpm_resume_noirq(PMSG_RESUME);------在這里會恢復irq,然后進入early resume階段

platform_resume_early(state);

dpm_resume_early(PMSG_RESUME);

……}

在dpm_resume_noirq函數中,會調用各個設備驅動的noirq callback,在此之后,調用resume_device_irqs函數,完成各個設備irq的enable。

二、關于IRQF_NO_SUSPEND Flag

當然,有些中斷需要在整個系統的suspend-resume過程中(包括在noirq階段,包括將nonboot CPU推送到offline狀態以及系統resume后,將其重新設置為online的階段)保持能夠觸發的狀態。一個簡單的例子就是timer中斷,此外IPI以及一些特殊目的設備中斷也需要如此。

在中斷申請的時候,IRQF_NO_SUSPEND flag可以用來告知IRQ subsystem,這個中斷就是上一段文字中描述的那種中斷:需要在系統的suspend-resume過程中保持enable狀態。有了這個flag,suspend_device_irqs并不會disable該IRQ,從而讓該中斷在隨后的suspend和resume過程中,保持中斷開啟。當然,這并不能保證該中斷可以將系統喚醒。如果想要達到喚醒的目的,請調用enable_irq_wake。

需要注意的是:IRQF_NO_SUSPEND flag影響使用該IRQ的所有外設(一個IRQ可以被多個外設共享,不過ARM中不會這么用)。如果一個IRQ被多個外設共享,并且各個外設都注冊了對應的interrupt handler,如果其一在申請中斷的時候使用了IRQF_NO_SUSPEND flag,那么在系統suspend的時候(指suspend_device_irqs之后,按理說各個IRQ已經被disable了),所有該IRQ上的各個設備的interrupt handler都可以被正常的被觸發執行,即便是有些設備在調用request_irq(或者其他中斷注冊函數)的時候沒有設定IRQF_NO_SUSPEND flag。正因為如此,我們應該盡可能的避免同時使用IRQF_NO_SUSPEND 和IRQF_SHARED這兩個flag。

三、系統中斷喚醒接口:enable_irq_wake() 和 disable_irq_wake()

有些中斷可以將系統從睡眠狀態中喚醒,我們稱之“可以喚醒系統的中斷”,當然,“可以喚醒系統的中斷”需要配置才能啟動喚醒系統這樣的功能。這樣的中斷一般在工作狀態的時候就是作為普通I/O interrupt出現,只要在準備使能喚醒系統功能的時候,才會發起一些特別的配置和設定。

這樣的配置和設定有可能是和硬件系統(例如SOC)上的信號處理邏輯相關的,我們可以考慮下面的HW block圖:

外設的中斷信號被送到“通用的中斷信號處理模塊”和“特定中斷信號接收模塊”。正常工作的時候,我們會turn on“通用的中斷信號處理模塊”的處理邏輯,而turn off“特定中斷信號接收模塊” 的處理邏輯。但是,在系統進入睡眠狀態的時候,有可能“通用的中斷信號處理模塊”已經off了,這時候,我們需要啟動“特定中斷信號接收模塊”來接收中斷信號,從而讓系統suspend-resume模塊(它往往是suspend狀態時候唯一能夠工作的HW block了)可以正常的被該中斷信號喚醒。一旦喚醒,我們最好是turn off“特定中斷信號接收模塊”,讓外設的中斷處理回到正常的工作模式,同時,也避免了系統suspend-resume模塊收到不必要的干擾。

IRQ子系統提供了兩個接口函數來完成這個功能:enable_irq_wake()函數用來打開該外設中斷線通往系統電源管理模塊(也就是上面的suspend-resume模塊)之路,另外一個接口是disable_irq_wake(),用來關閉該外設中斷線通往系統電源管理模塊路徑上的各種HW block。

調用了enable_irq_wake會影響系統suspend過程中的suspend_device_irqs處理,代碼如下:

static bool suspend_device_irq(struct irq_desc *desc)

{

……

if (irqd_is_wakeup_set(&desc->irq_data)) {

irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);

return true;

}

省略Disable 中斷的代碼

}

也就是說,一旦調用enable_irq_wake設定了該設備的中斷作為系統suspend的喚醒源,那么在該外設的中斷不會被disable,只是被標記一個IRQD_WAKEUP_ARMED的標記。對于那些不是wakeup source的中斷,在suspend_device_irq 函數中會標記IRQS_SUSPENDED并disable該設備的irq。在系統喚醒過程中(resume_device_irqs),被diable的中斷會重新enable。

當然,如果在suspend的過程中發生了某些事件(例如wakeup source產生了有效信號),從而導致本次suspend abort,那么這個abort事件也會通知到PM core模塊。事件并不需要被立刻通知到PM core模塊,一般而言,suspend thread會在某些點上去檢查pending的wakeup event。

在系統suspend的過程中,每一個來自wakeup source的中斷都會終止suspend過程或者將系統喚醒(如果系統已經進入suspend狀態)。但是,在執行了suspend_device_irqs之后,普通的中斷被屏蔽了,這時候,即便HW觸發了中斷信號也無法執行其interrupt handler。作為wakeup source的IRQ會怎樣呢?雖然它的中斷沒有被mask掉,但是其interrupt handler也不會執行(這時候的HW Signal只是用來喚醒系統)。唯一有機會執行的interrupt handler是那些標記IRQF_NO_SUSPEND flag的IRQ,因為它們的中斷始終是enable的。當然,這些中斷不應該調用enable_irq_wake進行喚醒源的設定。

四、Interrupts and Suspend-to-Idle

Suspend-to-idle (也被稱為"freeze" 狀態)是一個相對比較新的系統電源管理狀態,相關代碼如下:

static int suspend_enter(suspend_state_t state, bool *wakeup)

{

……

各個設備的late suspend階段

各個設備的noirq suspend階段

if (state == PM_SUSPEND_FREEZE) {

freeze_enter();

goto Platform_wake;

}

……

}

Freeze和suspend的前面的操作基本是一樣的:首先凍結系統中的進程,然后是suspend系統中的形形色色的device,不一樣的地方在noirq suspend完成之后,freeze不會disable那些non-BSP的處理器和syscore suspend階段,而是調用freeze_enter函數,把所有的處理器推送到idle狀態。這時候,任何的enable的中斷都可以將系統喚醒。而這也就意味著那些標記IRQF_NO_SUSPEND(其IRQ沒有在suspend_device_irqs過程中被mask掉)是有能力將處理器從idle狀態中喚醒(不過,需要注意的是:這種信號并不會觸發一個系統喚醒信號),而普通中斷由于其IRQ被disable了,因此無法喚醒idle狀態中的處理器。

那些能夠喚醒系統的wakeup interrupt呢?由于其中斷沒有被mask掉,因此也可以將系統從suspend-to-idle狀態中喚醒。整個過程和將系統從suspend狀態中喚醒一樣,唯一不同的是:將系統從freeze狀態喚醒走的中斷處理路徑,而將系統從suspend狀態喚醒走的喚醒處理路徑,需要電源管理HW BLOCK中特別的中斷處理邏輯的參與。

五、IRQF_NO_SUSPEND 標志和enable_irq_wake函數不能同時使用

針對一個設備,在申請中斷的時候使用IRQF_NO_SUSPEND flag,又同時調用enable_irq_wake設定喚醒源是不合理的,主要原因如下:

1、如果IRQ沒有共享,使用IRQF_NO_SUSPEND flag說明你想要在整個系統的suspend-resume過程中(包括suspend_device_irqs之后的階段)保持中斷打開以便正常的調用其interrupt handler。而調用enable_irq_wake函數則說明你想要將該設備的irq信號設定為中斷源,因此并不期望調用其interrupt handler。而這兩個需求明顯是互斥的。

2、IRQF_NO_SUSPEND 標志和enable_irq_wake函數都不是針對一個interrupt handler的,而是針對該IRQ上的所有注冊的handler的。在一個IRQ上共享喚醒源以及no suspend中斷源是比較荒謬的。

不過,在非常特殊的場合下,一個IRQ可以被設定為wakeup source,同時也設定IRQF_NO_SUSPEND 標志。為了代碼邏輯正確,該設備的驅動代碼需要滿足一些特別的需求。

參考文獻

1、內核文檔power/suspend-and-interrupts.txt

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    19291

    瀏覽量

    229906
  • 中斷
    +關注

    關注

    5

    文章

    898

    瀏覽量

    41513
  • IRQ
    IRQ
    +關注

    關注

    0

    文章

    16

    瀏覽量

    10770
  • Freeze
    +關注

    關注

    0

    文章

    4

    瀏覽量

    7983
收藏 人收藏

    評論

    相關推薦

    Jtti:有哪些工具可以幫助我監控自動更新過程中系統狀態?

    監控自動更新過程中系統狀態對于確保系統的穩定性和性能至關重要。以下是一些可以幫助你監控系統狀態的工具: 1.系統日志工具 dmesg:顯示
    的頭像 發表于 12-10 15:46 ?102次閱讀

    單片機有哪些中斷類型

    單片機中斷是指在單片機執行程序的過程中,當外部設備或內部條件發生某個特定事件時,能夠暫停當前正在執行的程序,轉而去執行一個特定的服務程序(稱為中斷服務程序或
    的頭像 發表于 10-17 18:12 ?732次閱讀

    在linux系統下,TLV320ADC3101可以在設備運行過程中,可以實時修改CODEC的采樣率嗎?

    請問:在linux系統下,TLV320ADC3101可以在設備運行過程中,可以實時修改CODEC的采樣率嗎? 采樣位數,增益這些呢
    發表于 09-30 06:45

    __disable_irq()和__enable_irq()函數的具體定義

    前段時間一工程師向我咨詢了一個問題,問我為什么他的MCU KEIL工程代碼里沒有找到__disable_irq() 和 __enable_irq()的具體定義,是不是有問題。
    的頭像 發表于 08-29 10:06 ?2565次閱讀
    __disable_<b class='flag-5'>irq</b>()和__enable_<b class='flag-5'>irq</b>()函數的具體定義

    設備運行過程中,調用云端接口后報status500的原因?如何解決?

    設備運行過程中出現,調用云端接口后,報500,設備接收到了云端發過來數據,并執行了動作! 想問導致status500錯誤具體可能的情況和原因是什么?如何解決?
    發表于 07-18 06:48

    電容充放電過程中電壓的變化規律

    電容充放電過程中電壓的變化規律是一個非常重要的電子學課題,涉及到電容器的基本工作原理和特性。在這篇文章,我們將詳細探討電容充放電過程中電壓的變化規律,包括電容的基本特性、充電過程、放
    的頭像 發表于 07-11 09:43 ?5720次閱讀

    STM32MP157D提示DAC沒有進入syspend,導致休眠失敗怎么解決?

    : last_failed_dev:40017000.dac:dac@1 40017000.dac:dac@1 last_failed_errno: -16 -16 last_failed_step:suspend suspend DAC驅動使用的是ST原生驅動,想問一下
    發表于 05-30 08:16

    使用FreeRTOS過程中如何退出Tickless?

    在使用FreeRTOS過程中,如果設置Tickless,那要怎么退出呢?進入Tickless模式的話應該是吧系統滴答中斷給關閉了,如果我在沒有外部中斷的情況下,那
    發表于 04-17 06:26

    stm32f4如何禁止usb suspend或修改進入suspend的時間?

    手冊說是usb設備在3ms沒有數據就會進入 suspend mode,哪里可以修改時間,或者把3ms修改成3秒,或者禁止usb 進入suspend. DCD_HandleUSBSuspend_ISR USBD_
    發表于 04-02 08:06

    使用RTC喚醒中斷喚醒休眠狀態的MCU出現故障怎么解決?

    因在做項目為了節省功耗需求,使設備不運行時MCU休眠,然后用內部RTC喚醒中斷重啟MCU;在批量電路板中發現有極個別MCU無法喚醒,其他設備運行正常,有大佬碰到過類似情況沒有?謝謝!
    發表于 04-01 06:23

    電力補償電容器運行過程中缺相怎么辦?

    電力補償電容器是現代電力系統不可或缺的重要設備之一。它能夠有效改善電力系統的功率因數,提高電能利用率,降低電力系統的損耗。然而,在電力補償
    的頭像 發表于 02-20 14:28 ?996次閱讀
    電力補償電容器運行<b class='flag-5'>過程中</b>缺相怎么辦?

    為什么nulink會在調試過程中時不時的中斷

    為啥nulink 會在調試過程中時不時的中斷?是不是要設置什么?
    發表于 01-17 06:52

    什么是電池休眠?鋰電池休眠怎么激活?

    什么是電池休眠?鋰電池休眠怎么激活? 電池休眠是指鋰電池在長期存放或使用過程中,由于自放電和化學反應等原因,使得電池電量降低到一定程度后進入休眠
    的頭像 發表于 01-10 16:45 ?3690次閱讀

    stm32中斷怎么處理的

    中斷是指在程序執行過程中,由硬件或軟件的觸發而打斷正常的程序執行流程,暫時轉去執行特定的處理程序,并在完成后返回原來的程序流程。中斷可以分為硬件中斷和軟件
    的頭像 發表于 01-02 17:35 ?2600次閱讀

    為什么ADE7758中斷IRQ始終為低電平?

    我使用ADE7758與PIC16F877,將7758的IRQ與877的INT直接相連。初始化后測IRQ始終是低電平,即使讀取了復位狀態寄存器后(RSTATUS)依然是低電平。然后在初始化我將
    發表于 01-02 06:22
    主站蜘蛛池模板: 日本久久久久久久| 狠狠操影院| 婷婷色在线视频| a欧美视频| 亚洲综合久久综合激情久久| 伊人久久大香线蕉综合高清| 一级特级毛片免费| 亚洲成在人线影视天堂网| 亚洲第一色图| 日韩黄色成人| 久久久久免费精品国产小说| 国产一区二区三区在线观看影院| 国产美女主播在线观看| 又粗又硬又爽又黄毛片| 天堂网中文在线最新版| 色婷婷综合缴情综六月| 日本免费性| 美女涩涩网站| 色尼玛亚洲综合| 美女免费观看一区二区三区| 国产性色视频| 天天干天天玩| 狠狠ri| 另类激情亚洲| 综合激情网五月| 日本不卡一区在线| 888午夜不卡理论久久| 日本亚洲视频| 午夜婷婷网| 婷婷中文字幕| 免费国产一区二区三区| 成人免费观看一区二区| 日日干夜夜骑| 免费三级pq| 日本一本一道久久香蕉免费| 美女福利在线观看| 国产黄色在线看| 亚洲免费三级| 久久伊人精品青青草原高清| www四虎影视| 国产精品夜夜春夜夜爽久久|