μCOS-Ⅱ在ATmega128上的移植St_第1頁
μCOS-Ⅱ在ATmega128上的移植St_第2頁
μCOS-Ⅱ在ATmega128上的移植St_第3頁
μCOS-Ⅱ在ATmega128上的移植St_第4頁
μCOS-Ⅱ在ATmega128上的移植St_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、    C/OS-在ATmega128上的移植St    C/OS-在ATmega128上的移植St    類別:單片機(jī)/DSP                              &

2、amp;nbsp本文詳細(xì)介紹了把C/OS-移植到ATMEL公司的8位微控制器ATmega128上的全過程。所謂移植,就是使一個實時內(nèi)核能在   &nbsp某個微處理器或微控制器上運行。在移植之前,希望讀者能熟悉所用微處理器和C編譯器的特點。   &nbsp1 ATmega128的內(nèi)核特點   &nbsp之所以要先介紹ATmega128 MCU內(nèi)核特點,是因為在C/OS-的移植過程中,仍需要用戶用C語言和匯編語言編寫一些與微   &nbsp處理器

3、相關(guān)的代碼。這里主要介紹ATmega128與C/OS-移植相關(guān)的內(nèi)核特點。如果讀者已經(jīng)對ATmega128 比較了解了,   &nbsp那就不必閱讀這一部分了。   &nbsp1.1微控制器 (MCU)   &nbspATmega128的MCU包括一個算術(shù)邏輯單元(ALU),一個狀態(tài)寄存器(SREG),一個通用工作寄存器組和一個堆棧指針。狀態(tài)   &nbsp寄存器(SREG)的最高位I是全局中斷允許位。如果全局中斷允許位為零,則所有中斷

4、0;  &nbsp都被禁止。當(dāng)系統(tǒng)響應(yīng)一個中斷后,I位將由硬件自動清“0”;當(dāng)執(zhí)行中斷返回(RETI)指令時,I位由硬件自動置“1”   &nbsp,從而允許系統(tǒng)再次響應(yīng)下一個中斷請求。   &nbsp通用工作寄存器組是由32個8位的通用工作寄存器組成。其中R26R31這6個寄存器還可以兩兩合并為3個16位的間接   &nbsp地址寄存器。這些寄存器可以用來對數(shù)據(jù)存儲空間進(jìn)行間接尋址。這3個間接地址寄存器的名稱為:X寄存器、Y寄存器、Z 

5、60; &nbsp寄存器。其中Z寄存器還能用作對程序存儲空間進(jìn)行間接尋址的寄存器。有些AVR C語言編譯器還把Y寄存器作為軟件堆棧的   &nbsp堆棧指針,比如ICC- AVR,CodevisionAVR。   &nbsp堆棧指針(SP)是一個指示堆棧頂部地址的16位寄存器。在ICCAVR中,它被用作指向硬件堆棧的堆棧指針。AVR單片   &nbsp機(jī)上電復(fù)位后,SP指針的初始值為0x0000,由于AVR單片機(jī)的堆棧是向下生長的(從高地址向低地址生長),所以系統(tǒng)

6、程序   &nbsp一開始必須對堆棧指針SP進(jìn)行初始化,即將SP的值設(shè)為數(shù)據(jù)存儲空間的最高地址。ICCAVR編譯器在鏈接C程序文件的時   &nbsp候,會自動在程序頭鏈入startup文件。startup文件里面的程序?qū)プ龀跏蓟疭P指針的工作。鏈入startup文件是ICCAVR   &nbsp這個編譯器的特點,在用其它編譯器的時候,希望讀者確認(rèn)所使用的編譯器是否帶有自動初始化SP的功能,若沒有,應(yīng)在   &nbsp用戶程序中初始化SP。

7、   &nbsp1.2 數(shù)據(jù)存儲空間(僅內(nèi)部)   &nbspAVR單片機(jī)的數(shù)據(jù)存儲器是線形的,從低地址到高地址依次是CPU寄存器區(qū)(32個通用寄存器),I/O寄存器區(qū),數(shù)據(jù)存儲區(qū)   &nbsp。   &nbspICCAVR編譯器又將數(shù)據(jù)存儲區(qū)劃分為全局變量和字符串區(qū),軟件堆棧區(qū)和硬件堆棧區(qū)三個空間。如下圖:   &nbsp高地址   &nbsp硬件堆棧區(qū) 

8、  &nbsp軟件堆棧區(qū)   &nbsp全局變量和字符串區(qū)   &nbspI/O寄存器區(qū)   &nbspCPU寄存器區(qū)   &nbsp低地址   &nbspICCAVR編譯器將堆棧分成了兩個功能不同的堆棧來處理(這一點與8051系列的單片機(jī)編譯器處理方式不同)。硬件堆   &nbsp棧用于儲存子程序和中斷服務(wù)子程序調(diào)用時的函數(shù)返回地址。這塊數(shù)

