中斷一般包括中斷產(chǎn)生設(shè)備和中斷處理設(shè)備。中斷控制器負(fù)責(zé)處理中斷,每一個(gè)中斷都有對(duì)應(yīng)的中斷號(hào)及觸發(fā)條件。中斷產(chǎn)生設(shè)備可能有多個(gè)中斷源,有時(shí)多個(gè)中斷源對(duì)應(yīng)中斷控制器中的一個(gè)中斷,這種情況中斷產(chǎn)生設(shè)備的中斷源稱之為中斷控制器中對(duì)應(yīng)中斷的子中斷。一般情況中斷產(chǎn)生設(shè)備數(shù)量要多于中斷控制器,多個(gè)中斷產(chǎn)生設(shè)備的中斷都由一個(gè)中斷控制器處理,這種多對(duì)一的關(guān)系也很像一個(gè)樹形結(jié)構(gòu),所以在設(shè)備樹中,中斷也被描述成樹,叫中斷樹。以下表述的時(shí)候?yàn)榱嗣鞔_是在說(shuō)中斷樹,在父節(jié)點(diǎn)和子節(jié)點(diǎn)前邊我們都加上“中斷”二字,是為了防止和設(shè)備樹的父節(jié)點(diǎn)、子節(jié)點(diǎn)混淆(雖然大部分情況設(shè)備樹的父子關(guān)系就是中斷樹的父子關(guān)系,但是因?yàn)榇嬖谔乩晕覀冞€是強(qiáng)調(diào)是中斷父子關(guān)系)。
中斷產(chǎn)生設(shè)備用interrupts屬性描述中斷源(interrupt specifier),因?yàn)椴煌?a href="http://www.wenjunhu.com/v/tag/1751/" target="_blank">硬件描述中斷源需要的數(shù)據(jù)量不同,所以interrupts屬性的類型也是。為了明確表示一個(gè)中斷由幾個(gè)u32表示,又引入了#interrupt-cells屬性,#interrupt-cells屬性的類型是u32,假如一個(gè)中斷源需要2個(gè)u32表示(一個(gè)表示中斷號(hào),另一個(gè)表示中斷類型),那么#interrupt-cells就設(shè)置成2。有些情況下,設(shè)備樹的父節(jié)點(diǎn)不是中斷的父節(jié)點(diǎn)(主要是中斷控制器一般不是父節(jié)點(diǎn)),為此引入了interrupt-parent屬性,該屬性的類型是,用來(lái)引用中斷父節(jié)點(diǎn)(我們前邊說(shuō)過(guò),一般用父節(jié)點(diǎn)的標(biāo)簽,這個(gè)地方說(shuō)中斷父節(jié)點(diǎn)而不是中斷控制器是有原因的)。如果設(shè)備樹的父節(jié)點(diǎn)就是中斷父節(jié)點(diǎn),那么可以不用設(shè)置interrupt-parent屬性。interrupts屬性和interrupt-parent屬性都是中斷產(chǎn)生設(shè)備節(jié)點(diǎn)的屬性,但是#interrupt-cells屬性不是,#interrupt-cells屬性是中斷控制器節(jié)點(diǎn)以及interrupt nexus節(jié)點(diǎn)的屬性,這兩類節(jié)點(diǎn)都可能是中斷父節(jié)點(diǎn)。
中斷控制器節(jié)點(diǎn)用interrupt-controller屬性表示自己是中斷控制器,這個(gè)屬性的類型是空,不用設(shè)置值,只要存在這個(gè)節(jié)點(diǎn)就表示該節(jié)點(diǎn)是中斷控制器。除了這個(gè)屬性外,中斷控制器節(jié)點(diǎn)還有#interrupt-cells屬性,用來(lái)表示該中斷控制器直接管理下的interrupt domain(后邊我們會(huì)講中斷控制器的中斷子節(jié)點(diǎn)interrupt nexus節(jié)點(diǎn)有單獨(dú)的interrupt domain)用幾個(gè)u32表示一個(gè)中斷源(interrupt specifier)。中斷控制器節(jié)點(diǎn)就包括interrupt-controller和#interrupt-cells兩個(gè)關(guān)于中斷的屬性。中斷控制器的#address-cells屬性和中斷映射有關(guān)系,但是該屬性不是為中斷設(shè)計(jì)的,中斷映射只是用到了這個(gè)屬性而已。
前邊說(shuō)中斷控制器中的一個(gè)中斷可能對(duì)應(yīng)中斷產(chǎn)生設(shè)備中的多個(gè)中斷源,那這種對(duì)應(yīng)關(guān)系用什么描述呢?我們還說(shuō)過(guò)#interrupt-celll屬性不僅是中斷控制器節(jié)點(diǎn)的屬性,還是interrupt nexus節(jié)點(diǎn)的屬性,這個(gè)interrupt nexus節(jié)點(diǎn)就是描述中斷映射關(guān)系的,該節(jié)點(diǎn)通過(guò)interrupt-map,interrupt-map-mask屬性描述中斷映射關(guān)系。interrupt-map屬性是類型的,每個(gè)元素表示一個(gè)中斷映射關(guān)系(注意是一個(gè)"中斷映射關(guān)系",不是"一個(gè)中斷"映射關(guān)系),從前向后包括:中斷子設(shè)備地址,中斷子設(shè)備中斷源(interrupt specifier),中斷父設(shè)備,中斷父設(shè)備地址,中斷父設(shè)備中斷源(interrupt specifier)五部分。中斷子設(shè)備地址具體由幾個(gè)u32組成是由中斷子設(shè)備所在總線(不是中斷父設(shè)備)的#address-cells屬性決定的,這個(gè)地方為什么用中斷設(shè)備地址而不用中斷設(shè)備的phandle,是有原因的,因?yàn)橹袛嘣O(shè)備會(huì)用interrupt-parrent屬性指向中斷父節(jié)點(diǎn),所以中斷子設(shè)備是可以確定的,不需要說(shuō)明。還因?yàn)橹袛嘧釉O(shè)備地址可以做與運(yùn)算,通過(guò)interrupt-map-mask屬性就可以實(shí)現(xiàn)多對(duì)一的映射。中斷子設(shè)備中斷源(interrupt specifier)由幾個(gè)u32組成是由該interrupt nexus節(jié)點(diǎn)下的#interrupt-cell決定的。中斷父設(shè)備是一個(gè)指向中斷父設(shè)備的屬性,一般情況下是中斷控制器,但是按照中斷樹的邏輯,也可能是更高一級(jí)的interrupt nexus節(jié)點(diǎn)。中斷父設(shè)備地址具體由幾個(gè)u32組成是由中斷父設(shè)備節(jié)點(diǎn)下的#address-cells屬性決定的(注意,不是中斷父設(shè)備所在總線的#address-cells屬性)。中斷父設(shè)備中斷源(interrupt specifier)由幾個(gè)u32組成是由中斷父設(shè)備的#interrupt-cells屬性決定的。
還記得前邊說(shuō)過(guò)中斷設(shè)備的中斷源和中斷控制器的中斷源可能是多對(duì)一的關(guān)系,如果每個(gè)子中斷都用interrupt-map中的一行表示,那么interrupt-map屬性將非常大。為了讓多個(gè)子中斷共享映射關(guān)系,引入了interrupt-map-mask屬性,該屬性的類型也是,包含中斷子設(shè)備地址和中斷子設(shè)備中斷源的bit mask,給定一個(gè)子中斷源,那么首先和interrupt-map-mask做與運(yùn)算,運(yùn)算結(jié)果再通過(guò)interrupt-map屬性查找對(duì)應(yīng)的中斷父設(shè)備中斷源。這就是我們前邊為什么說(shuō)interrupt-map屬性的一行是一個(gè)“中斷映射關(guān)系”,而不是“一個(gè)中斷”映射關(guān)系的原因。
我們?cè)賮?lái)復(fù)習(xí)一下,整個(gè)中斷樹的最底層是中斷產(chǎn)生設(shè)備(也可能是從interrupt nexus節(jié)點(diǎn)),中斷產(chǎn)生設(shè)備用interrupts屬性描述他能產(chǎn)生的中斷。因?yàn)樗闹袛喔冈O(shè)備可能和設(shè)備樹的父設(shè)備不同,那么用interrupt-parent屬性指向他的中斷父設(shè)備。他的中斷父設(shè)備可能是中斷控制器(如果中斷產(chǎn)生設(shè)備的中斷和中斷控制器的中斷是一一對(duì)應(yīng)的,或者最底層是interrupt nexus節(jié)點(diǎn)),也可能是interrupt nexus節(jié)點(diǎn)(如果最底層是中斷產(chǎn)生設(shè)備,且需要映射)。interrupt nexus節(jié)點(diǎn)及他的所有直接子節(jié)點(diǎn)構(gòu)成了一個(gè)interrupt domain,在該interrupt domain下中斷源怎樣表示由#interrupt-cells屬性決定,如何由中斷子設(shè)備中斷源找到中斷父設(shè)備中斷源由interrupt-map和interrupt-map-mask屬性決定。interrupt nexus的父節(jié)點(diǎn)可能還是一個(gè)interrupt nexus父節(jié)點(diǎn),也可能是一個(gè)中斷控制器,當(dāng)向上找到最后一個(gè)中斷控制器,并且該中斷控制器再也沒有中斷父設(shè)備時(shí),整個(gè)中斷樹就遍歷完成了。中斷控制器用interrupt-controller屬性表示自己是中斷控制器,并且用#interrupt-cells屬性表示他所直接管理的interrupt domain用幾個(gè)u32表示一個(gè)中斷源。根據(jù)中斷樹的特性,一個(gè)設(shè)備樹中是有可能有多個(gè)中斷樹的。
以上是中斷在設(shè)備樹中如何描述的規(guī)則,聽起來(lái)是挺復(fù)雜的,但只要理解了就很簡(jiǎn)單,為了幫助理解我們舉一個(gè)實(shí)際的例子。為了突出中斷部分,我們做了簡(jiǎn)化。
/ {
?? ?model = "Marvell Armada 375 family SoC";
?? ?compatible = "marvell,armada375";
?? ?soc {
?? ??? ?#address-cells = <2>;
?? ??? ?#size-cells = <1>;
?? ??? ?interrupt-parent = <&gic>;
?? ??? ?internal-regs {
?? ??? ??? ?compatible = "simple-bus";
?? ??? ??? ?#address-cells = <1>;
?? ??? ??? ?#size-cells = <1>;
?? ??? ??? ?timer@c600 {
?? ??? ??? ??? ?compatible = "arm,cortex-a9-twd-timer";
?? ??? ??? ??? ?reg = <0xc600 0x20>;
?? ??? ??? ??? ?interrupts = ;
?? ??? ??? ??? ?clocks = <&coreclk 2>;
?? ??? ??? ?};
?? ??? ??? ?gic: interrupt-controller@d000 {
?? ??? ??? ??? ?compatible = "arm,cortex-a9-gic";
?? ??? ??? ??? ?#interrupt-cells = <3>;
?? ??? ??? ??? ?#address-cells = <0>;
?? ??? ??? ??? ?interrupt-controller;
?? ??? ??? ??? ?reg = <0xd000 0x1000>,
?? ??? ??? ??? ?????? <0xc100 0x100>;
?? ??? ??? ?};
?? ??? ?}
?? ??? ?pcie-controller {
?? ??? ??? ?compatible = "marvell,armada-370-pcie";
?? ??? ??? ?#address-cells = <3>;
?? ??? ??? ?#size-cells = <2>;
?? ??? ??? ?pcie@1,0 {
?? ??? ??? ??? ?#address-cells = <3>;
?? ??? ??? ??? ?#size-cells = <2>;
?? ??? ??? ??? ?#interrupt-cells = <1>;
?? ??? ??? ??? ?interrupt-map-mask = <0 0 0 0>;
?? ??? ??? ??? ?interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
?? ??? ??? ?};
?? ??? ?};
}
首先我們看到timer@c600這個(gè)設(shè)備節(jié)點(diǎn)下定義了interrupts屬性,這說(shuō)明該設(shè)備可以產(chǎn)生中斷,但是這個(gè)屬性下描述了幾個(gè)中斷我們是看不出來(lái)的(如果有經(jīng)驗(yàn)了,我們能猜出只是一個(gè)中斷,現(xiàn)在我們按照規(guī)則確認(rèn))。因?yàn)樵摴?jié)點(diǎn)沒有interrupt-parent屬性,那么認(rèn)為設(shè)備樹的父節(jié)點(diǎn)internal-regs就是中斷父節(jié)點(diǎn),在internal-regs父節(jié)點(diǎn)下還是沒有interrupt-parent屬性,那么還是繼續(xù)找設(shè)備樹父節(jié)點(diǎn),找到了soc,在該節(jié)點(diǎn)下邊有interrupt-parent屬性。該屬性引用的標(biāo)簽為gic,搜索整個(gè)設(shè)備樹,interrupt-controller@d000的標(biāo)簽為gic。gic節(jié)點(diǎn)下有interrupt-controller屬性,說(shuō)明他是一個(gè)中斷控制器。gic節(jié)點(diǎn)還有屬性#interrupt-cells = <3>,說(shuō)明在該控制器的interrupt domain下,中斷源(interrupt specifier)用3個(gè)u32表示,我們?cè)倏磘imer@c600下的interrupts屬性也確實(shí)由3個(gè)u32組成(可以參考GIC的規(guī)范,第一個(gè)u32表示中斷類型,第二個(gè)是中斷號(hào),第三個(gè)是中斷觸發(fā)條件)。這個(gè)例子說(shuō)明如果中斷產(chǎn)生設(shè)備的中斷源和中斷控制器的中斷源是一一對(duì)應(yīng)的,那么可以不需要interrupt nexus節(jié)點(diǎn)及相關(guān)的屬性來(lái)表示中斷映射。
再看pcie@1,0這個(gè)節(jié)點(diǎn),有#interrupt-cells屬性,但是沒有interrupt-controller屬性,這說(shuō)明他是一個(gè)interrupt nexus節(jié)點(diǎn)。該節(jié)點(diǎn)的#interrupt-cells屬性為1,說(shuō)明該interrupt nexus節(jié)點(diǎn)管轄下的中斷源用1個(gè)u32表示就可以了。在pcie@1,0節(jié)點(diǎn)下邊沒有子節(jié)點(diǎn),且也沒有節(jié)點(diǎn)的interrupt-parent屬性指向pcie@1,0節(jié)點(diǎn),所以從設(shè)備樹上看不到該interrupt domain下的中斷產(chǎn)生設(shè)備,可能的原因是這些中斷產(chǎn)生設(shè)備軟件可以動(dòng)態(tài)識(shí)別所以不需要設(shè)備樹描述。因?yàn)閕nterrupt-map-mask屬性是由中斷產(chǎn)生設(shè)備的地址和中斷源(interrupt specifier)組成,且中斷源用1個(gè)u32表示,那么可以推測(cè)中斷產(chǎn)生設(shè)備地址由3個(gè)u32組成。這里需要注意的是pcie@1,0節(jié)點(diǎn)的#address-cells屬性為3,是說(shuō)該總線下邊的設(shè)備地址用3個(gè)u32表示,但并不代表中斷產(chǎn)生設(shè)備的設(shè)備地址也一定3個(gè)u32表示,此處不能說(shuō)是巧合,但是我們要清楚中斷產(chǎn)生設(shè)備的地址由幾個(gè)u32組成是由該設(shè)備所在總線決定的,對(duì)于pcie總線也確實(shí)是3,但是其他總線可能存在其他種的情況?,F(xiàn)在我們來(lái)分析interrupt-map屬性,前三個(gè)數(shù)字是中斷設(shè)備地址,第四個(gè)數(shù)字是中斷設(shè)備的中斷源。因?yàn)閕nterrupt-map-mask是全0,這樣不管與什么數(shù)字做與運(yùn)算結(jié)果都是0,interrupt-map屬性的前4個(gè)數(shù)字也都是0,這說(shuō)明在pcie@1,0下邊所有的中斷映射到中斷父節(jié)點(diǎn)的中斷都是一個(gè)中斷。接著是指向gic的,因?yàn)間ic節(jié)點(diǎn)下#address-cells屬性為0,所以后邊不需要描述中斷父設(shè)備的地址了,后邊3個(gè)數(shù)字都是表示中斷父設(shè)備中斷源的。一句話描述就是pcie@1,0下的所有中斷都映射到gic,GIC_SPI類型的第29號(hào)中斷,觸發(fā)類型為高電平觸發(fā)。這個(gè)例子說(shuō)明在中斷樹的最下邊可以是interrupt nexus節(jié)點(diǎn)。
以上例子中斷樹的根是gic,gic下邊有兩個(gè)孩子,一個(gè)是中斷設(shè)備timer@c600,一個(gè)是interrupt nexus節(jié)點(diǎn)pcie@1,0。gic直接管轄的interrupt domain用3個(gè)u32表示中斷源,timer@c600在這個(gè)interrupt domain下。pcie@1,0下定義了一個(gè)新的interrupt domain,在該interrupt domain下,中斷源用1個(gè)u32表示,pcie@1,0用interrupt-map和interrupt-map-mask屬性將下邊所有設(shè)備的中斷映射到一個(gè)gic下邊的中斷上。
?
評(píng)論
查看更多