linux kernel的中斷子系統(tǒng)之(四):High level irq event handler作者:linuxer 發(fā)布于:2014-8-28 20:00 分類:中斷子系統(tǒng) 一、前言 當外設觸發(fā)一次中斷后,一個大概的處理過程是: 1、具體CPU architecture相關的模塊會進行現(xiàn)場保護,然后調(diào)用machine driver對應的中斷處理handler 2、machine driver對應的中斷處理handler中會根據(jù)硬件的信息獲取HW interrupt ID,并且通過irq domain模塊翻譯成IRQ number 3、調(diào)用該IRQ number對應的high level irq event handler,在這個high level的handler中,會通過和interupt controller交互,進行中斷處理的flow control(處理中斷的嵌套、搶占等),當然最終會遍歷該中斷描述符的IRQ action list,調(diào)用外設的specific handler來處理該中斷 4、具體CPU architecture相關的模塊會進行現(xiàn)場恢復。 上面的1、4這兩個步驟在linux kernel的中斷子系統(tǒng)之(六):ARM中斷處理過程中已經(jīng)有了較為細致的描述,步驟2在linux kernel的中斷子系統(tǒng)之(二):irq domain介紹中介紹,本文主要描述步驟3,也就是linux中斷子系統(tǒng)的high level irq event handler。
注:這份文檔充滿了猜測和空想,很多地方描述可能是有問題的,不過我還是把它發(fā)出來,拋磚引玉,希望可以引發(fā)大家討論。
一、如何進入high level irq event handler 1、從具體CPU architecture的中斷處理到machine相關的處理模塊 說到具體的CPU,我們還是用ARM為例好了。對于ARM,我們在ARM中斷處理文檔中已經(jīng)有了較為細致的描述。這里我們看看如何從從具體CPU的中斷處理到machine相關的處理模塊 ,其具體代碼如下:
其實,直接從CPU的中斷處理跳轉(zhuǎn)到通用中斷處理模塊是不可能的,中斷處理不可能越過interrupt controller這個層次。一般而言,通用中斷處理模塊會提供一些通用的中斷代碼處理庫,然后由interrupt controller這個層次的代碼調(diào)用這些通用中斷處理的完成整個的中斷處理過程?!癷nterrupt controller這個層次的代碼”是和硬件中斷系統(tǒng)設計相關的,例如:系統(tǒng)中有多少個interrupt contrller,每個interrupt controller是如何控制的?它們是如何級聯(lián)的?我們稱這些相關的驅(qū)動模塊為machine interrupt driver。 在上面的代碼中,如果配置了MULTI_IRQ_HANDLER的話,ARM中斷處理則直接跳轉(zhuǎn)到一個叫做handle_arch_irq函數(shù),如果系統(tǒng)中只有一個類型的interrupt controller(可能是多個interrupt controller,例如使用兩個級聯(lián)的GIC),那么handle_arch_irq可以在interrupt controller初始化的時候設定。代碼如下:
gic_nr是GIC的編號,linux kernel初始化過程中,每發(fā)現(xiàn)一個GIC,都是會指向GIC driver的初始化函數(shù)的,不過對于第一個GIC,gic_nr等于0,對于第二個GIC,gic_nr等于1。當然handle_arch_irq這個函數(shù)指針不是per CPU的變量,是全部CPU共享的,因此,初始化一次就OK了。 當使用多種類型的interrupt controller的時候(例如HW 系統(tǒng)使用了S3C2451這樣的SOC,這時候,系統(tǒng)有兩種interrupt controller,一種是GPIO type,另外一種是SOC上的interrupt controller),則不適合在interrupt controller中進行設定,這時候,可以考慮在machine driver中設定。在這種情況下,handle_arch_irq 這個函數(shù)是在setup_arch函數(shù)中根據(jù)machine driver設定,具體如下:
關于MULTI_IRQ_HANDLER這個配置項,我們可以再多說幾句。當然,其實這個配置項的名字已經(jīng)出賣它了。multi irq handler就是說系統(tǒng)中有多個irq handler,可以在run time的時候指定。為何要run time的時候,從多個handler中選擇一個呢?HW interrupt block難道不是固定的嗎?我的理解(猜想)是:一個kernel的image支持多個HW platform,對于不同的HW platform,在運行時檢查HW platform的類型,設定不同的irq handler。 2、interrupt controller相關的代碼 我們還是以2個級聯(lián)的GIC為例來描述interrupt controller相關的代碼。代碼如下:
更多關于GIC相關的信息,請參考linux kernel的中斷子系統(tǒng)之(七):GIC代碼分析。對于ARM處理器,handle_IRQ代碼如下:
3、調(diào)用high level handler 調(diào)用high level handler的代碼邏輯非常簡單,如下:
二、理解high level irq event handler需要的知識準備 1、自動探測IRQ 一個硬件驅(qū)動可以通過下面的方法進行自動探測它使用的IRQ:
如果能夠自動探測到IRQ,上面程序中的irq(probe_irq_off的返回值)就是自動探測的結(jié)果。后續(xù)程序可以通過request_threaded_irq申請該IRQ。probe_irq_on函數(shù)主要的目的是返回一個32 bit的掩碼,通過該掩碼可以知道可能使用的IRQ number有哪些,具體代碼如下:
(1)那些能自動探測IRQ的中斷描述符需要具體兩個條件: a、該中斷描述符還沒有通過request_threaded_irq或者其他方式申請該IRQ的specific handler(也就是irqaction數(shù)據(jù)結(jié)構(gòu)) b、該中斷描述符允許自動探測(不能設定IRQ_NOPROBE) (2)如果滿足上面的條件,那么該中斷描述符屬于備選描述符。設定其internal state為IRQS_AUTODETECT | IRQS_WAITING。IRQS_AUTODETECT表示本IRQ正處于自動探測中。 (3)在等待過程中,系統(tǒng)仍然允許,各種中斷依然會觸發(fā)。在各種high level irq event handler中,總會有如下的代碼:
這里會清除IRQS_WAITING狀態(tài)。 (4)這時候,我們還沒有控制那個想要自動探測IRQ的硬件產(chǎn)生中斷,因此處于自動探測中,并且IRQS_WAITING并清除的一定不是我們期待的IRQ(可能是spurious interrupts導致的),這時候,clear IRQS_AUTODETECT,shutdown該IRQ。 (5)最大探測的IRQ是31(mask是一個32 bit的value),mask返回的是可能的irq掩碼。 我們再來看看probe_irq_off的代碼:
因為在調(diào)用probe_irq_off已經(jīng)觸發(fā)了自動探測IRQ的那個硬件中斷,因此在該中斷的high level handler的執(zhí)行過程中,該硬件對應的中斷描述符的IRQS_WAITING標致應該已經(jīng)被清除,因此probe_irq_off函數(shù)scan中斷描述符DB,找到處于auto probe中,而且IRQS_WAITING標致被清除的那個IRQ。如果找到一個,那么探測OK,返回該IRQ number,如果找到多個,說明探測失敗,返回負的IRQ個數(shù)信息,沒有找到的話,返回0。
一個ARM SOC總是有很多的GPIO,有些GPIO可以提供中斷功能,這些GPIO的中斷可以配置成level trigger或者edge trigger。一般而言,大家都更喜歡用level trigger的中斷。有的SOC只能是有限個數(shù)的GPIO可以配置成電平中斷,因此,在項目初期進行pin define的時候,大家都在爭搶電平觸發(fā)的GPIO。 電平觸發(fā)的中斷有什么好處呢?電平觸發(fā)的中斷很簡單、直接,只要硬件檢測到硬件事件(例如有數(shù)據(jù)到來),其assert指定的電平信號,CPU ack該中斷后,電平信號消失。但是對于邊緣觸發(fā)的中斷,它是用一個上升沿或者下降沿告知硬件的狀態(tài),這個狀態(tài)不是一個持續(xù)的狀態(tài),如果軟件處理不好,容易丟失中斷。 什么時候會resend一個中斷呢?我們考慮一個簡單的例子: (1)CPU A上正在處理x外設的中斷 (2)x外設的中斷再次到來(CPU A已經(jīng)ack該IRQ,因此x外設的中斷可以再次觸發(fā)),這時候其他CPU會處理它(mask and ack),并設置該中斷描述符是pending狀態(tài),并委托CPU A處理該pending狀態(tài)的中斷。需要注意的是CPU已經(jīng)ack了該中斷,因此該中斷的硬件狀態(tài)已經(jīng)不是pending狀態(tài),無法觸發(fā)中斷了,這里的pending狀態(tài)是指中斷描述符的軟件狀態(tài)。 (3)CPU B上由于同步的需求,disable了x外設的IRQ,這時候,CPU A沒有處理pending狀態(tài)的x外設中斷就離開了中斷處理過程。 (4)當enable x外設的IRQ的時候,需要檢測pending狀態(tài)以便resend該中斷,否則,該中斷會丟失的 具體代碼如下:
在各種high level irq event handler中,總會有如下的代碼:
這里會清除IRQS_REPLAY狀態(tài),表示該中斷已經(jīng)被retrigger,一次resend interrupt的過程結(jié)束。
3、unhandled interrupt和spurious interrupt 在中斷處理的最后,總會有一段代碼如下:
note_interrupt就是進行unhandled interrupt和spurious interrupt處理的。對于這類中斷,linux kernel有一套復雜的機制來處理,你可以通過command line參數(shù)(noirqdebug)來控制開關該功能。 當發(fā)生了一個中斷,但是沒有被處理(有兩種可能,一種是根本沒有注冊的specific handler,第二種是有handler,但是handler否認是自己對應的設備觸發(fā)的中斷),怎么辦?毫無疑問這是一個異常狀況,那么kernel是否要立刻采取措施將該IRQ disable呢?也不太合適,畢竟interrupt request信號線是允許共享的,直接disable該IRQ有可能會下手太狠,kernel采取了這樣的策略:如果該IRQ觸發(fā)了100,000次,但是99,900次沒有處理,在這種條件下,我們就是disable這個interrupt request line。多么有情有義的策略??!相關的控制數(shù)據(jù)在中斷描述符中,如下:
irq_count和irqs_unhandled都是比較直觀的,為何要記錄unhandled interrupt發(fā)生的時間呢?我們來看具體的代碼。具體的相關代碼位于note_interrupt中,如下:
(1)是否是一次有效的unhandled interrupt還要根據(jù)時間來判斷。一般而言,當硬件處于異常狀態(tài)的時候往往是非常短的時間觸發(fā)非常多次的中斷,如果距離上次unhandled interrupt的時間超過了10秒(HZ=100),那么我們要把irqs_unhandled重新計數(shù)。如果不這么處理的話,隨著時間的累計,最終irqs_unhandled可能會達到99900次的,從而把這個IRQ錯誤的推上了審判臺。 (2)irq_count每次都會加一,記錄IRQ被觸發(fā)的次數(shù)。但只要大于100000才啟動 step (3)中的檢查。一旦啟動檢查,irq_count會清零,irqs_unhandled也會清零,進入下一個檢查周期。 (3)如果滿足條件(IRQ觸發(fā)了100,000次,但是99,900次沒有處理),disable該IRQ。 (4)啟動timer,輪詢整個系統(tǒng)中的handler來處理這個中斷(輪詢啊,絕對是真愛?。_@個timer的callback函數(shù)定義如下:
三、和high level irq event handler相關的硬件描述 1、CPU layer和Interrupt controller之間的接口 從邏輯層面上看,CPU和interrupt controller之間的接口包括: (1)觸發(fā)中斷的signal。一般而言,這個(些)信號是電平觸發(fā)的。對于ARM CPU,它是nIRQ和nFIQ信號線,對于X86,它是INT和NMI信號線,對于PowerPC,這些信號線包括MC(machine check)、CRIT(critical interrupt)和NON-CRIT(Non critical interrupt)。對于linux kernel的中斷子系統(tǒng),我們只使用其中一個信號線(例如對于ARM而言,我們只使用nIRQ這個信號線)。這樣,從CPU層面看,其邏輯動作非常的簡單,不區(qū)分優(yōu)先級,觸發(fā)中斷的那個信號線一旦assert,并且CPU沒有mask中斷,那么軟件就會轉(zhuǎn)到一個異常向量執(zhí)行,完畢后返回現(xiàn)場。 (2)Ack中斷的signal。這個signal可能是物理上的一個連接CPU和interrupt controller的銅線,也可能不是。對于X86+8259這樣的結(jié)構(gòu),Ack中斷的signal就是nINTA信號線,對于ARM+GIC而言,這個信號就是總線上的一次訪問(讀Interrupt Acknowledge Register寄存器)。CPU ack中斷標識cpu開啟啟動中斷服務程序(specific handler)去處理該中斷。對于X86而言,ack中斷可以讓8259將interrupt vector數(shù)據(jù)送到數(shù)據(jù)總線上,從而讓CPU獲取了足夠的處理該中斷的信息。對于ARM而言,ack中斷的同時也就是獲取了發(fā)生中斷的HW interrupt ID,總而言之,ack中斷后,CPU獲取了足夠開啟執(zhí)行中斷處理的信息。 (3)結(jié)束中斷(EOI,end of interrupt)的signal。這個signal用來標識CPU已經(jīng)完成了對該中斷的處理(specific handler或者ISR,interrupt serivce routine執(zhí)行完畢)。實際的物理形態(tài)這里就不描述了,和ack中斷signal是類似的。 (4)控制總線和數(shù)據(jù)總線接口。通過這些接口,CPU可以訪問(讀寫)interrupt controller的寄存器。
2、Interrupt controller和Peripheral device之間的接口 所有的系統(tǒng)中,Interrupt controller和Peripheral device之間的接口都是一個Interrupt Request信號線。外設通過這個信號線上的電平或者邊緣向CPU(實際上是通過interrupt controller)申請中斷服務。
四、幾種典型的high level irq event handler 本章主要介紹幾種典型的high level irq event handler,在進行high level irq event handler的設定的時候需要注意,不是外設使用電平觸發(fā)就選用handle_level_irq,選用什么樣的high level irq event handler是和Interrupt controller的行為以及外設電平觸發(fā)方式?jīng)Q定的。介紹每個典型的handler之前,我會簡單的描述該handler要求的硬件行為,如果該外設的中斷系統(tǒng)符合這個硬件行為,那么可以選擇該handler為該中斷的high level irq event handler。 1、邊緣觸發(fā)的handler。 使用handle_edge_irq這個handler的硬件中斷系統(tǒng)行為如下: 我們以上升沿為例描述邊緣中斷的處理過程(下降沿的觸發(fā)是類似的)。當interrupt controller檢測到了上升沿信號,會將該上升沿狀態(tài)(pending)鎖存在寄存器中,并通過中斷的signal向CPU觸發(fā)中斷。需要注意:這時候,外設和interrupt controller之間的interrupt request信號線會保持高電平,這也就意味著interrupt controller不可能檢測到新的中斷信號(本身是高電平,無法形成上升沿)。這個高電平信號會一直保持到軟件ack該中斷(調(diào)用irq chip的irq_ack callback函數(shù))。ack之后,中斷控制器才有可能繼續(xù)探測上升沿,觸發(fā)下一次中斷。 ARM+GIC組成的系統(tǒng)不符合這個類型。雖然GIC提供了IAR(Interrupt Acknowledge Register)寄存器來讓ARM來ack中斷,但是,在調(diào)用high level handler之前,中斷處理程序需要通過讀取IAR寄存器獲得HW interrpt ID并轉(zhuǎn)換成IRQ number,因此實際上,對于GIC的irq chip,它是無法提供本場景中的irq_ack函數(shù)的。很多GPIO type的interrupt controller符合上面的條件,它們會提供pending狀態(tài)寄存器,讀可以獲取pending狀態(tài),而向pending狀態(tài)寄存器寫1可以ack該中斷,讓interrupt controller可以繼續(xù)觸發(fā)下一次中斷。 handle_edge_irq代碼如下:
(0) 這時候,中斷仍然是關閉的,因此不會有來自本CPU的并發(fā),使用raw spin lock就防止其他CPU上對該IRQ的中斷描述符的訪問。針對該spin lock,我們直觀的感覺是raw_spin_lock和(7)中的raw_spin_unlock是成對的,實際上并不是,handle_irq_event中的代碼是這樣的:
實際上,由于在handle_irq_event中處理action list的耗時還是比較長的,因此處理具體的action list的時候并沒有持有中斷描述符的spin lock。在如果那樣的話,其他CPU在對中斷描述符進行操作的時候需要spin的時間會很長的。 (1)判斷是否需要執(zhí)行下面的action list的處理。這里分成幾種情況: a、該中斷事件已經(jīng)被其他的CPU處理了 b、該中斷被其他的CPU disable了 c、該中斷描述符沒有注冊specific handler。這個比較簡單,如果沒有irqaction,根本沒有必要調(diào)用action list的處理 如果該中斷事件已經(jīng)被其他的CPU處理了,那么我們僅僅是設定pending狀態(tài)(為了委托正在處理的該中斷的那個CPU進行處理),mask_ack_irq該中斷并退出就OK了,并不做具體的處理。另外正在處理該中斷的CPU會檢查pending狀態(tài),并進行處理的。同樣的,如果該中斷被其他的CPU disable了,本就不應該繼續(xù)執(zhí)行該中斷的specific handler,我們也是設定pending狀態(tài),mask and ack中斷就退出了。當其他CPU的代碼離開臨界區(qū),enable 該中斷的時候,軟件會檢測pending狀態(tài)并resend該中斷。 這里的irq_check_poll代碼如下:
IRQS_POLL_INPROGRESS標識了該IRQ正在被polling(上一章有描述),如果沒有被輪詢,那么返回false,進行正常的設定pending標記、mask and ack中斷。如果正在被輪詢,那么需要等待poll結(jié)束。 (2)ack該中斷。對于中斷控制器,一旦被ack,表示該外設的中斷被enable,硬件上已經(jīng)準備好觸發(fā)下一次中斷了。再次觸發(fā)的中斷會被調(diào)度到其他的CPU上?,F(xiàn)在,我們可以再次回到步驟(1)中,為什么這里用mask and ack而不是單純的ack呢?如果單純的ack則意味著后續(xù)中斷還是會觸發(fā),這時候怎么處理?在pending+in progress的情況下,我們要怎么處理?記錄pending的次數(shù),有意義嗎?由于中斷是完全異步的,也有可能pending的標記可能在另外的CPU上已經(jīng)修改為replay的標記,這時候怎么辦?當事情變得復雜的時候,那一定是本來方向就錯了,因此,mask and ack就是最好的策略,我已經(jīng)記錄了pending狀態(tài),不再考慮pending嵌套的情況。 (3)在調(diào)用specific handler處理具體的中斷的時候,由于不持有中斷描述符的spin lock,因此其他CPU上有可能會注銷其specific handler,因此do while循環(huán)之后,desc->action有可能是NULL,如果是這樣,那么mask irq,然后退出就OK了 (4)如果中斷描述符處于pending狀態(tài),那么一定是其他CPU上又觸發(fā)了該interrupt source的中斷,并設定了pending狀態(tài),“委托”本CPU進行處理,這時候,需要把之前mask住的中斷進行unmask的操作。一旦unmask了該interrupt source,后續(xù)的中斷可以繼續(xù)觸發(fā),由其他的CPU處理(仍然是設定中斷描述符的pending狀態(tài),委托當前正在處理該中斷請求的那個CPU進行處理)。 (5)處理該中斷請求事件
(6)只要有pending標記,就說明該中斷還在pending狀態(tài),需要繼續(xù)處理。當然,如果有其他的CPU disable了該interrupt source,那么本次中斷結(jié)束處理。
2、電平觸發(fā)的handler 使用handle_level_irq這個handler的硬件中斷系統(tǒng)行為如下: 我們以高電平觸發(fā)為例。當interrupt controller檢測到了高電平信號,并通過中斷的signal向CPU觸發(fā)中斷。這時候,對中斷控制器進行ack并不能改變interrupt request signal上的電平狀態(tài),一直要等到執(zhí)行具體的中斷服務程序(specific handler),對外設進行ack的時候,電平信號才會恢復成低電平。在對外設ack之前,中斷狀態(tài)一直是pending的,如果沒有mask中斷,那么中斷控制器就會assert CPU。 handle_level_irq的代碼如下:
(1)考慮CPU<------>interrupt controller<------>device這樣的連接方式中,我們認為high level handler主要是和interrupt controller交互,而specific handler(request_irq注冊的那個)是和device進行交互。Level類型的中斷的特點就是只要外設interrupt request line的電平狀態(tài)是有效狀態(tài),對于interrupt controller,該外設的interrupt總是active的。由于外設檢測到了事件(比如數(shù)據(jù)到來了),因此assert了指定的電平信號,這個電平信號會一直保持,直到軟件清除了外設的狀態(tài)寄存器。但是,high level irq event handler這個層面只能操作Interrupt controller,不能操作具體外設的寄存器(那應該屬于具體外設的specific interrupt handler處理內(nèi)容,該handler會掛入中斷描述符中的IRQ action list)。直到在具體的中斷服務程序(specific handler中)操作具體外設的寄存器,才能讓這個asserted電平信號消息。 正是因為level trigger的這個特點,因此,在high level handler中首先mask并ack該IRQ。這一點和邊緣觸發(fā)的high level handler有顯著的不同,在handle_edge_irq中,我們僅僅是ack了中斷,并沒有mask,因為邊緣觸發(fā)的中斷稍縱即逝,一旦mask了該中斷,容易造成中斷丟失。而對于電平中斷,我們不得不mask住該中斷,如果不mask住,只要CPU ack中斷,中斷控制器將持續(xù)的assert CPU中斷(因為有效電平狀態(tài)一直保持)。如果我們mask住該中斷,中斷控制器將不再轉(zhuǎn)發(fā)該interrupt source來的中斷,因此,所有的CPU都不會感知到該中斷,直到軟件unmask。這里的ack是針對interrupt controller的ack,本身ack就是為了clear interrupt controller對該IRQ的狀態(tài)寄存器,不過由于外部的電平仍然是有效信號,其實未必能清除interrupt controller的中斷狀態(tài),不過這是和中斷控制器硬件實現(xiàn)相關的。 (2)對于電平觸發(fā)的high level handler,我們一開始就mask并ack了中斷,因此后續(xù)specific handler因該是串行化執(zhí)行的,為何要判斷in progress標記呢?不要忘記spurious interrupt,那里會直接調(diào)用handler來處理spurious interrupt。 (3)這里有兩個場景 a、沒有注冊specific handler。如果沒有注冊handler,那么保持mask并設定pending標記(這個pending標記有什么作用還沒有想明白)。 b、該中斷被其他的CPU disable了。如果該中斷被其他的CPU disable了,本就不應該繼續(xù)執(zhí)行該中斷的specific handler,我們也是設定pending狀態(tài),mask and ack中斷就退出了。當其他CPU的代碼離開臨界區(qū),enable 該中斷的時候,軟件會檢測pending狀態(tài)并resend該中斷。 (4)為何是有條件的unmask該IRQ?正常的話當然是umask就OK了,不過有些threaded interrupt(這個概念在下一份文檔中描述)要求是one shot的(首次中斷,specific handler中開了一槍,wakeup了irq handler thread,如果允許中斷嵌套,那么在specific handler會多次開槍,這也就不是one shot了,有些IRQ的handler thread要求是one shot,也就是不能嵌套specific handler)。
3、支持EOI的handler TODO 原創(chuàng)文章,轉(zhuǎn)發(fā)請注明出處。蝸窩科技。http://www./linux_kenrel/High_level_irq_event_handler.html 標簽: 中斷處理 評論:
heziq
2015-03-23 10:19 @linuxer:
請教幾個問題: 1.有沒有同時支持上升沿和下降沿的中斷控制器?當然我覺得不可能有同時支持高電平和低電平出發(fā)的中斷控制器。 2.gpio type 中斷,如果是上升沿中斷,是不是要使用下拉電阻或者根本不使用上下拉?如果使用了上拉電阻會怎么樣? 3.gpio type 中斷,如果是高電平,我覺得肯定要使用下拉電阻,將電平鉗制在低電平。 3.gpio type 中斷,如果是下降沿,是不是要使用上拉電阻,或者不使用。如果使用了下拉電阻會怎么樣? 4.gpio type 中斷,如果是低電平,我覺得肯定要使用上拉電阻,將電平鉗制在高電平。 5.如果gpio中斷內(nèi)部使用了上拉電阻,如果外部在使用上拉電阻,會出現(xiàn)什么副作用嗎。我覺得有,兩個上拉電源之間會互相影響。 5.如果gpio中斷內(nèi)部使用了下拉電阻,如果外部在使用下拉電阻,會使pin腳的輸入電阻變低,有可能高電平信號拉不起來。 6.如果外設使用邊沿觸發(fā)。比如上升沿,那么它的高電平維持時間有要求嗎,由高電平變低電平,是外設自己拉低的?還是interrupt controler控制? 這都是我在工作中碰到的疑問。有些設置不好,會造成中斷觸發(fā)失敗,有些會造成功耗過大。在這里想和大家交流一下。
RobinHsiang
2015-03-26 17:29 @linuxer:一般所說GPIO導致漏電,是什么導致的?是比如GPIO設置,或者類似中斷類型GPIO錯誤的上下拉導致的嗎?
而漏電的方向是從CPU漏到device還是反過來漏?這個主要看電源域嗎? 一般怎么樣去查證項目中有沒有GPIO上面的漏電呢?
linuxer
2015-03-28 22:22 @RobinHsiang:多謝你的問題,讓我仔細思考了一番(好的問題總是有這樣的特性),因此延遲到今天才回復。
一般而言,漏電(leakage current)是一個芯片的DC參數(shù)之一,例如Iozl和Iozh這兩個參數(shù),分別表示引腳處于高阻(High-Impedance)狀態(tài)時,外加高電平和低電平的電流值。由于是高阻狀態(tài),因此這時候的leakage current應該是很小的(例如1uA)。當然,我想你這里說的不是這種漏電。 我們調(diào)試嵌入式設備總是從功能開始,然后性能,特別是功耗,例如待機或者關機電流,我們都是希望能夠滿足功能的情況下越小越好。當大刀闊斧的針對各個HW block的的檢查過后,最后往往會糾纏在GPIO狀態(tài)的調(diào)整上,正確的GPIO設定往往能節(jié)省幾個毫安的電流(例如如果一個GPIO的狀態(tài)的錯誤設定可能導致0.1mA的電流,那么精細的調(diào)整10個GPIO可以節(jié)省1個mA) 具體電流是source(用你的描述就是從CPU漏到device)還是sink(從device漏到CPU)是和實際的電路連接、cpu pin的特性以及外設芯片引腳的特性相關。例如CPU的一個GPIO是tri state,假設在CPU處于suspend的時候,將該pin設定為high-impedance狀態(tài),如果對端連接的是外設芯片的enable引腳(低電平有效),為了穩(wěn)定的電路狀態(tài),可能需要連接一個上拉電阻,確保外設芯片處于disable狀態(tài),以便節(jié)省功耗。如果CPU處于suspend的時候,將該pin設定為低電平,那么上拉電阻上將有一個不小的電流消耗(假設上拉到3V,上拉電阻是10k,那么CPU在該GPIO上的sink current大約要0.3mA)。如果調(diào)整輸出成高電平,也不會有這個sink current。 具體的電路形形色色,這里無法每一個都描述了。
Rocky
2015-03-18 17:23 a、沒有注冊specific handler。如果沒有注冊handler,那么保持mask并設定pending標記(這個pending標記有什么作用還沒有想明白)。
@linuxer 應該沒有特別的作用,就是代碼簡潔吧?!要不是為了mark一下IRQS_PENDING,表明此中斷曾經(jīng)來過?? if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {-----(3) if(desc->action)//啰嗦吧?! desc->istate |= IRQS_PENDING; goto out_unlock; } ps:寫的真的挺好的,看第二遍就理解很清楚了!
linuxer
2015-03-23 23:21 @Rocky:多謝!有機會的話可以考慮出中斷子系統(tǒng)version 2,這次寫的很多文檔有些自己也沒有搞明白,因此很難讓讀者明白。有些自己明白,寫出來又不是那么明白??傊@次的中斷系統(tǒng)的文檔就當是愛因斯坦的第一個小板凳吧,雖然粗糙,但是有些板凳的形狀,需要后續(xù)不斷的打磨。
linuxer
2014-08-29 19:33 補充兩句,實際上這份文檔我是寫不下去了,我準備從具體的中斷控制器驅(qū)動開始,把各種中斷控制器的代碼理清楚的話,在回頭review這份文檔,也許這份文檔也是注定要打上“廢棄”的標簽
linuxer
2014-09-01 12:18 @forion:我寫的也很累啊,哈哈
這種抽象層的東西就是理解起來比較困難,因此實際的系統(tǒng)是千奇百怪的,因此,要要足夠的底層知識的累積才可以悟到上層邏輯的精妙。
linuxer 2014-09-01 18:21 @linuxer:因此實際的系統(tǒng)是千奇百怪的--->因為實際的系統(tǒng)是千奇百怪的
------------------------------- 這里沒有精確的表達我的意思,本來我想說的是:目前我還不掌握足夠的底層知識,需要積累到一定程度才能領會上層邏輯的精妙。因此,我準備先潛心研究一下具體的中斷控制器再回頭看看怎么修改這份文檔。目前考慮先看看ARM+GIC系統(tǒng),X86+Multi APIC系統(tǒng)和PowerPC+MPIC系統(tǒng) |
|
|