9、據(jù)區(qū)域由堆棧指針SP進(jìn)行尋址,數(shù)據(jù)的進(jìn)棧和出棧有   &nbsp專門的匯編指令(pop,push等)支持,所以叫做硬件堆棧區(qū)。軟件堆棧用于傳遞參數(shù),儲存臨時變量和局部變量。這塊數(shù)   &nbsp據(jù)區(qū)域是用軟件模擬堆棧儲存數(shù)據(jù)的方式進(jìn)行數(shù)據(jù)存儲,對該區(qū)域?qū)ぶ返闹羔樣捎脩糇约憾x,所以叫做軟件堆棧區(qū)。   &nbspAVR單片機(jī)的硬件堆棧的生長方向是向下的(從高地址向低地址生長),所以軟件堆棧在定義的時候,也采取相同的   &nbsp生長方向。&#

10、160;  &nbsp這里沒有用ATmega128而采用AVR單片機(jī)的提法是因為ATmega128屬于AVR系列單片機(jī)中的一種,而所有的AVR單片機(jī)的   &nbsp數(shù)據(jù)存儲器組織方式都是一致的。在創(chuàng)建C/OS-的任務(wù)棧時,需要了解所用微處理器數(shù)據(jù)存儲空間尤其是堆棧空間的組   &nbsp織形式及相關(guān)的操作。讀者應(yīng)參閱所用微處理器的資料和編譯器的幫助文檔,了解該部分知   &nbsp識。   &nbsp1.3 ATm

11、ega128的中斷響應(yīng)機(jī)制   &nbspATmega128有34個不同的中斷源,每個中斷源和系統(tǒng)復(fù)位在程序存儲空間都有一個獨立的中斷向量(中斷入口地址)   &nbsp。每個中斷源都有各自獨立的中斷允許控制位,當(dāng)某個中斷源的中斷允許控制位為“1”且全局中斷允許位I也為“1”時,   &nbsp系統(tǒng)才響應(yīng)該中斷。   &nbsp當(dāng)系統(tǒng)響應(yīng)一個中斷請求后,會自動將全局中斷允許位I清零,此時,后續(xù)中斷響應(yīng)被屏蔽。當(dāng)系統(tǒng)執(zhí)行中斷返回指 &#

12、160; &nbsp令RETI時,會將全局中斷允許位I置“1”,以允許響應(yīng)下一個中斷。若用戶想實現(xiàn)中斷嵌套,必須在中斷服務(wù)子程序中將   &nbsp全局中斷允許位I置“1”。(這一點與8051系列的單片機(jī)不同)   &nbsp在中斷向量表中,處于低地址的中斷具有高的優(yōu)先級。優(yōu)先級高只是表明在多個中斷同時發(fā)生的時候,系統(tǒng)先響應(yīng)優(yōu)   &nbsp先級高的中斷,并不含有高優(yōu)先級的中斷能打斷低優(yōu)先級的中斷處理工程的意思。這與8051系列單片機(jī)的中斷優(yōu)先級概念 &

13、#160; &nbsp不同。   &nbsp由于C/OS-的任務(wù)切換實際上是模擬一次中斷,因此需要知道CPU的中斷響應(yīng)機(jī)制。中斷發(fā)生時,ATmega128按以下   &nbsp步驟順序執(zhí)行:   &nbspA. 全局中斷允許位I清零。   &nbspB. 將指向下一條指令的PC值壓入堆棧,同時堆棧指針SP減2。   &nbspC. 選擇最高優(yōu)先級的中斷向量裝入PC,程序從此地址繼續(xù)執(zhí)行中斷

14、處理。   &nbspD. 當(dāng)執(zhí)行中斷處理時,中斷源的中斷允許控制位清零。   &nbsp中斷結(jié)束后,執(zhí)行RETI指令,此時   &nbspA. 全局中斷允許位I置“1”。   &nbspB. PC從堆棧推出,程序從被中斷的地方繼續(xù)執(zhí)行。   &nbsp特別要注意的是:AVR單片機(jī)在響應(yīng)中斷及從中斷返回時,并不會對狀態(tài)寄存器SREG和通用寄存器自動進(jìn)行保存和恢復(fù)操作   &am

