Linux裝置樹 四 中斷

2022-06-18 11:06:11 字數 4917 閱讀 8662

中斷一般包括中斷產生裝置和中斷處理裝置。中斷控制器負責處理中斷,每乙個中斷都有對應的中斷號及觸發條件。中斷產生裝置可能有多個中斷源,有時多個中斷源對應中斷控制器中的乙個中斷,這種情況中斷產生裝置的中斷源稱之為中斷控制器中對應中斷的子中斷。一般情況中斷產生裝置數量要多於中斷控制器,多個中斷產生裝置的中斷都由乙個中斷控制器處理,這種多對一的關係也很像乙個樹形結構,所以在裝置樹中,中斷也被描述成樹,叫中斷樹。以下表述的時候為了明確是在說中斷樹,在父節點和子節點前邊我們都加上「中斷」二字,是為了防止和裝置樹的父節點、子節點混淆(雖然大部分情況裝置樹的父子關係就是中斷樹的父子關係,但是因為存在特例,所以我們還是強調是中斷父子關係)。

中斷產生裝置用interrupts屬性描述中斷源(interrupt specifier),因為不同的硬體描述中斷源需要的資料量不同,所以interrupts屬性的型別也是。為了明確表示乙個中斷由幾個u32表示,又引入了#interrupt-cells屬性,#interrupt-cells屬性的型別是u32,假如乙個中斷源需要2個u32表示(乙個表示中斷號,另乙個表示中斷型別),那麼#interrupt-cells就設定成2。有些情況下,裝置樹的父節點不是中斷的父節點(主要是中斷控制器一般不是父節點),為此引入了interrupt-parent屬性,該屬性的型別是,用來引用中斷父節點(我們前邊說過,一般用父節點的標籤,這個地方說中斷父節點而不是中斷控制器是有原因的)。如果裝置樹的父節點就是中斷父節點,那麼可以不用設定interrupt-parent屬性。interrupts屬性和interrupt-parent屬性都是中斷產生裝置節點的屬性,但是#interrupt-cells屬性不是,#interrupt-cells屬性是中斷控制器節點以及interrupt nexus節點的屬性,這兩類節點都可能是中斷父節點。

中斷控制器節點用interrupt-controller屬性表示自己是中斷控制器,這個屬性的型別是空,不用設定值,只要存在這個節點就表示該節點是中斷控制器。除了這個屬性外,中斷控制器節點還有#interrupt-cells屬性,用來表示該中斷控制器直接管理下的interrupt domain(後邊我們會講中斷控制器的中斷子節點interrupt nexus節點有單獨的interrupt domain)用幾個u32表示乙個中斷源(interrupt specifier)。中斷控制器節點就包括interrupt-controller和#interrupt-cells兩個關於中斷的屬性。中斷控制器的#address-cells屬性和中斷對映有關係,但是該屬性不是為中斷設計的,中斷對映只是用到了這個屬性而已。

前邊說中斷控制器中的乙個中斷可能對應中斷產生裝置中的多個中斷源,那這種對應關係用什麼描述呢?我們還說過#interrupt-celll屬性不僅是中斷控制器節點的屬性,還是interrupt nexus節點的屬性,這個interrupt nexus節點就是描述中斷對映關係的,該節點通過interrupt-map,interrupt-map-mask屬性描述中斷對映關係。interrupt-map屬性是型別的,每個元素表示乙個中斷對映關係(注意是乙個"中斷對映關係",不是"乙個中斷"對映關係),從前向後包括:中斷子裝置位址,中斷子裝置中斷源(interrupt specifier),中斷父裝置,中斷父裝置位址,中斷父裝置中斷源(interrupt specifier)五部分。中斷子裝置位址具體由幾個u32組成是由中斷子裝置所在匯流排(不是中斷父裝置)的#address-cells屬性決定的,這個地方為什麼用中斷裝置位址而不用中斷裝置的phandle,是有原因的,因為中斷裝置會用interrupt-parrent屬性指向中斷父節點,所以中斷子裝置是可以確定的,不需要說明。還因為中斷子裝置位址可以做與運算,通過interrupt-map-mask屬性就可以實現多對一的對映。中斷子裝置中斷源(interrupt specifier)由幾個u32組成是由該interrupt nexus節點下的#interrupt-cell決定的。中斷父裝置是乙個指向中斷父裝置的屬性,一般情況下是中斷控制器,但是按照中斷樹的邏輯,也可能是更高一級的interrupt nexus節點。中斷父裝置位址具體由幾個u32組成是由中斷父裝置節點下的#address-cells屬性決定的(注意,不是中斷父裝置所在匯流排的#address-cells屬性)。中斷父裝置中斷源(interrupt specifier)由幾個u32組成是由中斷父裝置的#interrupt-cells屬性決定的。

