新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > μC/OS-II在80x86上的移植

        μC/OS-II在80x86上的移植

        作者: 時間:2016-10-08 來源:網絡 收藏

        OSTaskStkInit()

        OSTaskCreateHook()

        OSTaskDelHook()

        OSTaskSwHook()

        OSTaskStatHook()

        OSTimeTickHook()

        實際需要修改的只有OSTaskStkInit()函數,其他五個函數需要聲明,但不一定有實際內容。這五個函數都是用戶定義的,所以OS_CPU_C.C中沒有給出代碼。如果用戶需要使用這些函數,請將文件OS_CFG.H中的#define constant OS_CPU_HOOKS_EN設為1,設為0表示不使用這些函數。

        程序清單L 9.9 18.2Hz 的OSTickISR()函數.

        _OSTickISRPROCFAR

        ;

        PUSHA; 保存被中斷任務的CPU環境

        PUSHES

        PUSHDS

        ;

        MOVAX,SEG_OSIntNesting;載入 DS

        MOVDS,AX

        ;

        INCBYTEPTR_OSIntNesting;標示uC/OS-II進入中斷

        ;

        INT081H; 調用DOS的時鐘中斷處理函數

        ;

        CALLFARPTR_OSTimeTick; 調用OSTimeTick()函數

        ;

        CALLFARPTR_OSIntExit;標示uC/OS-IIof中斷結束

        ;

        POPDS; 恢復被中斷任務的CPU環境

        POPES

        POPA

        ;

        IRET; 返回被中斷任務

        ;

        _OSTickISRENDP

        圖F9.7 傳遞參數 pdata的堆棧初始化結構

        9.05.01 OSTaskStkInit()

        該函數由OSTaskCreate()或OSTaskCreateExt()調用,用來初始化任務的堆棧。初始狀態的堆棧模擬發生一次中斷后的堆棧結構。圖F9.7說明了OSTaskStkInit()初始化后的堆棧內容。請注意,圖中的堆棧結構不是調用OSTaskStkInit()任務的,而是新創建任務的。

        當調用OSTaskCreate()或OSTaskCreateExt()創建一個新任務時,需要傳遞的參數是:

        任務代碼的起使地址,參數指針(pdata),任務堆棧頂端的地址,任務的優先級。

        OSTaskCreateExt()還需要一些其他參數,但與OSTask StkInit()沒有關系。

        OSTaskStkInit()(程序清單L9.10)只需要以上提到的3個參數(task,pdata,和ptos)。

        程序清單L 9.10 OSTaskStkInit().

        void*OSTaskStkInit(void(*task)(void*pd),void*pdata,void*ptos,INT16Uopt)

        {

        INT16U*stk;

        opt=opt;/*'opt'未使用,此處可防止編譯器的警告 */

        stk=(INT16U*)ptos;/* 載入堆棧指針 (1)*/

        *stk--=(INT16U)FP_SEG(pdata);/* 放置向函數傳遞的參數 (2)*/

        *stk--=(INT16U)FP_OFF(pdata);

        *stk--=(INT16U)FP_SEG(task);/* 函數返回地址(3)*/

        *stk--=(INT16U)FP_OFF(task);

        *stk--=(INT16U)0x0202;/*SW 設置為中斷開啟 (4)*/

        *stk--=(INT16U)FP_SEG(task);/* 堆棧頂端放置指向任務代碼的指針*/

        *stk--=(INT16U)FP_OFF(task);

        *stk--=(INT16U)0xAAAA;/*AX=0xAAAA(5)*/

        *stk--=(INT16U)0xCCCC;/*CX=0xCCCC*/

        *stk--=(INT16U)0xDDDD;/*DX=0xDDDD*/

        *stk--=(INT16U)0xBBBB;/*BX=0xBBBB*/

        *stk--=(INT16U)0x0000;/*SP=0x0000*/

        *stk--=(INT16U)0x1111;/*BP=0x1111*/

        *stk--=(INT16U)0x2222;/*SI=0x2222*/

        *stk--=(INT16U)0x3333;/*DI=0x3333*/

        *stk--=(INT16U)0x4444;/*ES=0x4444*/

        *stk=_DS;/*DS=當前CPU的 DS寄存器 (6)*/

        return((void*)stk);

        }

        由于80x86堆棧是16位寬的(以字為單位)[程序清單L9.10(1)],OSTaskStkInit()將創立一個指向以字為單位內存區域的指針。同時要求堆棧指針指向空堆棧的頂端。

        筆者使用的BorlandC/C++編譯器配置為用堆棧而不是寄存器來傳送參數pdata,此時參數pdata的段地址和偏移量都將被保存在堆棧中[程序清單L9.10(2)]。

        堆棧中緊接著是任務函數的起始地址[程序清單L9.10(3)],理論上,此處應該為任務的返回地址,但在μC/OS-II中,任務函數必須為無限循環結構,不能有返回點。

        返回地址下面是狀態字(SW)[程序清單L9.10(4)], 設置狀態字也是為了模擬中斷發生后的堆棧結構。堆棧中的SW初始化為0x0202,這將使任務啟動后允許中斷發生;如果設為0x0002,則任務啟動后將禁止中斷。需要注意的是,如果選擇任務啟動后允許中斷發生,則所有的任務運行期間中斷都允許;同樣,如果選擇任務啟動后禁止中斷,則所有的任務都禁止中斷發生,而不能有所選擇。

        如果確實需要突破上述限制,可以通過參數pdata向任務傳遞希望實現的中斷狀態。如果某個任務選擇啟動后禁止中斷,那么其他的任務在運行的時候需要重新開啟中斷。同時還要修改OSTaskIdle()和OSTaskStat()函數,在運行時開啟中斷。如果以上任何一個環節出現問題,系統就會崩潰。所以筆者還是推薦用戶設置SW為0x0202,在任務啟動時開啟中斷。

        堆棧中還要留出各個寄存器的空間,注意寄存器在堆棧中的位置要和運行指令PUSHA,PUSHES,和PUSHDS和壓入堆棧的次序相同。 上述指令在每次進入中斷服務程序時都會調用[程序清單L9.10(5)]。AX,BX,CX,DX,SP,BP,SI,和DI的次序是和指令PUSHA的壓棧次序相同的。如果使用沒有PUSHA指令的8086處理器,就要使用多個PUSH指令壓入上述寄存器,且順序要與PUSHA相同。 在程序清單L9.10中每個寄存器被初始化為不同的值, 這是為了調試方便。

        Borland編譯器支持偽寄存器變量操作,可以用_DS關鍵字取得CPUDS寄存器的值,程序清單

        L9.10中(6)標記處用_DS直接把DS寄存器拷貝到堆棧中。

        堆棧初始化工作結束后,OSTaskStkInit()返回新的堆棧棧頂指針,OSTaskCreate()或

        OSTaskCreateExt()將指針保存在任務的OS_TCB中。

        9.05.02 OSTaskCreateHook()

        OS_CPU_C.C中未定義,此函數為用戶定義。

        9.05.03 OSTaskDelHook()

        OS_CPU_C.C中未定義,此函數為用戶定義。

        9.05.04 OSTaskSwHook()

        OS_CPU_C.C中未定義,此函數為用戶定義。其用法請參考例程3。

        9.05.05 OSTaskStatHook()



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 北宁市| 邯郸县| 新丰县| 斗六市| 时尚| 前郭尔| 渭南市| 左权县| 西峡县| 渑池县| 罗甸县| 阿城市| 隆德县| 阜南县| 扶余县| 建德市| 象山县| 中方县| 舞钢市| 东阳市| 丰县| 辽宁省| 白河县| 唐河县| 繁峙县| 德令哈市| 夏河县| 吴川市| 杭锦后旗| 南江县| 满洲里市| 兴义市| 天津市| 临武县| 台中市| 涿州市| 张家港市| 台山市| 东兰县| 犍为县| 江达县|