15、p;nbsp,因此,對狀態(tài)寄存器SREG和通用寄存器的中斷保護(hù)工作必須由用戶來完成。   &nbsp1.4 ATmega128的定時器中斷   &nbspATmega128有三個定時器:T0,T1,T2;它們?nèi)叨加杏嫈?shù)溢出中斷功能,而且T1和T2還有匹配比較中斷,即定時器計數(shù)   &nbsp到設(shè)定的值時,產(chǎn)生中斷并自動清零。若系統(tǒng)采用這種中斷方式,其好處是在中斷服務(wù)程序ISR中不需要重新裝載定時器的   &nbsp值。但本文出于通用性的考慮,

16、仍采用定時器計數(shù)溢出中斷方式   &nbsp2 C/OS-的移植   &nbsp2.1移植條件   &nbsp要實現(xiàn)C/OS-的移植,所用的處理器和編譯器必須滿足一定的條件:    (1) 所用的C編譯器能產(chǎn)生可重入代碼。   &nbsp可重入代碼是指可以被一個以上的任務(wù)調(diào)用,而不必?fù)?dān)心其數(shù)據(jù)會被破壞的代碼??芍厝氪a任何時候都可以被中斷,一   &nbsp段時間以后

17、又可以重新運行,而相應(yīng)的數(shù)據(jù)不會丟失,不可重入代碼則不行。本文所使用ImageCraft公司的ICCAVR V6.29   &nbsp編譯器能產(chǎn)生可重入代碼。   &nbsp(2) 用C語言就可以打開和關(guān)閉中斷。   &nbsp本文所使用的ICCAVR V6.29編譯器支持在C語言中內(nèi)嵌匯編語句且提供專門開關(guān)中斷的宏:CLI()和SEI()。這樣,使得在C   &nbsp語言中開關(guān)中斷非常方便。   &nb

18、sp(3)    &nbsp處理器支持中斷,并且能產(chǎn)生定時中斷(通常在10至100Hz之間)本文使用的ATmega128,有3個定時器,能產(chǎn)生C/OS-   &nbsp所需的定時中斷。   &nbsp(4) 處理器支持能夠容納一定數(shù)量數(shù)據(jù)的硬件堆棧。本文使用的ATmega128有4K RAM,硬件堆??梢蚤_辟在這4K RAM中。   &nbsp(5) 處理器有將堆棧指針和其它CPU寄存器從內(nèi)存中讀出和存儲到堆?;騼?nèi)存中的指令。一般的單片機(jī)都滿足

19、這個要求(   &nbsp如PUSH、POP指令),且ATmega128還具有直接訪問I/O寄存器的指令(IN、OUT等),它比8051系列的單片機(jī)更容易實現(xiàn)上述   &nbsp要求。   &nbsp2.2移植的實現(xiàn)   &nbspC/OS-的移植工作包括以下幾個內(nèi)容:   &nbsp用typedef聲明與編譯器相關(guān)的10個數(shù)據(jù)類型(OS_CPU.H)   &nbsp用

20、#define設(shè)置一個常量的值(OS_CPU.H)    #define聲明三個宏(OS_CPU.H)   &nbsp用C語言編寫六個簡單的函數(shù)(OS_CPU_C.C)   &nbsp編寫四個匯編語言函數(shù)(OS_CPU_A.S)   &nbsp根據(jù)這幾項內(nèi)容,本文逐步來完成。   &nbsp2.2.1 INCLUDES.H文件   &nbspINCLUDES.H &#

21、160;  &nbsp是主頭文件,在所有后綴名為.C的文件的開始都包含INCLUDES.H文件。使用INCLUDES.H的好處是所有的.C文件都只包含一   &nbsp個頭文件,簡潔,可讀性強(qiáng)。缺點是.C文件可能會包含一些它并不需要的頭文件,增加編譯時間。我們是以增加編譯時間   &nbsp為代價來換取程序的可移植性的。用戶可以改寫INCLUDES.H文件,增加自己的頭文件,但必須加在文件末尾。   &nbsp程序清單L2.2.1INCLUDES.H.&

22、#160;   #include<iom128v.h>/ ATmega128的寄存器頭文件    #include<macros.h>/ ICCAVR的宏    #include<stdio.h>    #include<string.h>    #include<ctype.h>    #include&l

23、t;stdlib.h>/一些C語言的標(biāo)準(zhǔn)庫    /*    *    *C/OS- 頭文件    *    */    #include"G:PortingICCAVRporting12_8ATmega128os_cpu.h"    #include"G:PortingICCAVR

24、Porting12_8EX1_mega128os_cfg.h"    #include"G:PortingICCAVRPorting12_8SOURCEucos_ii.h"   &nbsp要注意,C/OS- 的3個頭文件的先后順序是:os_cpu.h,os_cfg.h最后是ucos_ii.h。   &nbsp2.2.2 OS_CPU.H文件   &nbspOS_CPU.H包括了用#define定義的與處理器相關(guān)的