還記得前邊說過中斷裝置的中斷源和中斷控制器的中斷源可能是多對一的關係,如果每個子中斷都用interrupt-map中的一行表示,那麼interrupt-map屬性將非常大。為了讓多個子中斷共享對映關係,引入了interrupt-map-mask屬性,該屬性的型別也是,包含中斷子裝置位址和中斷子裝置中斷源的bit mask,給定乙個子中斷源,那麼首先和interrupt-map-mask做與運算,運算結果再通過interrupt-map屬性查詢對應的中斷父裝置中斷源。這就是我們前邊為什麼說interrupt-map屬性的一行是乙個「中斷對映關係」,而不是「乙個中斷」對映關係的原因。

我們再來複習一下,整個中斷樹的最底層是中斷產生裝置(也可能是從interrupt nexus節點),中斷產生裝置用interrupts屬性描述他能產生的中斷。因為他的中斷父裝置可能和裝置樹的父裝置不同,那麼用interrupt-parent屬性指向他的中斷父裝置。他的中斷父裝置可能是中斷控制器(如果中斷產生裝置的中斷和中斷控制器的中斷是一一對應的,或者最底層是interrupt nexus節點),也可能是interrupt nexus節點(如果最底層是中斷產生裝置,且需要對映)。interrupt nexus節點及他的所有直接子節點構成了乙個interrupt domain,在該interrupt domain下中斷源怎樣表示由#interrupt-cells屬性決定,如何由中斷子裝置中斷源找到中斷父裝置中斷源由interrupt-map和interrupt-map-mask屬性決定。interrupt nexus的父節點可能還是乙個interrupt nexus父節點,也可能是乙個中斷控制器,當向上找到最後乙個中斷控制器,並且該中斷控制器再也沒有中斷父裝置時,整個中斷樹就遍歷完成了。中斷控制器用interrupt-controller屬性表示自己是中斷控制器,並且用#interrupt-cells屬性表示他所直接管理的interrupt domain用幾個u32表示乙個中斷源。根據中斷樹的特性,乙個裝置樹中是有可能有多個中斷樹的。

以上是中斷在裝置樹中如何描述的規則,聽起來是挺複雜的,但只要理解了就很簡單,為了幫助理解我們舉乙個實際的例子。為了突出中斷部分,我們做了簡化。

/;

gic: interrupt-controller@d000 ;

}pcie-controller ;

};}

首先我們看到timer@c600這個裝置節點下定義了interrupts屬性,這說明該裝置可以產生中斷,但是這個屬性下描述了幾個中斷我們是看不出來的(如果有經驗了,我們能猜出只是乙個中斷,現在我們按照規則確認)。因為該節點沒有interrupt-parent屬性,那麼認為裝置樹的父節點internal-regs就是中斷父節點,在internal-regs父節點下還是沒有interrupt-parent屬性,那麼還是繼續找裝置樹父節點,找到了soc,在該節點下邊有interrupt-parent屬性。該屬性引用的標籤為gic,搜尋整個裝置樹,interrupt-controller@d000的標籤為gic。gic節點下有interrupt-controller屬性,說明他是乙個中斷控制器。gic節點還有屬性#interrupt-cells = <3>,說明在該控制器的interrupt domain下,中斷源(interrupt specifier)用3個u32表示,我們再看timer@c600下的interrupts屬性也確實由3個u32組成(可以參考gic的規範,第乙個u32表示中斷型別,第二個是中斷號,第三個是中斷觸發條件)。這個例子說明如果中斷產生裝置的中斷源和中斷控制器的中斷源是一一對應的,那麼可以不需要interrupt nexus節點及相關的屬性來表示中斷對映。

