久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8420|回復: 5
打印 上一主題 下一主題
收起左側

STC單片機uCOS-II移植教程

  [復制鏈接]
跳轉到指定樓層
樓主
ID:555185 發(fā)表于 2020-2-12 12:44 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
前言
       其實關于uCOS-II的51單片機移植教程和例子網(wǎng)上已經(jīng)有很多了,但是大部分都是基于Proteus仿真外擴內存的,下載之后也不能直接在硬件上使用,也沒有具體的移植教程。這對于一個想學習操作系統(tǒng)而又無從下手小白的來說簡直就是噩夢。
       由于51內核的特殊性和keil編譯器原因(51的系統(tǒng)堆棧指針和Keil編譯后仿真堆棧指針增長的方向是相反的)帶來移植的困難。網(wǎng)上的例程處理堆棧的方式有兩種(至于不太懂的同學可以移步看看這篇帖子)https://blog.csdn.net/s111sw/article/details/6012720,一種是用小模式Small,另外一種是大模式Large。Small模式是把系統(tǒng)堆棧數(shù)據(jù)和仿真堆棧數(shù)據(jù)一起復制到用戶堆棧XDATA區(qū),這種方式編譯代碼小但是任務切換速度慢。而Large模式在編譯的時候Keil默認是把仿真堆棧數(shù)據(jù)設置在XDATA區(qū),所以在任務切換的時候只需要把系統(tǒng)堆棧和仿真堆棧的當前地址保存到用戶堆棧就行,這樣的方式編譯代碼大但任務切換速度快(現(xiàn)在都是用這種方式,STC12C5A60S2在22.1184MHz晶振下任務切換時間37us)。可是,前面已經(jīng)說了51的系統(tǒng)堆棧指針是向上增長的,而Keil編譯的仿真指針是向下增長的,這就導致了一個 問題---uCOS操作系統(tǒng)的堆棧檢測函數(shù)OSTaskStkChk沒辦法使用。上面鏈接帖子里面用的方法是修改uCOS的內核函數(shù)實現(xiàn)堆棧檢測功能的。正是因為我不想修改內核函數(shù)的原因所以才有了我現(xiàn)在移植的uCOS的版本。
                                                                                                                                                                                                         
圖1

雖然51的系統(tǒng)堆棧指針只能向上增長,但是在代碼里面我們可以人為的把里面的數(shù)據(jù)按照自己的意愿存放到用戶堆棧里。下面是我移植的堆棧結構,把系統(tǒng)堆棧增長方向和仿真堆棧統(tǒng)一起來就可以實現(xiàn)堆棧連續(xù)存放數(shù)據(jù)了。
                                                                                                                                                                                                         
                                                                                                                   圖2
開始移植
準備工具
1、    電腦一臺(廢話!)
2、    Keil4
3、    下載配套的代碼一份,我移植的是比較經(jīng)典的版本uCOS-II 2.52

51_uCOS-II V2.52.zip (376.83 KB, 下載次數(shù): 101)
STC uCOS-II移植教程.pdf (252.53 KB, 下載次數(shù): 82)
下載的代碼已經(jīng)是移植好STC12C5A60S2的例程
功能就是兩個任務用堆棧檢測函數(shù)OSTaskStkChk檢測當前自己堆棧使用情況,然后串口發(fā)出
波特率115200

下面開始講解怎么把uCOS移植到不同型號51單片機
打開工程\51_uCOS-IIV2.52\Project\ uCOS.uvproj

第1步:把keil配置為大模式,就是讓Keil把默認變量定義到XDATA,下圖3                                                                                           圖3
第2步:打開STARTUP .A51啟動文件修改一些啟動參數(shù)來對應單片機資源
    根據(jù)單片機內部資源作調整,因為STC12C5A60S2有1280字節(jié)的SRAM,包括內部0-0xFF 256字節(jié)和外部0-0x3FF 1024字節(jié)
圖4把IDATALEN改成100H(內部256),XDATALEN改成0x03FF(外部內存根據(jù)不同型號芯片的大小配置,最大是0xFFFF),這樣單片機初始化的時候就會把相應的RAM清0。

                      圖4  
