1. gzyueqian
      18078865874
      首頁 > 新聞中心 > > 正文

      μC/OS-Ⅱ在ATmega128上的移植Step by Step

      更新時間: 2007-06-27 09:42:32來源: 粵嵌教育瀏覽量:790

        本文詳細介紹了把μC/OS-Ⅱ移植到ATMEL公司的8位微控制器ATmega128上的全過程。所謂移植,就是使一個實時內核能在某個微處理器或微控制器上運行。在移植之前,希望讀者能熟悉所用微處理器和C編譯器的特點。

        1 ATmega128的內核特點

        之所以要先介紹ATmega128 MCU內核特點,是因為在μC/OS-Ⅱ的移植過程中,仍需要用戶用C語言和匯編語言編寫一些與微處理器相關的代碼。這里主要介紹ATmega128與μC/OS-Ⅱ移植相關的內核特點。如果讀者已經對ATmega128 比較了解了,那就不必閱讀這一部分了。

        1.1微控制器 (MCU)

        ATmega128的MCU包括一個算術邏輯單元(ALU),一個狀態寄存器(SREG),一個通用工作寄存器組和一個堆棧指針。狀態寄存器(SREG)的位I是全局中斷允許位。如果全局中斷允許位為零,則所有中斷都被禁止。當系統響應一個中斷后,I位將由硬件自動清“0”;當執行中斷返回(RETI)指令時,I位由硬件自動置“1”,從而允許系統再次響應下一個中斷請求。

        通用工作寄存器組是由32個8位的通用工作寄存器組成。其中R26~R31這6個寄存器還可以兩兩合并為3個16位的間接地址寄存器。這些寄存器可以用來對數據存儲空間進行間接尋址。這3個間接地址寄存器的名稱為:X寄存器、Y寄存器、Z寄存器。其中Z寄存器還能用作對程序存儲空間進行間接尋址的寄存器。有些AVR C語言編譯器還把Y寄存器作為軟件堆棧的堆棧指針,比如ICC- AVR,CodevisionAVR。

        堆棧指針(SP)是一個指示堆棧頂部地址的16位寄存器。在ICCAVR中,它被用作指向硬件堆棧的堆棧指針。AVR單片機上電復位后,SP指針的初始值為0x0000,由于AVR單片機的堆棧是向下生長的(從高地址向低地址生長),所以系統程序一開始必須對堆棧指針SP進行初始化,即將SP的值設為數據存儲空間的地址。ICCAVR編譯器在鏈接C程序文件的時候,會自動在程序頭鏈入startup文件。startup文件里面的程序將會去做初始化SP指針的工作。鏈入startup文件是ICCAVR這個編譯器的特點,在用其它編譯器的時候,希望讀者確認所使用的編譯器是否帶有自動初始化SP的功能,若沒有,應在用戶程序中初始化SP。

        1.2 數據存儲空間(僅內部)

        AVR單片機的數據存儲器是線形的,從低地址到高地址依次是CPU寄存器區(32個通用寄存器),I/O寄存器區,數據存儲區。

        ICCAVR編譯器又將數據存儲區劃分為全局變量和字符串區,軟件堆棧區和硬件堆棧區三個空間。

        ICCAVR編譯器將堆棧分成了兩個功能不同的堆棧來處理(這一點與8051系列的單片機編譯器處理方式不同)。硬件堆棧用于儲存子程序和中斷服務子程序調用時的函數返回地址。這塊數據區域由堆棧指針SP進行尋址,數據的進棧和出棧有專門的匯編指令(pop,push等)支持,所以叫做硬件堆棧區。軟件堆棧用于傳遞參數,儲存臨時變量和局部變量。這塊數據區域是用軟件模擬堆棧儲存數據的方式進行數據存儲,對該區域尋址的指針由用戶自己定義,所以叫做軟件堆棧區。

        AVR單片機的硬件堆棧的生長方向是向下的(從高地址向低地址生長),所以軟件堆棧在定義的時候,也采取相同的生長方向。

        這里沒有用ATmega128而采用AVR單片機的提法是因為ATmega128屬于AVR系列單片機中的一種,而所有的AVR單片機的數據存儲器組織方式都是一致的。在創建μC/OS-Ⅱ的任務棧時,需要了解所用微處理器數據存儲空間尤其是堆??臻g的組織形式及相關的操作。讀者應參閱所用微處理器的資料和編譯器的幫助文檔,了解該部分知識。

        1.3 ATmega128的中斷響應機制

        ATmega128有34個不同的中斷源,每個中斷源和系統復位在程序存儲空間都有一個獨立的中斷向量(中斷入口地址)。每個中斷源都有各自獨立的中斷允許控制位,當某個中斷源的中斷允許控制位為“1”且全局中斷允許位I也為“1”時,系統才響應該中斷。
          
        當系統響應一個中斷請求后,會自動將全局中斷允許位I清零,此時,后續中斷響應被屏蔽。當系統執行中斷返回指令RETI時,會將全局中斷允許位I置“1”,以允許響應下一個中斷。若用戶想實現中斷嵌套,必須在中斷服務子程序中將全局中斷允許位I置“1”。(這一點與8051系列的單片機不同)
          
        在中斷向量表中,處于低地址的中斷具有高的優先級。優先級高只是表明在多個中斷同時發生的時候,系統先響應優先級高的中斷,并不含有高優先級的中斷能打斷低優先級的中斷處理工程的意思。這與8051系列單片機的中斷優先級概念不同。
          
        由于μC/OS-Ⅱ的任務切換實際上是模擬一次中斷,因此需要知道CPU的中斷響應機制。中斷發生時,ATmega128按以下步驟順序執行:

        A. 全局中斷允許位I清零。
        B. 將指向下一條指令的PC值壓入堆棧,同時堆棧指針SP減2。
        C. 選擇優先級的中斷向量裝入PC,程序從此地址繼續執行中斷處理。
        D. 當執行中斷處理時,中斷源的中斷允許控制位清零。
        中斷結束后,執行RETI指令,此時
        A. 全局中斷允許位I置“1”。
        B. PC從堆棧推出,程序從被中斷的地方繼續執行。

        特別要注意的是:AVR單片機在響應中斷及從中斷返回時,并不會對狀態寄存器SREG和通用寄存器自動進行保存和恢復操作,因此,對狀態寄存器SREG和通用寄存器的中斷保護工作必須由用戶來完成。

        1.4 ATmega128的定時器中斷
         
        ATmega128有三個定時器:T0,T1,T2;它們三者都有計數溢出中斷功能,而且T1和T2還有匹配比較中斷,即定時器計數到設定的值時,產生中斷并自動清零。若系統采用這種中斷方式,其好處是在中斷服務程序ISR中不需要重新裝載定時器的值。但本文出于通用性的考慮,仍采用定時器計數溢出中斷方式。

        2 μC/OS-Ⅱ的移植

        2.1移植條件

        要實現μC/OS-Ⅱ的移植,所用的處理器和編譯器必須滿足一定的條件:

        (1) 所用的C編譯器能產生可重入代碼。
        
        可重入代碼是指可以被一個以上的任務調用,而不必擔心其數據會被破壞的代碼。可重入代碼任何時候都可以被中斷,一段時間以后又可以重新運行,而相應的數據不會丟失,不可重入代碼則不行。本文所使用ImageCraft公司的ICCAVR V6.29編譯器能產生可重入代碼。

       ?。?) 用C語言就可以打開和關閉中斷。

        本文所使用的ICCAVR V6.29編譯器支持在C語言中內嵌匯編語句且提供專門開關中斷的宏:CLI()和SEI()。這樣,使得在C語言中開關中斷非常方便。

       ?。?) 處理器支持中斷,并且能產生定時中斷(通常在10至100Hz之間)本文使用的ATmega128,有3個定時器,能產生μC/OS-Ⅱ所需的定時中斷。

        (4) 處理器支持能夠容納一定數量數據的硬件堆棧。本文使用的ATmega128有4K RAM,硬件堆??梢蚤_辟在這4K RAM中。

       ?。?) 處理器有將堆棧指針和其它CPU寄存器從內存中讀出和存儲到堆?;騼却嬷械闹噶?。一般的單片機都滿足這個要求(如PUSH、POP指令),且ATmega128還具有直接訪問I/O寄存器的指令(IN、OUT等),它比8051系列的單片機更容易實現上述要求。

        2.2移植的實現

        μC/OS-Ⅱ的移植工作包括以下幾個內容:

        用typedef聲明與編譯器相關的10個數據類型(OS_CPU.H)
        用#define設置一個常量的值(OS_CPU.H)
        #define聲明三個宏(OS_CPU.H)
        用C語言編寫六個簡單的函數(OS_CPU_C.C)
        編寫四個匯編語言函數(OS_CPU_A.S)
        根據這幾項內容,本文逐步來完成。

        2.2.1 INCLUDES.H文件

        INCLUDES.H

        是主頭文件,在所有后綴名為.C的文件的開始都包含INCLUDES.H文件。使用INCLUDES.H的好處是所有的.C文件都只包含一個頭文件,簡潔,可讀性強。缺點是.C文件可能會包含一些它并不需要的頭文件,增加編譯時間。我們是以增加編譯時間為代價來換取程序的可移植性的。用戶可以改寫INCLUDES.H文件,增加自己的頭文件,但必須加在文件末尾。程序清單L2.2.1  INCLUDES.H.
        #include  <iom128v.h>                 // ATmega128的寄存器頭文件
        #include  <macros.h>                  // ICCAVR的宏
        #include  <stdio.h>
        #include  <string.h>
        #include  <ctype.h>
        #include  <stdlib.h>                 //一些C語言的標準庫

        /*
        ***************************************************************************
        *                  μC/OS-Ⅱ 頭文件
        ***************************************************************************
        */
        #include  "G:\Porting\ICCAVR\porting12_8\ATmega128\os_cpu.h"
        #include  "G:\Porting\ICCAVR\Porting12_8\EX1_mega128\os_cfg.h"
        #include  "G:\Porting\ICCAVR\Porting12_8\SOURCE\ucos_ii.h"

        要注意,μC/OS-Ⅱ 的3個頭文件的先后順序是:os_cpu.h,os_cfg.h是ucos_ii.h。

        2.2.2 OS_CPU.H文件

        OS_CPU.H包括了用#define定義的與處理器相關的常量、宏和類型定義。其中需要注意以下三點:

        一,是堆棧的生長方向。正如前面所述,ATmega128的堆棧生長方向是向下生長,即從高地址到低地址,因此,OS_STK_GROWTH要被定義為1。

        二,是進入臨界代碼段(critical code section)的方法。μC/OS-II提供了三種進入臨界代碼段的方法,種方法是直接對中斷允許位置1或清零,即進入臨界代碼段時,把中斷允許位清零,退出臨界代碼段時,把中斷允許位置1;第二種方法是進入臨界代碼段時,先將中斷狀態保存到堆棧中,然后關閉中斷。與之對應的是,退出臨界代碼段時,從堆棧中恢復前面保存的中斷狀態。第三種方法是,由于某些編譯提供了擴展功能,用戶可以得到當前處理器狀態字的值,并將其保存在C函數的局部變量之中。這個變量可用于恢復狀態寄存器SREG的值。由于ICCAVR不提供此項擴展功能,所以本文暫不考慮用第三種方法進入臨界代碼段。種方法存在著一個小小的問題:如果在關閉中斷后調用μC/OS-II的功能函數,當函數返回后,中斷可能會被打開。我們希望如果在調用μC/OS-II的功能函數前,中斷是關著的,那么在函數返回后,中斷仍然是關著的。方法1顯然不滿足要求。本文使用μC/OS-II的第二種方法——先將中斷狀態保存到堆棧中,然后關閉中斷。

        三,是任務切換函數OS_TASK_SW( )是個宏,具體的實現是在OSCtxSw( )(OS_CPU_A.S)中程序清單L 2.2.2 OS_CPU.H.

        #ifdef  OS_CPU_GLOBALS
        #define OS_CPU_EXT
        #else
        #define OS_CPU_EXT  extern
        #endif

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 亚洲欧美高清精品aⅴ | 色国产综合免费视频在线播放 | 日韩熟女久久久久久 | 在线视频男人的天堂 | 日韩AⅤ精品国内在线 | 中文字幕欧美精品制服丝袜 |