時間觸發(fā)模式下的ProtothreadS設(shè)計應(yīng)用
嵌入式行業(yè)的飛速發(fā)展使得嵌入式芯片的容量和功能都在不斷地提升。以工業(yè)應(yīng)用最為常見的8位微控制器為例,其ROM和RAM的容量都在不斷擴(kuò)大,甚至一些高端的8位處理器可以使用簡單的操作系統(tǒng)(OS)來進(jìn)行開發(fā)。同時,32位處理器的廣泛普及也使得其價格逐漸逼近8位處理器。所以對很多應(yīng)用來說,開發(fā)的簡化和迅速成為最主要的目標(biāo)。尤其是當(dāng)使用一款新的處理器或者硬件電路時,快速的搭建其開發(fā)的框架變得尤其重要。在嵌入式系統(tǒng)中,通常會采用兩種不同的任務(wù)管理和調(diào)度方式:事件觸發(fā)和時間觸發(fā)。事件觸發(fā)方式以事件的發(fā)生為核心,往往會采用多級中斷的方法來實現(xiàn),其發(fā)生的時間具有隨機(jī)性。所以事件觸發(fā)方式具有較好的實時性,但是這樣也意味著該系統(tǒng)具有較高的復(fù)雜度。而且,事件觸發(fā)方式的開銷往往是很大的。Alexander Metzner的研究指出:一個包含27個任務(wù)、采用RM(Rate Mono―tonic)調(diào)度算法的事件觸發(fā)系統(tǒng),CPU的實際利用率僅為18%。
而時間觸發(fā)方式開發(fā)的系統(tǒng),保證了在同一時刻只處理一個事件,雖然犧牲了并發(fā)處理的實時性,但是保證了系統(tǒng)的可靠性,并且使得程序員能很好地預(yù)測程序的流程。Kopetz就指出:使用基于時間觸發(fā)的合作式調(diào)度器會使得系統(tǒng)有非常好的可預(yù)測性。在本項目中,嵌入式系統(tǒng)的功能主要集中在控制一些具有一定時隙間隔的外圍設(shè)備上面。鍵盤的掃描、顯示的刷新、數(shù)據(jù)緩沖的存儲等都是需要定期完成的任務(wù),而這些任務(wù)的實時要求也并不高,所以選用時間觸發(fā)方式的合作式調(diào)度器成為系統(tǒng)設(shè)計的首選。
Protothrcads利用隱式的return提供了阻塞的功能,經(jīng)過Protothrcads封裝的任務(wù),其程序的邏輯更加接近處理事件的上層邏輯,大大簡化了編程。而且使用簡單的宏就可以實現(xiàn)Protothrcads,其開銷也是很小的。本文就對使用Protothrcads應(yīng)用于時間觸發(fā)模式的合作式調(diào)度器做一些討論。
2 Protothreads簡介
Protothrcads是由瑞典計算機(jī)科學(xué)研究所的科學(xué)家Adam Dunkels所創(chuàng)的一種新的線程編程方法。按AdamDunkels所說,Protothreads是專為資源緊張的系統(tǒng)設(shè)計的一種耗費資源少,且不使用堆棧的線程模型,它可以不使用復(fù)雜的狀態(tài)機(jī)機(jī)制來實現(xiàn)順序流的控制。Proto―thrcads也可以用于操作系統(tǒng)當(dāng)中。
簡單地說,Protothrcads借鑒了用c語言實現(xiàn)協(xié)同(co―routine)的原理,它應(yīng)用switch―case語句的直接跳轉(zhuǎn)功能,實現(xiàn)了有條件阻塞(conditional block),最終實現(xiàn)了虛擬的并行處理功能(concurrent)。實際上,Protothrcads并不是真正的線程,在多任務(wù)的切換中并不會真正涉及上下文的切換,其線程的調(diào)度也僅僅是依靠隱式的return,進(jìn)而退出函數(shù)體來完成的。但是Protothreads的優(yōu)點卻是實實在在的。首先它不需要堆??臻g,而正如筆者用宏實現(xiàn)的那樣,Protothrcads也實現(xiàn)了很多只有線程編程方法才能實現(xiàn)的機(jī)制,比如阻塞。而用宏進(jìn)行了封裝之后,使用者完全可以像使用線程一樣使用它們,而且其邏輯更加簡化,這大大增加了程序的清晰度,并降低了開發(fā)維護(hù)的難度。
在對實時性要求比較高或者說要求并行處理的場合,往往需要在任務(wù)A執(zhí)行到一定程度、等待事件C發(fā)生時,退出當(dāng)前任務(wù)A并轉(zhuǎn)而執(zhí)行任務(wù)B;當(dāng)事件C發(fā)生之后,系統(tǒng)繼續(xù)回到任務(wù)A,繼續(xù)方才的執(zhí)行。所以必須將任務(wù)A上次執(zhí)行到地方的環(huán)境存儲起來,以便重回任務(wù)A后可以接著打斷的地方繼續(xù)運行。線程的上下文切換可以達(dá)到這個目的,Simon Tatham用C語言實現(xiàn)的co―routine也可以。Protothreads正是借鑒了這一原理,如以下任務(wù)函數(shù)所示:
可以看出,在進(jìn)行了宏擴(kuò)展之后,下面的程序段和上面的程序段是完全相同的,但是宏封裝很好地構(gòu)建了一個上層的邏輯體系。這正是Protothreads的核心所在。同時,這也決定了Protothreads具有一定的局限:
①Protothreads中使用的必須是靜態(tài)變量或者全局變量;
②避免與switch語句的合用(Protothreads的實現(xiàn)已經(jīng)用了switch語句);
③因為編譯器會將__LINE__解釋為當(dāng)前所在的行號,所以不能將多個“返回”置于同一行。
3 調(diào)度器設(shè)計
時間觸發(fā)方式的嵌入式系統(tǒng)是根據(jù)定時器產(chǎn)生的恒定間隔的中斷來觸發(fā)和管理任務(wù)的。系統(tǒng)依靠一個基準(zhǔn)的時間中斷,以此中斷為任務(wù)處理的節(jié)奏和“節(jié)拍”,任務(wù)的調(diào)度發(fā)生在“節(jié)拍”規(guī)定的時刻。中斷服務(wù)子程序也同樣占用這個時間間隔,為了系統(tǒng)的穩(wěn)定性,一方面要使中斷服務(wù)子程序盡可能短,以節(jié)省任務(wù)的執(zhí)行時間;另一方面,執(zhí)行的任務(wù)也應(yīng)該盡可能短,一些比較耗時的任務(wù)可以細(xì)分為若干個子任務(wù)加以調(diào)度。同時,這也要求調(diào)度器的設(shè)計盡可能簡單。本文的設(shè)計思想就是對于系統(tǒng)僅僅定義一個任務(wù)控制塊(TCB)隊列,每個任務(wù)對應(yīng)于隊列中的一個節(jié)點,由中斷服務(wù)子程序更改TCB隊列中的記錄,調(diào)度函數(shù)根據(jù)此TCB來進(jìn)行調(diào)度??梢月晕⑿薷腜roto―threads中的結(jié)構(gòu)體pt,以滿足作為TCB隊列節(jié)點的需要。當(dāng)然,此結(jié)構(gòu)也需要聲明為全局變量或者靜態(tài)變量。其數(shù)據(jù)結(jié)構(gòu)如下所示:
評論