接著把圖5的XBPSTACK設置為1使能圖6的仿真堆棧初始化代碼,XBPSTACKTOP設置成 0x03FF,就是單片機外部RAM的末尾地址。
                                    
       圖5

                                                                                                            
                       圖6
這樣就配置好啟動文件了。
第3 步:配置uCOS文件
     uCOS系統(tǒng)需要一個時鐘節(jié)拍,節(jié)拍頻率10Hz-1000Hz。我用的是T0定時器每10ms中斷一次。打開OS_CPU_C.C文件找到void InitHardware(void)  T0定時器初始化函數(shù),配置成想要的中斷時間,然后修改中斷函數(shù)void OSTickISR(void) interrupt 1里面TL0和TL1的初值,如果是有 自動重裝功能的定時器就可以注釋掉這兩句,最后配置OS_CFG.H文件里最下面的宏定義#define  OS_TICKS_PER_SEC,這個就是1秒鐘的節(jié)拍數(shù),例如10ms中斷一次就是100,20ms中斷一次就是50。
#define  OS_TICKS_PER_SEC100  /* Set the number of ticks in one second */
----------------------------------移植完畢---------------------------------------

堆棧結構解釋
                               圖7
        任務創(chuàng)建之后堆棧指針一直指向用戶棧頂,圖7左是堆棧初始化之后里面的數(shù)據(jù)結構,用戶堆棧的最高3個字節(jié)一直固定保存“系統(tǒng)堆棧長度”和“?C_XBP(仿真堆棧指針)”因為任務初始化的時候仿真堆棧還沒有使用,所以?C_XBP指向的堆棧下一個地址就是空閑堆棧,緊跟著就是系統(tǒng)堆棧數(shù)據(jù)。
        在啟動任務調度置后仿真堆棧被使用之后變成圖7右的結構,任務切換時從?C_XBP指向的下一個地址開始保存系統(tǒng)堆棧數(shù)據(jù),保存的數(shù)據(jù)長度由“系統(tǒng)堆棧長度” 決定 ,這樣就實現(xiàn)了堆棧向下連續(xù)增長而不需要修改uCOS的堆棧檢測函數(shù)。

//堆棧初始化函數(shù)
OS_STK *OSTaskStkInit(void (*task)(void *pd) reentrant, void *p_arg, OS_STK *ptos, INT16U opt)reentrant
{
    OS_STK *stk;

    p_arg =p_arg;
    opt    = opt;                      //opt沒被用到,保留此語句防止告警產(chǎn)生   
    stk    =ptos;                     //用戶堆棧最低有效地址
    *stk-- =15;                       //系統(tǒng)堆棧長度
*stk-- =(INT16U)(ptos-3) >> 8; //?C_XBP 仿真堆棧指針高8位
   *stk-- = (INT16U)(ptos-3) &0xFF; //?C_XBP 仿真堆棧指針低8位 最高3個字節(jié)一直被占
//用所以減3
    *stk-- =0x07;                          //R7
    *stk-- =0x06;                          //R6
    *stk-- =0x05;                          //R5
    *stk-- =0x04;                          //R4
    *stk-- =0x01;                          //R3
    *stk-- =0x02;                     //R2
    *stk-- =0x01;                    //R1
    *stk-- =0x00;                          //R0
    *stk-- =0x00;                          //PSW
    *stk-- =0x00;                          //DPL
    *stk-- =0x00;                          //DPH
    *stk-- =0x0B;                          //B  
*stk-- =0x0A;                          //ACC
    *stk-- =(INT16U)task >> 8;             //任務地址高8位  
    *stk-- =(INT16U)task & 0xFF;           //任務地址低8位

stk    = ptos;//堆棧指針一直指向棧頂

    return stk;
}


;*****************************************************************************************
;*                                              uC/OS-II
;*                                               實時內核
;*
;*                        (c) Copyright1992-1998, Jean J. Labrosse, Plantation, FL
;*                                               版權所有
;*
;*                                           MCU-51 專用代碼
;*                                           KEIL C51大模式編譯
;*
;* 文件名 : OS_CPU_A.ASM
;* 作者  : Jean J. Labrosse
;*****************************************************************************************


