华南俳烁实业有限公司

考試首頁 | 考試用書 | 培訓(xùn)課程 | 模擬考場 | 考試論壇  
  當(dāng)前位置:操作系統(tǒng) > Linux > 文章內(nèi)容
  

Linux基礎(chǔ)教程:Linux設(shè)備樹(Devicetree)

 [ 2016年2月18日 ] 【

中斷

中斷一般包括中斷產(chǎn)生設(shè)備和中斷處理設(shè)備。中斷控制器負責(zé)處理中斷,每一個中斷都有對應(yīng)的中斷號及觸發(fā)條件。中斷產(chǎn)生設(shè)備可能有多個中斷源,有時多個中斷源對應(yīng)中斷控制器中的一個中斷,這種情況中斷產(chǎn)生設(shè)備的中斷源稱之為中斷控制器中對應(yīng)中斷的子中斷。一般情況中斷產(chǎn)生設(shè)備數(shù)量要多于中斷控制器,多個中斷產(chǎn)生設(shè)備的中斷都由一個中斷控制器處理,這種多對一的關(guān)系也很像一個樹形結(jié)構(gòu),所以在設(shè)備樹中,中斷也被描述成樹,叫中斷樹。以下表述的時候為了明確是在說中斷樹,在父節(jié)點和子節(jié)點前邊我們都加上“中斷”二字,是為了防止和設(shè)備樹的父節(jié)點、子節(jié)點混淆(雖然大部分情況設(shè)備樹的父子關(guān)系就是中斷樹的父子關(guān)系,但是因為存在特例,所以我們還是強調(diào)是中斷父子關(guān)系)。

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

中斷控制器節(jié)點用interrupt-controller屬性表示自己是中斷控制器,這個屬性的類型是空,不用設(shè)置值,只要存在這個節(jié)點就表示該節(jié)點是中斷控制器。除了這個屬性外,中斷控制器節(jié)點還有#interrupt-cells屬性,用來表示該中斷控制器直接管理下的interrupt domain(后邊我們會講中斷控制器的中斷子節(jié)點interrupt nexus節(jié)點有單獨的interrupt domain)用幾個u32表示一個中斷源(interrupt specifier)。中斷控制器節(jié)點就包括interrupt-controller和#interrupt-cells兩個關(guān)于中斷的屬性。中斷控制器的#address-cells屬性和中斷映射有關(guān)系,但是該屬性不是為中斷設(shè)計的,中斷映射只是用到了這個屬性而已。

前邊說中斷控制器中的一個中斷可能對應(yīng)中斷產(chǎn)生設(shè)備中的多個中斷源,那這種對應(yīng)關(guān)系用什么描述呢?我們還說過#interrupt-celll屬性不僅是中斷控制器節(jié)點的屬性,還是interrupt nexus節(jié)點的屬性,這個interrupt nexus節(jié)點就是描述中斷映射關(guān)系的,該節(jié)點通過interrupt-map,interrupt-map-mask屬性描述中斷映射關(guān)系。 interrupt-map屬性是類型的,每個元素表示一個中斷映射關(guān)系(注意是一個"中斷映射關(guān)系",不是"一個中斷"映射關(guān)系),從前向后包括:中斷子設(shè)備地址,中斷子設(shè)備中斷源(interrupt specifier),中斷父設(shè)備,中斷父設(shè)備地址,中斷父設(shè)備中斷源(interrupt specifier)五部分。中斷子設(shè)備地址具體由幾個u32組成是由中斷子設(shè)備所在總線(不是中斷父設(shè)備)的#address-cells屬性決定的,這個地方為什么用中斷設(shè)備地址而不用中斷設(shè)備的phandle,是有原因的,因為中斷設(shè)備會用interrupt-parrent屬性指向中斷父節(jié)點,所以中斷子設(shè)備是可以確定的,不需要說明。還因為中斷子設(shè)備地址可以做與運算,通過interrupt-map-mask屬性就可以實現(xiàn)多對一的映射。中斷子設(shè)備中斷源(interrupt specifier)由幾個u32組成是由該interrupt nexus節(jié)點下的#interrupt-cell決定的。中斷父設(shè)備是一個指向中斷父設(shè)備的屬性,一般情況下是中斷控制器,但是按照中斷樹的邏輯,也可能是更高一級的interrupt nexus節(jié)點。中斷父設(shè)備地址具體由幾個u32組成是由中斷父設(shè)備節(jié)點下的#address-cells屬性決定的(注意,不是中斷父設(shè)備所在總線的#address-cells屬性)。中斷父設(shè)備中斷源(interrupt specifier)由幾個u32組成是由中斷父設(shè)備的#interrupt-cells屬性決定的。