25、常量、宏和類型定義。其中需要注意以下三點:   &nbsp一是堆棧的生長方向。正如前面所述,ATmega128的堆棧生長方向是向下生長,即從高地址到低地址,因此,OS_STK_GROWT   &nbspH要被定義為1。   &nbsp二是進(jìn)入臨界代碼段(critical code section)的方法。C/OS-II提供了三種進(jìn)入臨界代碼段的方法,第一種方法是直接對   &nbsp中斷允許位置1或清零,即進(jìn)入臨界代碼段時,把中斷允許位清零,退

26、出臨界代碼段時,把中斷允許位置1;第二種方法是   &nbsp進(jìn)入臨界代碼段時,先將中斷狀態(tài)保存到堆棧中,然后關(guān)閉中斷。與之對應(yīng)的是,退出臨界代碼段時,從堆棧中恢復(fù)前面   &nbsp保存的中斷狀態(tài)。第三種方法是,由于某些編譯提供了擴(kuò)展功能,用戶可以得到當(dāng)前處理器狀態(tài)字的值,并將其保存在C函   &nbsp數(shù)的局部變量之中。這個變量可用于恢復(fù)狀態(tài)寄存器SREG的值。由于ICCAVR不提供此項擴(kuò)展功能,所以本文暫不考慮用第   &nbsp三種方法

27、進(jìn)入臨界代碼段。第一種方法存在著一個小小的問題:如果在關(guān)閉中斷后調(diào)用C/OS-II的功能函數(shù),當(dāng)函數(shù)返   &nbsp回后,中斷可能會被打開。我們希望如果在調(diào)用C/OS-II的功能函數(shù)前,中斷是關(guān)著的,那么在函數(shù)返回后,中斷仍然是   &nbsp關(guān)著的。方法1顯然不滿足要求。本文使用C/OS-II的第二種方法先將中斷狀態(tài)保存到堆棧中,然后關(guān)閉中斷。    &nbsp三是任務(wù)切換函數(shù)OS_TASK_SW( )是個宏,具體的實現(xiàn)是在OSCtxSw( )(OS_CPU_A.S)中

28、0;  &nbsp程序清單L 2.2.2 OS_CPU.H.    #ifdefOS_CPU_GLOBALS    #define OS_CPU_EXT    #else    #define OS_CPU_EXTextern    #endif    /*    *  

29、  *數(shù)據(jù)類型    * (與編譯器相關(guān)的內(nèi)容)    *    */   &nbsptypedef unsigned char BOOLEAN;   &nbsptypedef unsigned char INT8U;/ 無符號8位數(shù)    &nbsptypedef signed char INT8S;/ 帶符號8位數(shù)   

30、 &nbsptypedef unsigned intINT16U;/ 無符號16位數(shù)    &nbsptypedef signed intINT16S;/ 帶符號16位數(shù)    &nbsptypedef unsigned long INT32U;/ 無符號32位數(shù)    &nbsptypedef signed long INT32S;/ 帶符號32位數(shù)    &nbsptypedef floatFP32; / 單精度浮點數(shù) &

31、#160;  &nbsptypedef unsigned charOS_STK;/ 堆棧入口寬度為8位    &nbsptypedef unsigned charOS_CPU_SR;/ 定義狀態(tài)寄存器為8位    /*    *    *    *方法 #1:用簡單指令開關(guān)中斷。    *注意,用方法1關(guān)閉中斷,從調(diào)用函數(shù)返回后中斷

32、會重新打開!    * 方法 #2:關(guān)中斷前保存中斷被關(guān)閉的狀態(tài).    *     *    */    #defineOS_CRITICAL_METHOD 2    #ifOS_CRITICAL_METHOD = 1    #defineOS_ENTER_CRITICAL()_CLI()/ 關(guān)閉中斷 &#

33、160;  #defineOS_EXIT_CRITICAL()_SEI() / 打開中斷    #endif    #ifOS_CRITICAL_METHOD = 2    #defineOS_ENTER_CRITICAL()asm("st -y,r16n in r16,0x3Fn clin push    &nbspr16n    &nbspld r16,y+"

34、;);/ 關(guān)閉中斷     #defineOS_EXIT_CRITICAL()asm("st -y,r16n pop r16n out 0x3F,r16n ld         &nbspr16,y+");/ 打開中斷     #endif    #defineOS_STK_GROWTH1 / 堆棧向下生長    #defineOS_TAS

35、K_SW() OSCtxSw()   &nbsp2.2.3 OS_CPU_C.C文件   &nbspC/OS-II的移植需要用戶編寫OS_CPU_C.C中的十個函數(shù):   &nbspOSTaskStkInit();   &nbspOSInitHookBegin ();   &nbspOSInitHookEnd ();   &nbspOSTaskCreateHook();