;聲明:本代碼僅供學習研究uCOS-II使用,如用作其他用途出現(xiàn)問題本人概不負責。

;偽指令詳細用法請查A51.PDF文件
;程序結構詳見《uC/OS-II》193-198頁

;不用此語句!!! $CASE    ;標號和變量名區(qū)分大小寫

$NOMOD51
EA  BIT     0A8H.7
SP  DATA    081H
B   DATA    0F0H
ACC DATA    0E0H
DPH DATA    083H
DPL DATA    082H
PSW DATA    0D0H
TR0 BIT     088H.4
TH0 DATA    08CH
TL0 DATA    08AH

        NAMEOS_CPU_A    ;模塊名

;定義重定位段
?PR?OSStartHighRdy?OS_CPU_A    SEGMENT CODE
?PR?OSCtxSw?OS_CPU_A           SEGMENT CODE
?PR?OSIntCtxSw?OS_CPU_A        SEGMENT CODE

;?PR?OSTickISR?OS_CPU_A         SEGMENT CODE
;?PR?_?serial?OS_CPU_A          SEGMENT CODE

;聲明引用全局變量和外部子程序
        EXTRNDATA  (?C_XBP)     ;仿真堆棧指針用于重入局部變量保存,為V2.51能被C使用定義在本模塊中

        EXTRNIDATA (OSTCBCur)
        EXTRNIDATA (OSTCBHighRdy)
        EXTRNIDATA (OSRunning)
        EXTRNIDATA (OSPrioCur)
        EXTRN IDATA (OSPrioHighRdy)
     EXTRNDATA  (EA_Nesting)

;        EXTRNCODE  (OSTaskSwHook)
        EXTRNCODE  (OSIntEnter)
        EXTRNCODE  (OSIntExit)
        EXTRNCODE  (OSTimeTick)

;對外聲明4個不可重入函數(shù)
        PUBLICOSStartHighRdy
        PUBLICOSCtxSw
        PUBLICOSIntCtxSw

;        PUBLICOSTickISR
;        PUBLICSerialISR        


;分配堆棧空間,?STACK和STARTUP.A51中同名,編譯器會將兩個?STACK段合并,堆棧大小在STARTUP.A51中定義
?STACK    SEGMENT   IDATA
          RSEG    ?STACK
;-------------------------------------------------------------------------------
PUSHALL    MACRO ;定義壓棧出棧宏
        PUSH ACC
        PUSH B
        PUSH DPH
        PUSH DPL
        PUSH PSW
     MOV  PSW,#0x00
        PUSH0x00   ;R0-R7入棧
     PUSH 0x01
     PUSH 0x02
     PUSH 0x03
     PUSH 0x04
     PUSH 0x05
     PUSH 0x06
     PUSH 0x07
        ENDM

POPALL    MACRO
        POP  0x07   ;R0-R7出棧
     POP  0x06
     POP  0x05
     POP  0x04
     POP  0x03
     POP  0x02
     POP  0x01
     POP  0x00
        POP  PSW
        POP  DPL
        POP  DPH
        POP  B
        POP  ACC
        ENDM
;-------------------------------------------------------------------------
;    啟動任務------切換堆棧指針,恢復堆棧數(shù)據(jù)
;-------------------------------------------------------------------------
        RSEG?PR?OSStartHighRdy?OS_CPU_A
OSStartHighRdy:
        USING0    ;
