一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

系統(tǒng)休眠過程中,如何suspend設(shè)備中斷(IRQ)?

454398 ? 來源:蝸窩科技 ? 作者:linuxer ? 2020-09-21 14:29 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、設(shè)備IRQ的suspend和resume

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

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

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各個(gè)設(shè)備的irq

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

error = platform_suspend_prepare_noirq(state);

……

}

在dpm_suspend_noirq函數(shù)中,會針對系統(tǒng)中的每一個(gè)device,依次調(diào)用device_suspend_noirq來執(zhí)行該設(shè)備noirq情況下的suspend callback函數(shù),當(dāng)然,在此之前會調(diào)用suspend_device_irqs函數(shù)來disable所有設(shè)備的irq。

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

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

static int suspend_enter(suspend_state_t state, bool *wakeup)

{……

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

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

platform_resume_early(state);

dpm_resume_early(PMSG_RESUME);

……}

在dpm_resume_noirq函數(shù)中,會調(diào)用各個(gè)設(shè)備驅(qū)動的noirq callback,在此之后,調(diào)用resume_device_irqs函數(shù),完成各個(gè)設(shè)備irq的enable。

二、關(guān)于IRQF_NO_SUSPEND Flag

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

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

需要注意的是:IRQF_NO_SUSPEND flag影響使用該IRQ的所有外設(shè)(一個(gè)IRQ可以被多個(gè)外設(shè)共享,不過ARM中不會這么用)。如果一個(gè)IRQ被多個(gè)外設(shè)共享,并且各個(gè)外設(shè)都注冊了對應(yīng)的interrupt handler,如果其一在申請中斷的時(shí)候使用了IRQF_NO_SUSPEND flag,那么在系統(tǒng)suspend的時(shí)候(指suspend_device_irqs之后,按理說各個(gè)IRQ已經(jīng)被disable了),所有該IRQ上的各個(gè)設(shè)備的interrupt handler都可以被正常的被觸發(fā)執(zhí)行,即便是有些設(shè)備在調(diào)用request_irq(或者其他中斷注冊函數(shù))的時(shí)候沒有設(shè)定IRQF_NO_SUSPEND flag。正因?yàn)槿绱耍覀儜?yīng)該盡可能的避免同時(shí)使用IRQF_NO_SUSPEND 和IRQF_SHARED這兩個(gè)flag。

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

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

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

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

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

調(diào)用了enable_irq_wake會影響系統(tǒng)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 中斷的代碼

}

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

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

在系統(tǒng)suspend的過程中,每一個(gè)來自wakeup source的中斷都會終止suspend過程或者將系統(tǒng)喚醒(如果系統(tǒng)已經(jīng)進(jìn)入suspend狀態(tài))。但是,在執(zhí)行了suspend_device_irqs之后,普通的中斷被屏蔽了,這時(shí)候,即便HW觸發(fā)了中斷信號也無法執(zhí)行其interrupt handler。作為wakeup source的IRQ會怎樣呢?雖然它的中斷沒有被mask掉,但是其interrupt handler也不會執(zhí)行(這時(shí)候的HW Signal只是用來喚醒系統(tǒng))。唯一有機(jī)會執(zhí)行的interrupt handler是那些標(biāo)記IRQF_NO_SUSPEND flag的IRQ,因?yàn)樗鼈兊闹袛嗍冀K是enable的。當(dāng)然,這些中斷不應(yīng)該調(diào)用enable_irq_wake進(jìn)行喚醒源的設(shè)定。

四、Interrupts and Suspend-to-Idle

Suspend-to-idle (也被稱為"freeze" 狀態(tài))是一個(gè)相對比較新的系統(tǒng)電源管理狀態(tài),相關(guān)代碼如下:

static int suspend_enter(suspend_state_t state, bool *wakeup)

{

……

各個(gè)設(shè)備的late suspend階段

各個(gè)設(shè)備的noirq suspend階段

if (state == PM_SUSPEND_FREEZE) {

freeze_enter();

goto Platform_wake;

}

……

}

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

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

五、IRQF_NO_SUSPEND 標(biāo)志和enable_irq_wake函數(shù)不能同時(shí)使用

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

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

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

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

參考文獻(xiàn)

1、內(nèi)核文檔power/suspend-and-interrupts.txt