還記得前邊說過中斷設(shè)備的中斷源和中斷控制器的中斷源可能是多對一的關(guān)系,如果每個子中斷都用interrupt-map中的一行表示,那么 interrupt-map屬性將非常大。為了讓多個子中斷共享映射關(guān)系,引入了interrupt-map-mask屬性,該屬性的類型也是,包含中斷子設(shè)備地址和中斷子設(shè)備中斷源的bit mask,給定一個子中斷源,那么首先和interrupt-map-mask做與運算,運算結(jié)果再通過interrupt-map屬性查找對應(yīng)的中斷父設(shè)備中斷源。這就是我們前邊為什么說interrupt-map屬性的一行是一個“中斷映射關(guān)系”,而不是“一個中斷”映射關(guān)系的原因。

我們再來復(fù)習(xí)一下,整個中斷樹的最底層是中斷產(chǎn)生設(shè)備(也可能是從interrupt nexus節(jié)點),中斷產(chǎn)生設(shè)備用interrupts屬性描述他能產(chǎn)生的中斷。因為他的中斷父設(shè)備可能和設(shè)備樹的父設(shè)備不同,那么用 interrupt-parent屬性指向他的中斷父設(shè)備。他的中斷父設(shè)備可能是中斷控制器(如果中斷產(chǎn)生設(shè)備的中斷和中斷控制器的中斷是一一對應(yīng)的,或者最底層是interrupt nexus節(jié)點),也可能是interrupt nexus節(jié)點(如果最底層是中斷產(chǎn)生設(shè)備,且需要映射)。interrupt nexus節(jié)點及他的所有直接子節(jié)點構(gòu)成了一個interrupt domain,在該interrupt domain下中斷源怎樣表示由#interrupt-cells屬性決定,如何由中斷子設(shè)備中斷源找到中斷父設(shè)備中斷源由interrupt-map和 interrupt-map-mask屬性決定。interrupt nexus的父節(jié)點可能還是一個interrupt nexus父節(jié)點,也可能是一個中斷控制器,當(dāng)向上找到最后一個中斷控制器,并且該中斷控制器再也沒有中斷父設(shè)備時,整個中斷樹就遍歷完成了。中斷控制器用interrupt-controller屬性表示自己是中斷控制器,并且用#interrupt-cells屬性表示他所直接管理的 interrupt domain用幾個u32表示一個中斷源。根據(jù)中斷樹的特性,一個設(shè)備樹中是有可能有多個中斷樹的。