36、   &nbspOSTaskDelHook();   &nbspOSTaskSwHook();   &nbspOSTaskStatHook();   &nbspOSTimeTickHook();   &nbspOSTCBInitHook ();   &nbspOSTaskIdleHook ();   &nbsp實際需要修改的只有OS

37、TaskStkInit()函數(shù),其它九個函數(shù)都是由用戶定義的。如果用戶需要使用這九個函數(shù),可將文件OS    _CFG.H中的#define constant OS_CPU_HOOKS_EN設(shè)為1,設(shè)為0表示不使用這些函數(shù)。本文自定義的任務(wù)堆棧結(jié)構(gòu)下圖所示   &nbsp。函數(shù)OSTaskStkInit()是由OSTaskCreate()或OSTaskCreateExt()調(diào)用,用來初始化任務(wù)堆棧的。經(jīng)初始化后的任務(wù)堆棧   &nbsp應(yīng)該跟發(fā)生過一次中斷后任務(wù)的堆棧結(jié)構(gòu)一樣。由

38、前敘述可知,ATmega128在發(fā)生中斷后,自動保存了程序計數(shù)器PC。為了   &nbsp保存全部現(xiàn)場,還需要保存狀態(tài)寄存器SREG,R0R31這32個通用寄存器及SP的值。     需要注意的是:C/OS-規(guī)定,在建立任務(wù)時,只能傳遞一個參數(shù)給任務(wù),而且這個參數(shù)是一個指針;ICCAVR編譯器   &nbsp規(guī)定,傳遞給函數(shù)的第一個參數(shù)是放在R16、R17中的,所以在R16、R17的位置中放置的是向任務(wù)傳遞的參數(shù)。R28、R29的   &nb

39、sp值不需要入棧,是因為R28、R29所組成的Y指針被用作軟件堆棧的指針返回給調(diào)用函數(shù)。   &nbsp根據(jù)上述自定義任務(wù)堆棧的結(jié)構(gòu),編寫OSTaskStkInit()。其程序清單如2.2.3所示。   &nbsp程序清單L 2.2.3OS_CPU_C.C    #defineOS_CPU_GLOBALS    #include "G:PortingICCAVRporting12_8EX1_mega128includes.h&qu

40、ot; /包含頭文件    /*    *    * 九個接口函數(shù)(暫未使用)    *    */    #if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203   &nbspvoidOSInitHookBegin (void)  

41、0;         #endif    . .    /*    *    *OSTaskStkInit()    *    */   &nbspOS_STK*OSTaskStkInit (void (*task)(void *p

42、d), void *p_arg, OS_STK *ptos,         &nbspINT16U opt)       &nbspINT8U*psoft_stk;   &nbspINT8U*phard_stk; /為操作AVR單片機(jī)軟、硬件堆棧而建立的臨時指針   &nbspINT16Utmp;   &nbspopt = o

43、pt; /'opt'未使用,此處可防止編譯器的警告    &nbsppsoft_stk = (INT8U *)ptos;/ 載入堆棧指針   &nbspphard_stk = (INT8U *)ptos    - OS_TASK_SOFT_STK_SIZE / 任務(wù)棧棧空間的大小   &nbspL1    + OS_TASK_HARD_STK_SIZE;/ 系統(tǒng)返回的堆棧(硬件堆棧)L2

44、   &nbsptmp= *(INT16U const *)task;    *phard_stk- = (INT8U)tmp;     *phard_stk- = (INT8U)(tmp >> 8); /把任務(wù)入口地址放入硬件堆棧    /*通用寄存器入棧*/    *psoft_stk- = (INT8U)0x00; / R0 = 0x00   &

45、;nbspL3    *psoft_stk- = (INT8U)0x01; / R1 = 0x01    *psoft_stk- = (INT8U)0x02; / R2 = 0x02    *psoft_stk- = (INT8U)0x03; / R3 = 0x03    *psoft_stk- = (INT8U)0x04; / R4 = 0x04    *psoft_stk- = (INT8U)

46、0x05; / R5 = 0x05    *psoft_stk- = (INT8U)0x06; / R6 = 0x06    *psoft_stk- = (INT8U)0x07; / R7 = 0x07    *psoft_stk- = (INT8U)0x08; / R8 = 0x08    *psoft_stk- = (INT8U)0x09; / R9 = 0x09    *psoft_stk-

47、 = (INT8U)0x10; / R10= 0x10    *psoft_stk- = (INT8U)0x11; / R11= 0x11    *psoft_stk- = (INT8U)0x12; / R12= 0x12    *psoft_stk- = (INT8U)0x13; / R13= 0x13    *phard_stk- = (INT8U)tmp;     *phard_stk- =

