用協處理器提高μC/OS-II的實時性
μC/OS-II是一種可移植、可固化、可裁剪及可剝奪型的多任務實時操作系統(RTOS)。本文提出用雙核單片機提高實時操作系統μC/OS-II實時性的新思路,給出以協處理器實現μC/OS-II時鐘節拍的方法和步驟,測試并驗證了該方法對應用系統實時性的提升以及計時精度的提高。
關鍵詞? μC/OS-II? HCS12X? XGATE實時性? 協處理器
引言
μC/OS-II最多支持63個任務,并支持信號量、郵箱、消息隊列等多種進程間通信機制;同時,用戶可以根據需求對內核中的功能模塊進行裁剪。將μC/OS-II應用到嵌入式系統中,對于提高產品的質量、縮短開發周期和降低成本都有重要的意義。
為了保證系統的實時性,μC/OS-II采用查表策略,使優先級最高的任務一旦進入就緒態就立刻可以運行。這種查表算法與應用系統的任務數目無關,執行時間是固定值,從而保證了系統的硬實時性。μC/OS-II實時內核中唯一一個執行時間受任務數目影響的函數是時鐘節拍,時鐘節拍的中斷服務子程序需要遍歷所有使用延遲函數的任務,故執行時間與任務數目有關,為非固定值。此外,時鐘節拍的頻率也不能太高,否則會因為CPU頻繁加載中斷服務子程序,導致加重了CPU負荷,影響μC/OS-II的實時性。
Freescale公司的16位HCS12X(簡稱“S12X”)系列單片機引入了一個協處理器,名為“XGATE”。與普通意義上的浮點協處理器不同,這個協處理器主要用來處理中斷。如果采用協處理器來處理μC/OS-II時鐘節拍的中斷,那么主CPU無需頻繁加載中斷服務子程序,從而保證μC/OS-II內核的所有函數執行時間都為固定值。這樣,μC/OS-II的實時性就得到了保證,還能以提高時鐘節拍中斷頻率的方法提高應用系統定時的精度。
1? 單片機中的協處理器
HCS12X系列單片機中的XGATE協處理器是精簡指令集(RISC)結構的處理器,它的工作時鐘頻率是S12X主CPU的2倍。主CPU初始化系統時可決定使用或禁用XGATE。若使用,則XGATE在初始化后就獨立地運行,并通過雙端口RAM與CPU交換數據,必要時向主CPU發中斷請求。
XGATE處理完所有的中斷后進入休眠態,停止運行,直到下一次中斷發生。XGATE比較適合響應的中斷主要是加載頻率高的中斷,或不帶通信緩沖區的I/O中斷,例如SCI發送或接收中斷、PWM輸出中斷等。而對于本身帶發送、接收緩沖區的中斷(如CAN中斷、USB中斷等),采用協處理器處理中斷優勢不明顯。
μC/OS-II的時鐘節拍中斷是一個頻繁發生的中斷,所以很適合采用XGATE來響應。以下重點介紹如何用XGATE協處理器響應μC/OS-II的時鐘節拍中斷。
2? 用XGATE實現μC/OS-II的時鐘節拍
μC/OS-II的時鐘節拍中斷可以采用單片機的實時中斷(RealTime Interrupt,RTI)來實現。當然也可以使用定時器中的計數器來產生時鐘節拍,原理相同,方法近似。使用XGATE來響應RTI中斷,實現時鐘節拍時,XGATE協處理器和主CPU的分工如表1所列。
XGATE負責響應RTI中斷,實現時鐘節拍,并完成任務延時計數;在任務延時完成后,通知CPU進行任務調度。另外,XGATE還用來響應其他中斷,在需要任務調度時通知CPU。主CPU則只負責運行任務(包括系統任務)和任務調度,只有在需要任務調度時才會加載中斷服務子程序。使用XGATE來實現時鐘節拍的具體設置步驟如下所述。
2.1? 將RTI中斷的控制權交給XGATE
為了將RTI中斷交由XGATE來處理,系統初始化時需要設置S12X單片機中RTI中斷對應的中斷控制寄存器。中斷控制寄存器組成如下:
在S12X單片機中,每一個I/O中斷都有一個中斷控制寄存器與之對應。中斷控制寄存器控制相應的中斷是由S12X CPU響應還是由XGATE來響應,以及該中斷的優先級。
中斷控制寄存器中,RQST位為1時,中斷由XGATE來響應;為0時,中斷由S12X CPU響應。為了使用XGATE來響應RTI中斷,需要將RTI中斷對應的中斷控制寄存器的RQST位置1。PRIOLVL\[2∶0\]保存的是對應中斷的優先級,值越大,對應中斷的優先級越高。如果這3位均為0,那么對應中斷會被禁用。
設置中斷控制寄存器可以調用編譯器提供的一個函數ROUTE_INTERRUPT。這個函數需要的參數是對應中斷的中斷向量相對中斷向量表基址(0xFF00)的偏移量,以及中斷控制寄存器的值。設置RTI中斷控制寄存器的代碼如下:
ROUTE_INTERRUPT(0xF0, 0x81);
其中,0xF0是RTI中斷向量相對中斷向量表基址的偏移量,0x81是要設置的中斷控制寄存器的值。
2.2? XGATE與S12X CPU的數據共享
XGATE實現μC/OS-II的時鐘節拍和S12X CPU實現任務調度,都需要訪問與系統的任務控制塊鏈表相關的變量,因此這些變量需要聲明為XGATE和S12X CPU的共享變量。共享變量的聲明需要加上“volatile”類型聲明,并使用“#pragma”預處理命令將其放在共享內存中。
S12X CPU的程序中聲明如下:
#pragma? DATA_SEG? SHARED_DATA
OS_TCBvolatile*OSTCBCur;//當前任務控制塊指針
OS_TCBvolatile*OSTCBFreeList;//當前空閑任務控制塊指針
OS_TCBvolatile*OSTCBHighRdy;//當前最高優先級任務控制塊指針
OS_TCBvolatile*OSTCBList;//任務控制塊鏈表入口指針
#pragma? DATA_SEG? DEFAULT
在XGATE的程序中,需要使用extern聲明這些變量,具體語句如下:
#pragma? DATA_SEG? SHARED_DATA
externOS_TCBvolatile*OSTCBCur;//當前任務控制塊指針
externOS_TCBvolatile*OSTCBFreeList;//當前空閑任務控制塊指針
externOS_TCBvolatile*OSTCBHighRdy;//當前最高優先級任務控制塊指針
externOS_TCBvolatile*OSTCBList;//任務控制塊鏈表入口指針
#pragma? DATA_SEG? DEFAULT
2.3? XGATE與S12X CPU的指針變量變換
因為XGATE的內存空間編址與S12X CPU的內存空間編址不一樣,所以在指針變量共享時會存在問題。CPU的內存空間和XGATE的內存空間的差別如圖1所示。
從圖1中可以看出,在S12X CPU的尋址空間中,0x1000~0x3FFF為RAM空間;而對XGATE來說,RAM空間的地址范圍為0x8000~0xFFFF。如果XGATE的程序直接使用CPU的指針變量,則會導致XGATE訪問地址空間0x1000~0x3FFF,該區域對于XGATE是Flash,從而出錯。為了正確地共享指針變量,在XGATE中使用S12X CPU的指針變量時,需要對指針變量進行變換。S12X系列中不同單片機成員的地址分配可能有所不同。以MC9S12XDT512單片機為例,其內部共有8 KB非分頁RAM,可全都設為S12X CPU和XGATE的共享內存。這8 KB RAM在S12X CPU中的地址為0x2000~0x3FFF;而在XGATE中的地址為0xE000~0xFFFF,地址偏差為0xC000。因此,在XGATE使用S12X CPU的指針變量時,將指針變量的值加偏移量0xC000,就可以在XGATE程序中正常使用。
下面是XGATE程序中一個指針變量變換的代碼:
LDW R2,(R1,#0);R1中是指針變量的地址,將指針的值放到R2
ADDH R2,#$C0;將R2增加0xC000
MOV R1,R2;將變換后的指針放到R1
LDB R3, (R1,#0);通過變換后的指針訪問變量
在XGATE協處理器中有8個寄存器,編譯器使用其中的R1來傳遞參數,上面程序中的R2、R3是8個寄存器中的另外2個。
2.4? XGATE與S12X CPU的通信
XGATE處理RTI中斷時先完成指針變換,然后遍歷μC/OS-II的所有任務控制塊鏈表,對需要延時的任務進行延時計數器減1操作。若無需任務調度,則XGATE回到休眠態,直到響應下一次中斷。僅當某任務延時計數器遞減到零時,該任務進入就緒態,需要任務調度時才通知S12X CPU進行任務切換。
在XGATE的中斷服務子程序中,中斷標志指令SIF用于向S12X CPU發出中斷請求。該指令置位中斷標志位,請求S12X CPU繼續響應本次RTI中斷。在XGATE的中斷服務子程序中使用SIF指令的代碼如下(其中R5是協處理器XGATE的8個寄存器之一):
CMP R5,#0 ;R5保存進入就緒態且優先級比當前運行任務高的任務數目
BEQ OUT;如果R5為0,那么無需任務調度
SIF;如果R5不為0,那么需要通知S12XCPU進行任務調度
OUT: RTI;中斷子程序返回
由于遍歷任務控制塊鏈表和各任務延時計數器減1的操作,以及無需任務調度的RTI中斷響應都由XGATE完成了,S12X CPU只需要響應確實需要進行任務調度的RTI中斷,使其中斷服務子程序大大簡化:
void OSTickISR(void) {//S12X CPU時鐘節拍中斷服務
OSIntEnter();//中斷嵌套層數加1
XGIF0_XGIF_78 = 1;//清XGATE中斷
OS_SAVE_SP();//保存當前任務棧
OSIntExit();//中斷嵌套層數減1并進行任務調度
asm{ rti }//中斷返回
}
這樣,CPU的RTI中斷服務子程序所要執行的代碼是固定的,每次的運行時間也是固定值,因而μC/OS-II的實時性得到了確切的保證。
S12X CPU和XGATE的程序流程如圖2所示。
2.5? 設置XGATE向量表
為了使XGATE正常響應中斷,需要把XGATE的RTI中斷服務子程序地址寫到XGATE的中斷向量表中。XGATE的中斷向量表的寫法與CPU的中斷向量寫法類似,只是XGATE的中斷子程序可代入一個參數,需要將這個參數也寫入中斷向量表。
在XGATE中斷向量表的確定位置,寫入RTI中斷服務子程序地址和參數變量,就可以使XGATE在響應RTI中斷時進入RTI中斷服務子程序。
XGATE的中斷向量表的寫法如下:
constXGATE_TableEntry? XGATE_VectorTable[] = {/*通道0~8都是不能使用XGATE來響應的中斷,所以從通道9開始*/
{ErrorHandler, 0x09},//通道9,未使用
{ErrorHandler, 0x0A}, //通道10,未使用
…//其他通道,可以選擇使用
{RTI_Handler, (int)OSTCBList},//通道0x78,RTI中斷子程和參數,將控制塊鏈表作為參數
{ErrorHandler, 0x79},//通道0x79,IRQ中斷,未使用
};
其中,OSTCBList是XGATE響應RTI中斷時需要帶入的參數,這里這個參數是μC/OS-II任務控制塊鏈表的首地址;XGATE_TableEntry是一個編譯器自定義的結構體變量類型;XGATE_VectorTable[]是XGATE的中斷向量表。寫好XGATE的中斷向量表后,使用XGATE實現μC/OS-II時鐘節拍的設置過程就完成了。
3? 效果測試與分析
為了驗證用協處理器處理時鐘節拍中斷的效果,進行如下測試:在同一S12X單片機上,分別使用和不使用XGATE處理μC/OS-II的時鐘節拍中斷。在兩種情況下,建立同樣的10個任務,時鐘節拍中斷服務子程序中同樣只進行任務控制塊鏈表遍歷和延時計數器減1,不做任務調度。這樣,μC/OS-II中會有一個任務總處于就緒態并一直運行,這個一直運行的任務會通過循環計數的方法在一個I/O端口上輸出一個方波。在同樣的總線時鐘和同樣頻率的時鐘節拍下,比較兩種μC/OS-II輸出的方波周期的差別。
測試的目的是,觀察μC/OS-II的時鐘節拍中斷服務子程序的加載,對正在系統中運行的任務的影響。為了與XGATE處理任務控制塊鏈表遍歷和延時計數器減1進行對比,未使用XGATE的μC/OS-II中,S12X CPU的時鐘節拍中斷服務子程序只保留與XGATE同樣的操作。沒有任務調度,也方便對系統中正在運行的任務輸出的方波進行觀察。
在不使用的XGATE的μC/OS-II中,S12X CPU的RTI中斷的中斷服務子程序代碼如下:
interruptvoid? OSTickISR(void) {
OS_TCB ptcb;
OSIntEnter();//中斷嵌套層數加1
OS_SAVE_SP();//保存當前任務堆棧指針
CRGFLG |= 0x80;//清RTI中斷標志位
ptcb = OSTCBList; //獲得中斷控制塊鏈表的表頭指針
while (ptcb>OSTCBPrio != OS_IDLE_PRIO) {//遍歷所有的任務控制塊
OS_ENTER_CRITICAL();//進入臨界段代碼
if (ptcb>OSTCBDly != 0) { //對延時計數器非零的任務延時計數器減1ptcb>OSTCBDly;
}ptcb = ptcb>OSTCBNext; //指向下一個任務控制塊
OS_EXIT_CRITICAL();//離開臨界段代碼
}
OSIntExit();//中斷嵌套層數減1,必要時做任務調度
}
以上S12X CPU中斷服務子程序共有220條指令,需運行538個周期。測試中采用了16 MHz的總線時鐘和16 kHz的μC/OS-II時鐘節拍。可以估算出,每次中斷服務子程序在S12X CPU中的運行時間為33.6? μs,約相當于62.5 μs時鐘節拍的53%,即S12X CPU需要用一多半的時間響應時鐘節拍中斷,這顯然是不可取的。
在μC/OS-II中用XGATE處理時鐘節拍中斷時,當無需做任務調度時,XGATE遍歷10個任務的控制塊鏈表,執行延時計數器減1操作,共需要148條指令。由于XGATE是RISC結構的處理器,指令執行時間多為1~2個周期,故執行148條指令共需要218個周期。在32 MHz時鐘頻率下,執行時間大約7 μs,僅相當于62.5 μs時鐘節拍的11%。這說明,即使使用短至62.5 μs的時鐘節拍,對XGATE的占用率也并不高。
通過以上測試可看出,由單一CPU運行μC/OS-II,16 kHz的時鐘節拍導致S12X CPU頻繁地加載中斷服務子程序,占用超過了50%,嚴重地影響了任務的實時運行。故對于單一CPU,一般采用的時鐘節拍頻率不高于100 Hz,此時計時精度為±10 ms,以避免時鐘節拍中斷占用大量CPU運行時間。
在用XGATE處理μC/OS-II的時鐘節拍時,16 kHz的時鐘節拍并未對S12X CPU的任務運行產生影響,這個頻率的時鐘節拍使μC/OS-II的定時精度高于±62.5 μs。利用協處理器XGATE來處理μC/OS-II的時鐘節拍,使主 CPU的執行時間為固定值,因而保證了任務的實時運行,提升了系統實時性,高頻率的時鐘節拍也提高了計時精度。
4? 結論
μC/OS-II中,時鐘節拍中斷服務子程序需要遍歷整個任務控制塊鏈表,不同應用中任務數目不同,遍歷整個任務控制塊鏈表所花費的時間就不同。時鐘節拍中斷所帶來的不確定性是影響μC/OS-II實時性指標的唯一因素。采用協處理器來實現μC/OS-II的時鐘節拍可以很好地解決這個問題。
如果使用協處理器來響應μC/OS-II的時鐘節拍中斷,那么μC/OS-II任務控制塊鏈表的遍歷和延時計數器減1操作均由協處理器完成。主CPU只有在需要做任務調度時才會進入相應的中斷服務子程序,因此主CPU運行中斷服務子程序的時間是固定值。由于主 CPU的運行時間不會被時鐘節拍中斷占用,因而可以采用很高頻率的時鐘節拍來提高μC/OS-II的計時精度。
評論
查看更多