19bytes!玩轉(zhuǎn)嵌入式rtos―r&s在mcs51上的移植 阮海深 2004-12-8 修訂
r&s是一款層次清晰的嵌入式內(nèi)核,努力追求穩(wěn)定與快速;r&s主體部分是嚴(yán)格按照ansi c標(biāo)準(zhǔn)語法構(gòu)建的,幸運的是,當(dāng)前流行的處理器都有支持的標(biāo)準(zhǔn)c編譯環(huán)境,只需改動少量與處理器相關(guān)代碼,即可很容易將r&s移植到具體的處理器上;本文通過在mcs51的移植實例,探討r&s的一般移植思路。
一 r&s的文件結(jié)構(gòu) 1 \arch,依賴于具體體系結(jié)構(gòu)部分,包括中斷、時鐘服務(wù)、處理器棧指針切換,是移植的重點; 2 \example,演示例子; 3 \inc,內(nèi)核頭文件,包括默認(rèn)的配置文件config.h; 4 \kernel,基本內(nèi)核模塊,不依賴具體處理器部分代碼; 5 \ipc,任務(wù)間通訊支持,包括二值信號量、信號量、互斥鎖、郵箱、消息隊列; 6 \lib,用戶支持庫,基本IO,文件系統(tǒng),網(wǎng)絡(luò)支持…(待完善);
二 移植 r&s的移植過程是非常簡單的,實際上只需重新實現(xiàn)5個函數(shù)和幾個常數(shù)宏定義,移植涉及到文件均在目錄\arch下: ¨ basetype.h ¨ intr.h ¨ trace.h ¨ misc.c ¨ context.asm ¨ trace.c 共3個頭文件與3個源文件,其中1個asm文件。 basetype.h包含了關(guān)于cpu位寬、棧的增長方向、存儲字節(jié)序以及基本數(shù)據(jù)類型描述。 intr.h、misc.c、context.asm定義了臨界段相關(guān)的宏、任務(wù)上下文切換、以及系統(tǒng)時鐘中斷服務(wù),涉及到以下項修改: ¨ 臨界段控制宏CRITICAL_ENTER、CRITICAL_EXIT與中斷控制宏DISABLE_IRQ、ENABLE_IRQ定義 ¨ 任務(wù)棧初始化 __stack_init、__entry_init ¨ 任務(wù)棧指針切換 __switch_start、__switch_to ¨ 系統(tǒng)時鐘服務(wù) __timer_irs trace.h、trace.c是用戶接口輸出支持,包括對__ASSERT的實現(xiàn)。提供對r&s的DEBUG版本、字符輸出lib/pintk等相關(guān)的支持。對于沒有用戶接口硬件支持的系統(tǒng),可以省略這兩個文件。
1 修改basetype.h相關(guān)內(nèi)容
#define ARCH_CPU_BITS 8 //cpu位寬 #define ARCH_STACK_GROW UPWARDS //棧增長方向 #define ARCH_MM_BYTEORDER BIG_ENDIAN //字節(jié)序模式:大頭模式,即低地址高字節(jié)
//以下是基本數(shù)據(jù)類型 #define __arch_u8 char #define __arch_u16 short #define __arch_u32 long #define __arch_u64 long long
//重定義SP指針和基本類型修飾(可選內(nèi)容) #define __sp char idata * #define __const_ code #define __p_ data
2 移植intr.h、misc.c、context.asm
1) 臨界段宏CRITICAL_ENTER,CRITICAL_EXIT定義
DISABLE_IRQ、ENABLE_IRQ分別定義中斷開關(guān)控制。 宏CRITICAL_ENTER,CRITICAL_EXIT定義了系統(tǒng)臨界段代碼保護(hù),一般是通過開、關(guān)中斷實現(xiàn)。在提供內(nèi)嵌匯編語句的編譯器中,可以很方便定義插入?yún)R編指令來開、關(guān)中斷;在c51中,可以直接使用c語法來操作51的特殊寄存器,非常方便。 這里我們通過簡單的進(jìn)入臨界段CRITICAL_ENTER,關(guān)閉中斷EA=0,退出臨界段CRITICAL_EXIT打開中斷EA=1實現(xiàn)。注意,這種模式要避免臨界段的嵌套。在稍微復(fù)雜的應(yīng)用,進(jìn)入臨界段要先將中斷狀態(tài)保存到堆棧中,然后關(guān)閉中斷,退出臨界段時,從堆棧中恢復(fù)中斷狀態(tài)。 #define DISABLE_IRQ EA = 0 #define ENABLE_IRQ EA = 1 #define CRITICAL_ENTER EA=0 #define CRITICAL_EXIT EA=1
2) 任務(wù)棧初始化 __stack_init、__entry_init
初始化任務(wù)棧,實際上是模擬函數(shù)調(diào)用過程,給任務(wù)以假象--哦,我是從這個地方中斷的,現(xiàn)在我應(yīng)該回到那繼續(xù)!我們利用任務(wù)的入口地址entry初始化一個假想棧,這樣任務(wù)就可以從返回到入口開始工作。 實際上,r&s沒有讓任務(wù)馬上進(jìn)入任務(wù)入口函數(shù)entry運行,在任務(wù)開始前,總該做點什么,這個工作交給了__entry_init,很多時候,只需在__entry_init為每個任務(wù)簡單的打開中斷。 static void __entry_init(void) { ENABLE_IRQ; //在任務(wù)開始前,我們首先打開中斷 } //返回entry 現(xiàn)在利用__stack_init構(gòu)造一個初始化任務(wù)棧,使得任務(wù)能夠最終返回到入口entry開始。 |