48、 (INT8U)(tmp >> 8); /把任務(wù)入口地址放入硬件堆棧    /*R16、R17的位置中放置向任務(wù)傳遞的參數(shù)*/   &nbsptmp = (INT16U)p_arg;    *psoft_stk- = (INT8U)tmp;     *psoft_stk- = (INT8U)(tmp >> 8);     *psoft_stk- = (INT8U)0x18;

49、/ R18= 0x18    *psoft_stk- = (INT8U)0x19; / R19= 0x19    *psoft_stk- = (INT8U)0x20; / R20= 0x20    *psoft_stk- = (INT8U)0x21; / R21= 0x21    *psoft_stk- = (INT8U)0x22; / R22=    &nbsp0x22  &#

50、160; *psoft_stk- = (INT8U)0x23; / R23= 0x23     *psoft_stk- = (INT8U)0x24; / R24=    &nbsp0x24     *psoft_stk- = (INT8U)0x25; / R25= 0x25    *psoft_stk- = (INT8U)0x26; / R26= 0x26    *psoft_stk- =

51、 (INT8U)0x27; / R27= 0x27    /*R28、R29用作軟件堆棧的指針儲存在任務(wù)控制塊OS_TCB的OSTCBStkPtr中*/    *psoft_stk- = (INT8U)0x30; / R30= 0x30    *psoft_stk- = (INT8U)0x31; / R31= 0x31L2    *psoft_stk- = (INT8U)0x80; / SREG= 0x80,開全局中 

52、0; &nbsp斷   &nbsptmp = (INT16U)phard_stk;    *psoft_stk- = (INT8U)(tmp >> 8); / SPH    *psoft_stk= (INT8U) tmp; / SPL   &nbspreturn (void *)psoft_stk);       &nbspL1OS_

53、TASK_SOFT_STK_SIZE是指用戶任務(wù)棧棧空間的大小,這個值在Os_cfg.h中設(shè)定。決定任務(wù)棧??臻g的大小是一件   &nbsp很困難的事情,因為不僅要計算任務(wù)本身的需求(局部變量、函數(shù)調(diào)用等),還需要計算最多中斷嵌套層數(shù)(保存寄存器   &nbsp,中斷服務(wù)子程序的局部變量等)。在本文的移植過程中,所建任務(wù)不是特別復(fù)雜,所以將任務(wù)棧??臻g的大小設(shè)定為80   &nbsp。   &nbspL2OS_TASK_HARD_STK_SIZ

54、E 是指默認(rèn)的系統(tǒng)硬件堆棧空間的大小,這個值也是在Os_cfg.h中設(shè)定。本文設(shè)定為20,因為   &nbsp在程序嵌套程度不是很深的情況下,20個字節(jié)的硬件堆??臻g是足夠了。當(dāng)OS_TASK_HARD_STK_SIZE設(shè)定為20時,應(yīng)該在IC   &nbspCAVR編譯器中,把Complier Option ->Target下的Return Stack    &nbspSize也設(shè)置為20。這樣設(shè)置后,編譯器才會將硬件堆???#160;  &nb

55、sp間按照我們所希望的大小分配。需要注意的是:任務(wù)棧棧空間要根據(jù)具體的微處理器來定義,比如8051系列的微處理器沒   &nbsp有軟件堆棧和硬件堆棧的概念,就不需要在任務(wù)棧中劃分硬件堆??臻g了。   &nbspL3在初始化用以保存通用寄存器的區(qū)域時,本文不放零而放與寄存器標(biāo)號一致的十六進(jìn)制數(shù),是為了在測試代碼的時候   &nbsp方便從內(nèi)存中找出任務(wù)棧。   &nbsp2.2.4 OS_CPU_A.S文件   &

56、amp;nbspC/OS-II 的移植需要用戶編寫OS_CPU_A.S中的四個函數(shù):OSStartHighRdy();   &nbspOSTaskSwitch();   &nbspOSIntCtxSw();   &nbspOSTickISR();   &nbsp這些函數(shù)涉及到出棧和入棧操作,因此需要用匯編語言編寫。注意,在ICCAVR中,匯編語言文件是以.S而不是.asm作為文   &nbsp件后綴名的。&