聲明:本文內(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)注

    68

    文章

    19896

    瀏覽量

    235291
  • 中斷
    +關(guān)注

    關(guān)注

    5

    文章

    905

    瀏覽量

    42810
  • IRQ
    IRQ
    +關(guān)注

    關(guān)注

    0

    文章

    16

    瀏覽量

    11104
  • Freeze
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    8081
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-Linux系統(tǒng)中斷之按鍵中斷驅(qū)動

    設(shè)備節(jié)點(diǎn)相關(guān)的頭文件 #include //包含gpio子系統(tǒng)相關(guān)函數(shù)頭文件 #include//包含中斷函數(shù)相關(guān)頭文件 #define DEVICE_NAME \"button_irq
    發(fā)表于 03-31 16:50

    如何使用LS1046A IFC IRQ?

    嗨,我們設(shè)計(jì)了一個(gè)定制的基于 LS1046A 的電路板。 我想制作一個(gè)內(nèi)核驅(qū)動程序,在 cpld(fpga) 處理中斷信號。 但是,它沒有注冊,如下面的 insmod 結(jié)果所示。 在這種情況下
    發(fā)表于 03-31 08:18

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-Linux系統(tǒng)中斷之Linux中斷介紹

    能夠正確地響應(yīng)中斷事件。在中斷處理程序,可以執(zhí)行相應(yīng)的操作,如讀取設(shè)備數(shù)據(jù)、處理中斷狀態(tài)等。(三)中斷
    發(fā)表于 03-28 10:44

    飛凌嵌入式ElfBoard ELF 1板卡-Linux系統(tǒng)中斷之按鍵中斷驅(qū)動

    #include //包含gpio子系統(tǒng)相關(guān)函數(shù)頭文件#include//包含中斷函數(shù)相關(guān)頭文件 #define DEVICE_NAME \"button_irq\"http:// 設(shè)備名稱
    發(fā)表于 03-28 10:42

    半導(dǎo)體制造過程中的三個(gè)主要階段

    前段工藝(Front-End)、中段工藝(Middle-End)和后段工藝(Back-End)是半導(dǎo)體制造過程中的三個(gè)主要階段,它們在制造過程中扮演著不同的角色。
    的頭像 發(fā)表于 03-28 09:47 ?2723次閱讀
    半導(dǎo)體制造<b class='flag-5'>過程中</b>的三個(gè)主要階段

    飛凌嵌入式ElfBoard ELF 1板卡-Linux系統(tǒng)中斷之Linux中斷介紹

    能夠正確地響應(yīng)中斷事件。在中斷處理程序,可以執(zhí)行相應(yīng)的操作,如讀取設(shè)備數(shù)據(jù)、處理中斷狀態(tài)等。(三)中斷
    發(fā)表于 03-27 10:28

    TIM2輸入捕獲,DMA開啟中斷傳輸輸入捕獲數(shù)據(jù),程序跑的過程中,DMA一直中斷,TIM6只觸發(fā)一次中斷,怎么解決?

    用TIM2捕獲輸入的數(shù)據(jù),并且通過DMA存儲,在開啟DMA中斷同時(shí),TIM6中斷也開啟(用于計(jì)時(shí))。但是程序跑的過程中,DMA一直中斷,TIM6只觸發(fā)一次
    發(fā)表于 03-14 06:39

    如何在播放視頻過程中插入音頻

    ZDP14x0是一款基于開源GUI引擎的圖像顯示專用驅(qū)動芯片,可以通過串口或者SPI與其他芯片通信,且能播放視頻。本文將介紹如何在播放視頻過程中插入音頻。
    的頭像 發(fā)表于 12-26 11:13 ?1103次閱讀
    如何在播放視頻<b class='flag-5'>過程中</b>插入音頻

    調(diào)試ADS1278,讀取數(shù)據(jù)過程中在下一次SYNC低脈沖信號前出現(xiàn)反復(fù)進(jìn)入中斷的現(xiàn)象,請問是否正確?

    準(zhǔn)備檢索變?yōu)榈?,我控制在DRDY下降沿進(jìn)入中斷讀取數(shù)據(jù)(僅讀取通道1),但是讀取數(shù)據(jù)過程中在下一次SYNC低脈沖信號前出現(xiàn)反復(fù)進(jìn)入中斷的現(xiàn)象,請問是否正確?在時(shí)序上還有什么問題嗎? 黃色SCLK波形
    發(fā)表于 12-25 07:03

    Jtti:有哪些工具可以幫助我監(jiān)控自動更新過程中系統(tǒng)狀態(tài)?

    監(jiān)控自動更新過程中系統(tǒng)狀態(tài)對于確保系統(tǒng)的穩(wěn)定性和性能至關(guān)重要。以下是一些可以幫助你監(jiān)控系統(tǒng)狀態(tài)的工具: 1.系統(tǒng)日志工具 dmesg:顯示
    的頭像 發(fā)表于 12-10 15:46 ?500次閱讀

    芯片制造過程中的兩種刻蝕方法

    本文簡單介紹了芯片制造過程中的兩種刻蝕方法 ? 刻蝕(Etch)是芯片制造過程中相當(dāng)重要的步驟。 刻蝕主要分為干刻蝕和濕法刻蝕。 ①干法刻蝕 利用等離子體將不要的材料去除。 ②濕法刻蝕 利用腐蝕性
    的頭像 發(fā)表于 12-06 11:13 ?1621次閱讀
    芯片制造<b class='flag-5'>過程中</b>的兩種刻蝕方法

    步進(jìn)電機(jī)如何在加減速過程中控制技術(shù)?

    步進(jìn)電機(jī)是一種將電脈沖信號轉(zhuǎn)換為角位移或線位移的電機(jī),廣泛應(yīng)用于各種自動化控制系統(tǒng)。在加減速過程中,步進(jìn)電機(jī)的控制技術(shù)至關(guān)重要,以確保系統(tǒng)的穩(wěn)定性和精確性。 加減速控制原理 步進(jìn)電機(jī)
    的頭像 發(fā)表于 10-23 10:02 ?1311次閱讀

    單片機(jī)有哪些中斷類型

    單片機(jī)中斷是指在單片機(jī)執(zhí)行程序的過程中,當(dāng)外部設(shè)備或內(nèi)部條件發(fā)生某個(gè)特定事件時(shí),能夠暫停當(dāng)前正在執(zhí)行的程序,轉(zhuǎn)而去執(zhí)行一個(gè)特定的服務(wù)程序(稱為中斷服務(wù)程序或
    的頭像 發(fā)表于 10-17 18:12 ?2404次閱讀

    在linux系統(tǒng)下,TLV320ADC3101可以在設(shè)備運(yùn)行過程中,可以實(shí)時(shí)修改CODEC的采樣率嗎?

    請問:在linux系統(tǒng)下,TLV320ADC3101可以在設(shè)備運(yùn)行過程中,可以實(shí)時(shí)修改CODEC的采樣率嗎? 采樣位數(shù),增益這些呢
    發(fā)表于 09-30 06:45

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

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