以上是中斷在設(shè)備樹中如何描述的規(guī)則,聽起來是挺復(fù)雜的,但只要理解了就很簡單,為了幫助理解我們舉一個實際的例子。為了突出中斷部分,我們做了簡化。
/ {
    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這個設(shè)備節(jié)點下定義了interrupts屬性,這說明該設(shè)備可以產(chǎn)生中斷,但是這個屬性下描述了幾個中斷我們是看不出來的(如果有經(jīng)驗了,我們能猜出只是一個中斷,現(xiàn)在我們按照規(guī)則確認)。因為該節(jié)點沒有interrupt-parent屬性,那么認為設(shè)備樹的父節(jié)點internal-regs就是中斷父節(jié)點,在internal-regs父節(jié)點下還是沒有interrupt-parent屬性,那么還是繼續(xù)找設(shè)備樹父節(jié)點,找到了soc,在該節(jié)點下邊有interrupt-parent屬性。該屬性引用的標簽為gic,搜索整個設(shè)備樹,interrupt- controller@d000的標簽為gic。gic節(jié)點下有interrupt-controller屬性,說明他是一個中斷控制器。gic節(jié)點還有屬性#interrupt-cells = <3>,說明在該控制器的interrupt domain下,中斷源(interrupt specifier)用3個u32表示,我們再看timer@c600下的interrupts屬性也確實由3個u32組成(可以參考GIC的規(guī)范,第一個u32表示中斷類型,第二個是中斷號,第三個是中斷觸發(fā)條件)。這個例子說明如果中斷產(chǎn)生設(shè)備的中斷源和中斷控制器的中斷源是一一對應(yīng)的,那么可以不需要interrupt nexus節(jié)點及相關(guān)的屬性來表示中斷映射。

再看pcie@1,0這個節(jié)點,有#interrupt-cells屬性,但是沒有interrupt-controller屬性,這說明他是一個 interrupt nexus節(jié)點。該節(jié)點的#interrupt-cells屬性為1,說明該interrupt nexus節(jié)點管轄下的中斷源用1個u32表示就可以了。在pcie@1,0節(jié)點下邊沒有子節(jié)點,且也沒有節(jié)點的interrupt-parent屬性指向pcie@1,0節(jié)點,所以從設(shè)備樹上看不到該interrupt domain下的中斷產(chǎn)生設(shè)備,可能的原因是這些中斷產(chǎn)生設(shè)備軟件可以動態(tài)識別所以不需要設(shè)備樹描述。因為interrupt-map-mask屬性是由中斷產(chǎn)生設(shè)備的地址和中斷源(interrupt specifier)組成,且中斷源用1個u32表示,那么可以推測中斷產(chǎn)生設(shè)備地址由3個u32組成。這里需要注意的是pcie@1,0節(jié)點的#address-cells屬性為3,是說該總線下邊的設(shè)備地址用3個u32表示,但并不代表中斷產(chǎn)生設(shè)備的設(shè)備地址也一定3個u32表示,此處不能說是巧合,但是我們要清楚中斷產(chǎn)生設(shè)備的地址由幾個u32組成是由該設(shè)備所在總線決定的,對于pcie總線也確實是3,但是其他總線可能存在其他種的情況。現(xiàn)在我們來分析interrupt-map屬性,前三個數(shù)字是中斷設(shè)備地址,第四個數(shù)字是中斷設(shè)備的中斷源。因為interrupt-map- mask是全0,這樣不管與什么數(shù)字做與運算結(jié)果都是0,interrupt-map屬性的前4個數(shù)字也都是0,這說明在pcie@1,0下邊所有的中斷映射到中斷父節(jié)點的中斷都是一個中斷。接著是指向gic的,因為gic節(jié)點下#address-cells屬性為0,所以后邊不需要描述中斷父設(shè)備的地址了,后邊3個數(shù)字都是表示中斷父設(shè)備中斷源的。一句話描述就是pcie@1,0下的所有中斷都映射到 gic,GIC_SPI類型的第29號中斷,觸發(fā)類型為高電平觸發(fā)。這個例子說明在中斷樹的最下邊可以是interrupt nexus節(jié)點。

以上例子中斷樹的根是gic,gic下邊有兩個孩子,一個是中斷設(shè)備timer@c600,一個是interrupt nexus節(jié)點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屬性將下邊所有設(shè)備的中斷映射到一個gic下邊的中斷上。

本文糾錯】【告訴好友】【打印此文】【返回頂部
將考試網(wǎng)添加到收藏夾 | 每次上網(wǎng)自動訪問考試網(wǎng) | 復(fù)制本頁地址,傳給QQ/MSN上的好友 | 申請鏈接 | 意見留言 TOP
關(guān)于本站  網(wǎng)站聲明  廣告服務(wù)  聯(lián)系方式  站內(nèi)導(dǎo)航  考試論壇
Copyright © 2007-2013 中華考試網(wǎng)(Examw.com) All Rights Reserved
屏南县| 西丰县| 黔江区| 忻城县| 南和县| 湾仔区| 临漳县| 新晃| 彩票| 平舆县| 赤城县| 西吉县| 安义县| 师宗县| 鄂托克前旗| 桐梓县| 明光市| 临高县| 宣化县| 梁山县| 威信县| 湟源县| 锡林郭勒盟| 信丰县| 浏阳市| 福鼎市| 杭锦后旗| 来安县| 讷河市| 永康市| 通化县| 无极县| 昂仁县| 神农架林区| 信宜市| 永泰县| 萨迦县| 吉木乃县| 巴林右旗| 江山市| 赣榆县|