57、#160;   (1) OSStartHighRdy()   &nbsp該函數(shù)由OSStart()函數(shù)調(diào)用,功能是在多任務(wù)調(diào)度開始時運行優(yōu)先級最高的就緒任務(wù)。它主要完成三件事:一是通知操作   &nbsp系統(tǒng),多任務(wù)調(diào)度已經(jīng)開始;二是使SP指向優(yōu)先級最高的就緒任務(wù)的任務(wù)棧棧頂;三是恢復(fù)最高優(yōu)先級任務(wù)的運行環(huán)境   &nbsp各CPU寄存器的內(nèi)容等。函數(shù)OSStartHighRdy()的代碼如程序清單224-1所示。   &

58、amp;nbsp程序清單224-1 OSStartHighRdy( )    _OSStartHighRdy: CALL _OSTaskSwHook;調(diào)用用戶定義的任務(wù)切換接口函數(shù)   &nbspLDSR16,_OSRunning ;表明多任務(wù)調(diào)度開始   &nbspL1   &nbspINCR16   &nbspSTS_OSRunning,R16 ;OSRunning變?yōu)椤癟RUE” 

59、0;      &nbspLDSR30,_OSTCBHighRdy;讓Z指針指向優(yōu)先級最高的   &nbspLDSR31,_OSTCBHighRdy+1;任務(wù)的任務(wù)控制塊TCB   &nbspLDR28,Z+;將任務(wù)棧的指針裝入   &nbspLDR29,Z+;Y寄存器中        &nbspPOP_SP;裝入當(dāng)前任務(wù)的SP 

60、0; &nbspPOP_SREG;裝入當(dāng)前任務(wù)的SREG   &nbspPOP_ALL ;裝入當(dāng)前任務(wù)的寄存器   &nbspRET;開始執(zhí)行當(dāng)前任務(wù)L2   &nbspL1    &nbspICCAVR規(guī)定:在匯編程序中,向編譯器聲明一個全局變量是在該變量的標(biāo)識符前加上一條下劃線作為前綴。_OSRunning表   &nbsp示OSRunning是一個全局變量;向編譯器聲明一個外部函數(shù)則

61、是在該函數(shù)的標(biāo)識符前加上一條下劃線并在其后加上兩個冒號   &nbsp。_OSStartHighRdy:表示OSStartHighRdy是個外部函數(shù),其它C言語文件可以以O(shè)SStartHighRdy()的形式對它   &nbsp進(jìn)行調(diào)用。   &nbspL2 POP_SP,POP_SREG,POP_ALL是三個宏。其作用是恢復(fù)任務(wù)現(xiàn)場。當(dāng)執(zhí)行RET指令后,當(dāng)前任務(wù)的地址將被裝入PC,   &nbsp從而開始執(zhí)行當(dāng)前任務(wù)。任務(wù)現(xiàn)場的恢復(fù)順序應(yīng)該同

62、自定義的任務(wù)棧的存儲順序一致,否則會出現(xiàn)出入棧錯誤?,F(xiàn)給出POP    _ALL詳細(xì)代碼,請讀者比照OSTaskStkInit()函數(shù)初始化后任務(wù)棧進(jìn)行理解。其余宏代碼的編寫,與POP_ALL類同。   &nbsp程序清單POP_ALL    _.macro POP_ALL ;重新裝載所有的通用寄存器   &nbspLDR31,Y+   &nbspLDR30,Y+   &a

63、mp;nbspLDR27,Y+L1   &nbspLDR26,Y+   &nbspLDR25,Y+   &nbspLDR24,Y+   &nbspLDR23,Y+   &nbspLDR22,Y+   &nbspLDR21,Y+   &nbspLDR20,Y+   &nbspLDR19,Y+

64、60;  &nbspLDR18,Y+   &nbspLDR17,Y+   &nbspLDR16,Y+   &nbspLDR15,Y+   &nbspLDR14,Y+   &nbspLDR13,Y+   &nbspLDR12,Y+   &nbspLDR11,Y+   &

65、nbspLDR10,Y+   &nbspLDR9,Y+   &nbspLDR8,Y+   &nbspLDR7,Y+   &nbspLDR6,Y+   &nbspLDR5,Y+   &nbspLDR4,Y+   &nbspLDR3,Y+   &nbspLDR2,Y+  

66、0;&nbspLDR1,Y+   &nbspLDR0,Y+    .endmacro   &nbspL1OSTaskStkInit()中沒有給R28和R29留存儲空間,所以POP_ALL里面也不能將R28和R29彈出。    (2) OSCtxSw()   &nbspOSCtxSw()是一個任務(wù)級的任務(wù)切換函數(shù),它主要完成以下幾件事:保存當(dāng)前任務(wù)現(xiàn)場;保存當(dāng)前任務(wù)的任務(wù)棧指針到當(dāng)前 &