;       LCALL OSTaskSwHook
CtxSw:
       ;OSTCBCur ===> DPTR  獲得當前TCB指針,詳見C51.PDF第178頁
        MOV  R0,#LOW (OSTCBCur) ;獲得OSTCBCur指針低地址,
        INC  R0                  ;指針占3字節(jié)。+0類型+1高8位數(shù)據(jù)+2低8位數(shù)據(jù)
        MOV  DPH,@R0        ;全局變量OSTCBCur在IDATA中
        INC  R0
        MOV  DPL,@R0

       ;OSTCBCur->OSTCBStkPtr ===> DPTR 獲得用戶堆棧指針
        INC  DPTR       ;指針占3字節(jié)。+0類型+1高8位數(shù)據(jù)+2低8位數(shù)據(jù)
        MOVXA,@DPTR     ;取用戶棧頂指針OSTCBStkPtr
     MOV  R0,A
        INC  DPTR
        MOVXA,@DPTR

     ADD  A,#0FEH    ;DPTR-2指向保存?C_XBP低8位的地址
     MOV  DPL,A
     MOV  A,R0
     ADDC A,#0FFH
     MOV  DPH,A

     ;恢復仿真堆棧指針
     MOVX A,@DPTR
     MOV  ?C_XBP+1,A ;?C_XBP仿真堆棧指針低8位
     INC  DPTR
     MOVX A,@DPTR   
     MOV  ?C_XBP,A   ;?C_XBP仿真堆棧指針高8位

     INC  DPTR
        MOVXA,@DPTR    ;恢復系統(tǒng)堆棧長度
        MOV  R5,A      ;
     ;因為DPTR沒有自減1指令,所以只能計算出系統(tǒng)堆棧的末尾地址然后用INC DPTR復制數(shù)據(jù)提高效率
     CLR  C          ;系統(tǒng)堆棧末尾地址 = 當前仿真堆棧地址-系統(tǒng)堆棧長度
     MOV  A,?C_XBP+1
     SUBB A,R5
     MOV  DPL,A
     MOV  A,?C_XBP
     SUBB A,#0
     MOV  DPH,A

        MOV  R0,#?STACK-1 ;獲取堆棧起址

RestoreStk:          ;恢復現(xiàn)場堆棧內容
     INC DPTR        
        INC  R0
        MOVXA,@DPTR
        MOV  @R0,A
        DJNZR5,RestoreStk

        MOV  SP,R0 ;恢復堆棧指針SP

       ;OSRunning=TRUE
        MOV  R0,#LOW (OSRunning)
        MOV  @R0,#01

        POPALL

     MOVEA_Nesting,#0 ;切換任務清零EA嵌套
        SETBEA    ;開中斷
        RETI
;-------------------------------------------------------------------------
;    任務級切換函數(shù)
;-------------------------------------------------------------------------
        RSEG?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
        PUSHALL;任務堆棧進棧
IntCtxSw:
       ;OSTCBCur ===> DPTR  獲得當前TCB指針,詳見C51.PDF第178頁
        MOV  R0,#LOW (OSTCBCur) ;獲得OSTCBCur指針低地址,指針占3字節(jié)。+0類型+1高8位數(shù)據(jù)+2低8位數(shù)據(jù)
        INC  R0
        MOV  DPH,@R0  ;全局變量OSTCBCur在IDATA中
        INC  R0
        MOV  DPL,@R0

       ;OSTCBCur->OSTCBStkPtr ===> DPTR 獲得用戶堆棧指針
        INC  DPTR       ;指針占3字節(jié)。+0類型+1高8位數(shù)據(jù)+2低8位數(shù)據(jù)
        MOVXA,@DPTR     ;取用戶棧頂指針OSTCBStkPtr
     MOV  R0,A
        INC  DPTR
        MOVXA,@DPTR

     ADD  A,#0FEH    ;DPTR-2指向保存?C_XBP低8位的地址
     MOV  DPL,A
     MOV  A,R0
     ADDC A,#0FFH
     MOV  DPH,A

     ;保存仿真堆棧指針?C_XBP
     MOV  A,?C_XBP+1 ;?C_XBP 仿真堆棧指針低8位
     MOVX @DPTR,A
     INC  DPTR
     MOV  A,?C_XBP   ;?C_XBP 仿真堆棧指針高8位
     MOVX @DPTR,A

        MOV  A,SP ;計算系統(tǒng)堆棧長度
        CLR  C
        SUBBA,#?STACK-1
        MOV  R5,A
     ;保存系統(tǒng)堆棧長度
     INC  DPTR
     MOVX @DPTR,A
     ;因為DPTR沒有自減1指令,所以只能計算出系統(tǒng)堆棧的末尾地址然后用INC DPTR復制數(shù)據(jù)提高效率
     CLR  C          ;系統(tǒng)堆棧末尾地址 = 當前仿真堆棧地址-系統(tǒng)堆棧長度
     MOV  A,?C_XBP+1
     SUBB A,R5
     MOV  DPL,A
     MOV  A,?C_XBP
     SUBB A,#0
     MOV  DPH,A

        MOV  R0,#?STACK-1 ;獲取堆棧起址
