解決軟硬件接口的嵌入式系統(tǒng)設(shè)計(jì)實(shí)例
既然硬件設(shè)計(jì)工程師的重點(diǎn)已經(jīng)從邏輯門(mén)和總線轉(zhuǎn)移到了系統(tǒng)設(shè)計(jì),我們?cè)賮?lái)審視一下任何處理器系統(tǒng)中最常用到的寄存器設(shè)計(jì)。寄存器接口允許高速訪問(wèn)資源,其訪問(wèn)的效率對(duì)系統(tǒng)的性能有很大的影響。
寄存器的結(jié)構(gòu)與訪問(wèn)
設(shè)計(jì)工程師應(yīng)該精心選擇硬件寄存器大小,使處理器能最有效地進(jìn)行硬件訪問(wèn)。一般來(lái)說(shuō),總是采用系統(tǒng)內(nèi)部整數(shù)訪問(wèn)方式。寄存器應(yīng)該被譯碼為連續(xù)的組(沒(méi)有地址空檔),這樣可以加速指針或陣列索引對(duì)寄存器的訪問(wèn)。任何可寫(xiě)的寄存器也應(yīng)該是以同樣的格式可讀,這樣可以避免使用本地存儲(chǔ)器來(lái)緩存這些寄存器值。
控制一個(gè)子系統(tǒng)的寄存器應(yīng)該以相同的結(jié)構(gòu)形式在一起分組,使軟件能使用通用的驅(qū)動(dòng)程序?qū)λ鼈冞M(jìn)行訪問(wèn)。當(dāng)設(shè)計(jì)中需要多個(gè)同一類(lèi)型的子系統(tǒng)時(shí)這點(diǎn)尤其重要。
為了避免被編碼成獨(dú)立進(jìn)程的軟件任務(wù)之間發(fā)生沖突,獨(dú)立的子系統(tǒng)不能在系統(tǒng)處理器訪問(wèn)期間共享可寫(xiě)寄存器。這些“獨(dú)立”的軟件進(jìn)程在訪問(wèn)共享寄存器時(shí)會(huì)產(chǎn)生競(jìng)爭(zhēng),除非在系統(tǒng)代碼中使用不可中斷的讀/寫(xiě)驅(qū)動(dòng)程序。根據(jù)操作系統(tǒng)的不同,多個(gè)進(jìn)程共享寄存器甚至可能會(huì)產(chǎn)生功能調(diào)用的額外開(kāi)銷(xiāo)。訪問(wèn)共享寄存器的同時(shí)還有執(zhí)行其它進(jìn)程的做法是錯(cuò)誤的,也是軟件設(shè)計(jì)的通病,會(huì)導(dǎo)致間歇性的系統(tǒng)故障,影響集成和測(cè)試系統(tǒng)軟件的進(jìn)度。
系統(tǒng)A違反了很多上文提到的原則,如采用只寫(xiě)寄存器,共享控制和狀態(tài)寄存器,以及沒(méi)有為每個(gè)軸提供公共的寄存器映射。系統(tǒng)A必須用專(zhuān)門(mén)的驅(qū)動(dòng)程序來(lái)緩沖寫(xiě)輸出數(shù)據(jù),移位并屏蔽軸驅(qū)動(dòng)與位置信息,并防止軸驅(qū)動(dòng)寄存器內(nèi)容被為每個(gè)軸任務(wù)編寫(xiě)的代碼所影響。系統(tǒng)B由于分離并重組了與每個(gè)軸有關(guān)的寄存器,因此能克服這些問(wèn)題。
寄存器復(fù)位內(nèi)容
硬件設(shè)計(jì)工程師應(yīng)仔細(xì)考慮系統(tǒng)的復(fù)位狀態(tài)。硬件設(shè)計(jì)通常采用啟動(dòng)程序來(lái)取得系統(tǒng)啟動(dòng)后的控制權(quán),并將系統(tǒng)初始化到一個(gè)安全的狀態(tài)。系統(tǒng)復(fù)位后應(yīng)將硬件置于一個(gè)確定的安全狀態(tài),并且硬件應(yīng)持續(xù)保持安全狀態(tài)直到系統(tǒng)軟件初始化完成為止。代碼也應(yīng)在軟件控制下復(fù)位硬件以幫助調(diào)試、自檢和原始代碼的開(kāi)發(fā)。
系統(tǒng)A不控制驅(qū)動(dòng)寄存器的復(fù)位內(nèi)容,需要代碼的介入來(lái)將所有三個(gè)軸的驅(qū)動(dòng)寄存器設(shè)置為零。這種結(jié)構(gòu)會(huì)產(chǎn)生嚴(yán)重的系統(tǒng)設(shè)計(jì)問(wèn)題,因?yàn)樘幚砥魍ǔJ潜3衷趶?fù)位狀態(tài),直到FPGA和ASIC加電并得到配置后處理器才正常工作。如果開(kāi)發(fā)人員使用仿真器,那么在集成過(guò)程中系統(tǒng)A還會(huì)出現(xiàn)另外的問(wèn)題:被仿真器控制的處理器在系統(tǒng)加電后可能需要很長(zhǎng)的初始化時(shí)間才能正常工作。在軟件取得控制權(quán)之前系統(tǒng)A和B的軸都處于隨機(jī)驅(qū)動(dòng)狀態(tài)。
系統(tǒng)B在加電后會(huì)將所有軸驅(qū)動(dòng)寄存器設(shè)為零,它對(duì)軸驅(qū)動(dòng)設(shè)置的控制并不依賴(lài)于啟動(dòng)時(shí)間。因?yàn)橄到y(tǒng)B沒(méi)有隱藏的狀態(tài)機(jī),因此在本設(shè)計(jì)中沒(méi)有必要考慮增加額外的軟件復(fù)位寄存器。
寄存器域設(shè)計(jì)
大多數(shù)資源接口所包含的數(shù)據(jù)項(xiàng)并不正好適合一個(gè)寄存器。這種情況下,硬件設(shè)計(jì)工程師必須將一個(gè)寄存器分成若干域。合理的域結(jié)構(gòu)對(duì)系統(tǒng)性能來(lái)說(shuō)非常重要,與寄存器接口設(shè)計(jì)有相似的影響。有效的域接口設(shè)計(jì)規(guī)則類(lèi)似于寄存器設(shè)計(jì)規(guī)則,但設(shè)計(jì)工程師還需要特別注意域的順序與放置,還要對(duì)寄存器中未用到一些字節(jié)作一定的處理。
1. 寄存器的域
域被定義為寄存器中若干位的子集,主要用于報(bào)告或控制資源的一個(gè)功能要素。在硬件設(shè)計(jì)中最常用的域類(lèi)型有:1. 布爾域:真或假,通常是一位;2. 多位狀態(tài)域和控制域:多位用于報(bào)告或控制內(nèi)部相關(guān)功能;3. 列舉狀態(tài)域和控制域:多個(gè)位的集合,其中每個(gè)位代表了一種不同的硬件狀態(tài);4. 數(shù)字域:多個(gè)位組合在一起用來(lái)代表一定的數(shù)量值。
從軟件使用者角度看,最有效的域結(jié)構(gòu)是每個(gè)寄存器只用一個(gè)域。這種理想的軟件結(jié)構(gòu)可能導(dǎo)致硬件實(shí)現(xiàn)效率低,因此一個(gè)好的系統(tǒng)設(shè)計(jì)需要在軟硬件設(shè)計(jì)之間作出折衷,在每個(gè)寄存器中應(yīng)放置多個(gè)域。
下文將著重討論一個(gè)寄存器中假設(shè)存在多個(gè)域的情況,不過(guò),當(dāng)對(duì)資源的某個(gè)特殊參數(shù)進(jìn)行的有效訪問(wèn)將嚴(yán)重影響系統(tǒng)軟件性能時(shí),硬件設(shè)計(jì)工程師仍應(yīng)該考慮使用單個(gè)域的寄存器。
2. 域結(jié)構(gòu)
前文提到的用于寄存器的結(jié)構(gòu)概念同樣也適合于寄存器內(nèi)部的域。一個(gè)寄存器應(yīng)該只包含屬于設(shè)計(jì)中同一功能要素的域,并且該寄存器中的所有可寫(xiě)域都應(yīng)該是可讀的。
那些包含有屬于多個(gè)功能要素的域的寄存器同樣需要特殊驅(qū)動(dòng)程序支持,這樣才能使多個(gè)進(jìn)程安全地訪問(wèn)每個(gè)域。而配置為“只寫(xiě)”功能的域需要分配影子內(nèi)存來(lái)保存寄存器域中的前一狀態(tài)值。硬件設(shè)計(jì)工程師原來(lái)設(shè)想的簡(jiǎn)單的“屏蔽/寫(xiě)”操作現(xiàn)在變成了繁雜的多步功能調(diào)用,首先必須禁止中斷和任務(wù)切換,然后讀本地存儲(chǔ)器,屏蔽輸入輸出值,再進(jìn)行硬件寄存器寫(xiě),最后開(kāi)放中斷和多任務(wù)切換。如果寄存器中所有域能得到有效安排,通過(guò)一個(gè)軟件任務(wù)就能訪問(wèn)全部域的話,上述情況就能得到有效避免。
由于系統(tǒng)A將屬于不相關(guān)功能的多個(gè)域組合放在一個(gè)寄存器中,因此它需要使用特殊的驅(qū)動(dòng)程序。而系統(tǒng)B則遵循“單個(gè)寄存器內(nèi)的域按任務(wù)進(jìn)行組織”的原則,將每個(gè)域放置在屬于自己的專(zhuān)用寄存器中,因此能高效地訪問(wèn)資源中的每個(gè)軸參數(shù)。
3. 十六進(jìn)制數(shù)字對(duì)齊
硬件設(shè)計(jì)工程師還應(yīng)該明白針對(duì)處理器和軟件開(kāi)發(fā)環(huán)境進(jìn)行對(duì)齊約束。如果將域放置在錯(cuò)誤的地址上而超出字的邊界,將迫使軟件設(shè)計(jì)工程師只能按塊訪問(wèn)每個(gè)域,進(jìn)而增加訪問(wèn)復(fù)雜性,降低訪問(wèn)的速度。在調(diào)試過(guò)程中,用零值填充域是非常有用的,可以使每個(gè)域的最低位對(duì)齊十六進(jìn)制數(shù)字(4位)的邊界:當(dāng)在邏輯分析儀、調(diào)試儀或仿真器上顯示寄存器情況時(shí),十六進(jìn)制數(shù)字對(duì)齊會(huì)有助于域值的可視化提取。系統(tǒng)A的寄存器域是沒(méi)有對(duì)齊的,因此從原始的十六進(jìn)制數(shù)據(jù)中提取域值很困難。由于控制域沒(méi)有對(duì)齊,在查錯(cuò)時(shí)屏蔽測(cè)試輸入也十分困難。而系統(tǒng)B的所有域都是按十六進(jìn)制偶數(shù)數(shù)字對(duì)齊,因此通過(guò)寄存器讀可以很容易地確定每個(gè)域的狀態(tài),并且能方便地將某個(gè)域設(shè)為指定值。
4. 域位置的分配與順序
寄存器內(nèi)域的設(shè)置也會(huì)嚴(yán)重影響軟件實(shí)現(xiàn)的效率。布爾域和多位域通常與位置無(wú)關(guān),但當(dāng)列舉域和數(shù)字域被放置在寄存器的最低位(LSB)時(shí)對(duì)它們的訪問(wèn)效率通常是最高的(LSB的實(shí)際位數(shù)取決于處理器類(lèi)型,位0不一定是LSB)。將域配置在寄存器的LSB中可以有效地消除對(duì)域內(nèi)容屏蔽后的移位操作,也使測(cè)試設(shè)備或進(jìn)行可視化檢查的調(diào)試儀訪問(wèn)寄存器時(shí)能更容易地識(shí)別域值。
系統(tǒng)A中用于軸2和軸3的域值在使用前必須要求軟件進(jìn)行屏蔽和移位。而系統(tǒng)B則將所有數(shù)字域配置在寄存器的LSB中,從而能完成更有效的訪問(wèn)。系統(tǒng)B的集成性也更好,資源寄存器的十六進(jìn)制數(shù)據(jù)能真正分離成正確的域值。
5. 未用數(shù)據(jù)位
寄存器中的未用位同樣也會(huì)影響軟件實(shí)現(xiàn)的效率。所有未用位應(yīng)回歸為零,并且寫(xiě)入操作時(shí)無(wú)需對(duì)它們作特殊的處理,這樣可以避免不必要的屏蔽與清除操作。這個(gè)規(guī)則的唯一一個(gè)例外是包含數(shù)字域?yàn)?的補(bǔ)碼的寄存器,并且在寄存器中剩余的最高位(MSB)沒(méi)有用的情況。在這種情況下,使硬件實(shí)現(xiàn)符號(hào)將域的MSB擴(kuò)展到未用位就非常有用。以這種方式擴(kuò)展的數(shù)字域能夠被處理器直接訪問(wèn),因?yàn)閹Х?hào)的數(shù)值無(wú)需軟件符號(hào)的擴(kuò)展。當(dāng)對(duì)特殊的數(shù)字域變量的訪問(wèn)速度嚴(yán)重影響整體系統(tǒng)性能時(shí),將該類(lèi)型的域與“單個(gè)寄存器單個(gè)域”結(jié)合起來(lái)考慮將非常有用。由于無(wú)需屏蔽或符號(hào)擴(kuò)展,這些域能以?xún)?nèi)部數(shù)據(jù)訪問(wèn)的方式直接訪問(wèn)。
當(dāng)系統(tǒng)A中需要從寄存器提取域值時(shí),要求軟件對(duì)每個(gè)數(shù)字域值進(jìn)行符號(hào)擴(kuò)展,而系統(tǒng)B允許通過(guò)對(duì)寄存器的內(nèi)部整數(shù)訪問(wèn)直接訪問(wèn)域值。
6. 域類(lèi)型選擇
域類(lèi)型的正確選擇也能極大地提高軟件實(shí)現(xiàn)效率。在打開(kāi)或關(guān)閉獨(dú)立資源功能時(shí)布爾域是最有效的。要注意的是,只有當(dāng)寄存器是可讀寫(xiě)時(shí)單位域才容易編碼。如果硬件寄存器對(duì)域的訪問(wèn)有限制,就需要專(zhuān)門(mén)的緩沖器(有可能再加上一個(gè)專(zhuān)門(mén)的驅(qū)動(dòng)程序)來(lái)保存當(dāng)前的內(nèi)容。限制性訪問(wèn)同時(shí)也會(huì)限制一些編程構(gòu)造的使用,如位域(bit field),從而影響系統(tǒng)代碼的可讀性,且無(wú)助于減少編程錯(cuò)誤。
當(dāng)表達(dá)資源狀態(tài)的數(shù)據(jù)需要占用一定范圍的值時(shí)數(shù)字域就很有用。當(dāng)一個(gè)域能保持正值和負(fù)值使用時(shí),帶符號(hào)的表達(dá)式通常需要更多的軟件工作。另外,還要避免在數(shù)字域中對(duì)其它數(shù)據(jù)進(jìn)行編碼(如利用域符號(hào)表示一個(gè)不相關(guān)的資源狀態(tài))。
從硬件實(shí)現(xiàn)來(lái)看,多位域更有效,但在寫(xiě)入系統(tǒng)代碼時(shí)會(huì)增加代碼的復(fù)雜度。列舉類(lèi)型通常能更好地反映資源中相關(guān)功能的實(shí)際可用性,可以有效防止沖突功能的采用(如將存儲(chǔ)器塊切換到本地總線上)。列舉類(lèi)型還應(yīng)提供這樣的可選項(xiàng):無(wú)條件允許切換之間存在“停放帶”,無(wú)條件允許系統(tǒng)軟件中存在“先中斷再實(shí)現(xiàn)”的代碼切換。
系統(tǒng)A中對(duì)軸驅(qū)動(dòng)域的“只寫(xiě)”訪問(wèn)使軟件對(duì)目標(biāo)域的訪問(wèn)效率很低,必須用RAM保存寫(xiě)過(guò)程中不作修改的過(guò)去的軸內(nèi)容。系統(tǒng)B中由于每個(gè)寄存器都只有一個(gè)域并允許讀寫(xiě)操作,因此不存在這樣的問(wèn)題。
linux操作系統(tǒng)文章專(zhuān)題:linux操作系統(tǒng)詳解(linux不再難懂)
評(píng)論