67、#160; &nbsp任務(wù)的任務(wù)控制塊;切換最高優(yōu)先級任務(wù)為當(dāng)前任務(wù);使SP指向最高優(yōu)先級任務(wù)的任務(wù)棧的棧頂;恢復(fù)新任務(wù)的運行環(huán)境   &nbsp。由于ATmega128沒有軟中斷指令,只能通過匯編子程序來模擬中斷。OSCtxSw()程序如程序清單224-4所示。   &nbsp程序清單224-2 OSCtxSw( )    _OSCtxSw:PUSH_ALL;保存當(dāng)前任務(wù)現(xiàn)場   &nbspPUSH_SREG &

68、#160; &nbspPUSH_SP   &nbspLDSR30,_OSTCBCur保存當(dāng)前任務(wù)的堆棧指針   &nbspLDSR31,_OSTCBCur+1 到當(dāng)前任務(wù)的任務(wù)控制塊TCB   &nbspSTZ+,R28   &nbspSTZ+,R29    &nbspCALL _OSTaskSwHook調(diào)用用戶接口程序 L1   &nbspLDSR1

69、6,_OSPrioHighRdy 把最高優(yōu)先級的任務(wù)切換為當(dāng)前任務(wù)   &nbspSTS_OSPrioCur,R16OSPrioCur = OSPrioHighRdy   &nbspLDSR30,_OSTCBHighRdyZ = OSTCBHighRdy->OSTCBStkPtr   &nbspLDSR31,_OSTCBHighRdy+1   &nbspSTS_OSTCBCur,R30 將新任務(wù)的任務(wù)棧指針保存到L2  

70、; &nbspSTS_OSTCBCur+1,R31任務(wù)控制塊中   &nbspLDR28,Z+裝載新任務(wù)的任務(wù)棧指針   &nbspLDR29,Z+   &nbspPOP_SP恢復(fù)任務(wù)的運行環(huán)境   &nbspPOP_SREG   &nbspPOP_ALL   &nbspRET轉(zhuǎn)到新任務(wù)中去執(zhí)行   &nbspL1

71、如果這個由用戶定義的接口程序不用,可以把它注釋掉,這樣可以節(jié)約節(jié)約幾個時鐘周期。   &nbspL2雖然新任務(wù)有可能還是原來正在運行的任務(wù),如果原來任務(wù)的優(yōu)先級仍然是最高的話。這里的新任務(wù)指經(jīng)過任務(wù)切   &nbsp換后,即將運行的任務(wù)。    (3) OSIntCtxSw()   &nbsp由于中斷可能會使更高優(yōu)先級的任務(wù)進(jìn)入就緒態(tài)。為了讓更高優(yōu)先級的任務(wù)能立即運行,所以需要在中斷中進(jìn)行任務(wù)切換   &

72、nbsp。在中斷服務(wù)子程序的最后,OSIntExit()函數(shù)會調(diào)用OSIntCtxSw()做任務(wù)切換。OSIntCtxSw()是一個中斷級的任務(wù)切換   &nbsp函數(shù)。由于在此之前,中斷服務(wù)程序已經(jīng)保存了被中斷任務(wù)的現(xiàn)場,因此不需要再保存現(xiàn)場了。中斷級任務(wù)切換函數(shù)OSInt   &nbspCtxSw()的其它操作跟OSCtxSw()一樣,它的程序如程序清單224-3所示。   &nbsp程序清單224-3 OSIntCtxSw( )    

73、_OSIntCtxSw:   &nbspCALL _OSTaskSwHook調(diào)用用戶接口程序   &nbspLDSR16,_OSPrioHighRdy 把最高優(yōu)先級的任務(wù)切換為當(dāng)前任務(wù)   &nbspSTS_OSPrioCur,R16OSPrioCur = OSPrioHighRdy   &nbspLDSR30,_OSTCBHighRdyZ = OSTCBHighRdy->OSTCBStkPtr   &

74、;nbspLDSR31,_OSTCBHighRdy+1   &nbspSTS_OSTCBCur,R30 將新任務(wù)的堆棧指針保存到   &nbspSTS_OSTCBCur+1,R31任務(wù)控制塊中   &nbspLDR28,Z+裝載新任務(wù)任務(wù)棧的指針   &nbspLDR29,Z+   &nbspPOP_SP恢復(fù)任務(wù)運行的環(huán)境   &nbspPOP_SREG    &nbspPOP_ALL   &nbspRET轉(zhuǎn)到新任務(wù)中去執(zhí)行    (4) OSTickISR()   &nbspC/OS-II要求用戶提供一個周期行的時鐘源,來實現(xiàn)時間的延時和超時功能。為了達(dá)到這一要求,可以使用硬件定時器,也可以從交流電中獲得50/60Hz的時鐘頻率。本文是采用ATmega128的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論