SaveStk:
     INC  DPTR   ;保存系統(tǒng)堆棧到任務堆棧
     INC  R0
     MOV  A,@R0
     MOVX @DPTR,A
     DJNZR5,SaveStk

;    LCALL OSTaskSwHook  ;調用用戶程序

     ;獲取新任務TCB指針
     MOV  R0,#OSTCBCur   ;OSTCBCur= OSTCBHighRdy
     MOV  R1,#OSTCBHighRdy
     MOV  A,@R1
     MOV  @R0,A  ;指針類型
     INC  R0
     INC  R1
     MOV  A,@R1
     MOV  @R0,A  ;指針高8位
     INC  R0
     INC  R1
     MOV  A,@R1  
     MOV  @R0,A  ;指針低8位

     ;獲取新任務優(yōu)先級
     MOV R0,#OSPrioCur  ;OSPrioCur =OSPrioHighRdy
     MOV  R1,#OSPrioHighRdy
     MOV  A,@R1
     MOV  @R0,A

     LJMP CtxSw
;-------------------------------------------------------------------------
;    中斷級任務切換
;-------------------------------------------------------------------------
        RSEG?PR?OSIntCtxSw?OS_CPU_A
OSIntCtxSw:
        ;調整SP指針去掉在調用OSIntExit(),OSIntCtxSw()過程中壓入堆棧的多余內容
        ;SP=SP-4
        MOV  A,SP
        CLR  C
        SUBBA,#4
        MOV  SP,A

        LJMPIntCtxSw

        END

評分

參與人數(shù) 3黑幣 +60 收起 理由
zmc419 + 5 很給力!
admin + 50 共享資料的黑幣獎勵!
muzhi + 5 很給力!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏19 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發(fā)
ID:108624 發(fā)表于 2021-2-8 15:47 | 只看該作者
寫的不錯! 值得一試!
回復

使用道具 舉報

板凳
ID:677393 發(fā)表于 2021-2-9 10:20 | 只看該作者
哥太牛了,51能上系統(tǒng)
回復

使用道具 舉報

地板
ID:108624 發(fā)表于 2021-2-28 16:03 | 只看該作者
最近又測試了一下。非常好。發(fā)揮了STC的大XDATA. 值得一用!!!!!!!!
回復

使用道具 舉報

5#
ID:576482 發(fā)表于 2022-11-8 10:14 | 只看該作者
哪天吃多了沒事干的時候研究研究!!!
回復

使用道具 舉報

6#
ID:983641 發(fā)表于 2022-11-9 21:25 | 只看該作者
太強大了。。。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩三级免费观看 | 天天夜夜操 | 国产激情偷乱视频一区二区三区 | 手机看黄av免费网址 | 国产高清精品一区 | 国产精品日韩欧美一区二区三区 | 99热精品6 | 欧美亚洲综合久久 | 国产二区视频 | 亚洲欧美日韩精品久久亚洲区 | 91综合网| 国产成人一区二区三区精 | 日本人爽p大片免费看 | 91福利网| 在线看av网址 | 黄色在线免费观看视频 | 四虎网站在线观看 | 日韩欧美在线观看 | 欧洲一区二区三区 | 视频一区二区在线观看 | 蜜桃一区| 久久久精品影院 | 国产1区2区3区 | 69堂永久69tangcom | 91亚洲国产成人久久精品网站 | 久久99精品久久久久久 | 岛国av一区二区 | 亚洲精品国产电影 | 亚洲精品免费观看 | 久久一级大片 | 日日操夜夜操天天操 | 成人在线不卡 | 99re国产精品 | 久久大全 | 日韩一二三区视频 | 国产精品精品久久久 | 欧美黄色大片在线观看 | 国产偷录叫床高潮录音 | 国产精品精品久久久 | 色在线视频网站 | 日韩在线不卡 |