再看pcie@1,0這個節點,有#interrupt-cells屬性,但是沒有interrupt-controller屬性,這說明他是乙個interrupt nexus節點。該節點的#interrupt-cells屬性為1,說明該interrupt nexus節點管轄下的中斷源用1個u32表示就可以了。在pcie@1,0節點下邊沒有子節點,且也沒有節點的interrupt-parent屬性指向pcie@1,0節點,所以從裝置樹上看不到該interrupt domain下的中斷產生裝置,可能的原因是這些中斷產生裝置軟體可以動態識別所以不需要裝置樹描述。因為interrupt-map-mask屬性是由中斷產生裝置的位址和中斷源(interrupt specifier)組成,且中斷源用1個u32表示,那麼可以推測中斷產生裝置位址由3個u32組成。這裡需要注意的是pcie@1,0節點的#address-cells屬性為3,是說該匯流排下邊的裝置位址用3個u32表示,但並不代表中斷產生裝置的裝置位址也一定3個u32表示,此處不能說是巧合,但是我們要清楚中斷產生裝置的位址由幾個u32組成是由該裝置所在匯流排決定的,對於pcie匯流排也確實是3,但是其他匯流排可能存在其他種的情況。現在我們來分析interrupt-map屬性,前三個數字是中斷裝置位址,第四個數字是中斷裝置的中斷源。因為interrupt-map-mask是全0,這樣不管與什麼數字做與運算結果都是0,interrupt-map屬性的前4個數字也都是0,這說明在pcie@1,0下邊所有的中斷對映到中斷父節點的中斷都是乙個中斷。接著是指向gic的,因為gic節點下#address-cells屬性為0,所以後邊不需要描述中斷父裝置的位址了,後邊3個數字都是表示中斷父裝置中斷源的。一句話描述就是pcie@1,0下的所有中斷都對映到gic,gic_spi型別的第29號中斷,觸發型別為高電平觸發。這個例子說明在中斷樹的最下邊可以是interrupt nexus節點。

以上例子中斷樹的根是gic,gic下邊有兩個孩子,乙個是中斷裝置timer@c600,乙個是interrupt nexus節點pcie@1,0。gic直接管轄的interrupt domain用3個u32表示中斷源,timer@c600在這個interrupt domain下。pcie@1,0下定義了乙個新的interrupt domain,在該interrupt domain下,中斷源用1個u32表示,pcie@1,0用interrupt-map和interrupt-map-mask屬性將下邊所有裝置的中斷對映到乙個gic下邊的中斷上。

(四)中斷系統

好了,將按鍵寫完輸入輸出就都完了,我們來看看微控制器內部那些東西,首先說說中斷。中斷系統是為使cpu具有對外界緊急事件的實時處理能力而設定的。當 處理器cpu正在處理某件事的時候外界發生了緊急事件請求,要求cpu暫停當前的工作,轉而去處理這個緊急事件,處理完以後,再回到原來被中斷的地方,繼續原來的工...

8086學習(四)中斷

為什麼要用io介面?答 四個不匹配 速平格時,就這樣記了,沒法記的。針對這幾個不匹配,用不同的方法,例如設定緩衝以匹配速度,設定電平轉換電路,設定格式轉換電路,設定時序控制電路等 緩衝器與鎖存器各用在什麼地方?很顯然了,緩衝器用於匯流排上,起到緩衝作用,提高匯流排驅動能力 電平匹配 鎖存器具有暫存資...

作業系統筆記(四)中斷

ctime 2020 04 30 13 33 34 0900 1588221214 標籤 空格分隔 技術 作業系統 8086 80386 的中斷向量表並不像arm的中斷向量表放在位址0處,而是位置可變。當建好中斷向量表之後,通過lidt指令,將中斷向量表的位址給idtr暫存器,這樣當cpu發生中斷時...