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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

LPC11C14 uCOS II 2.91移植

[復制鏈接]
跳轉到指定樓層
樓主
ID:71922 發表于 2015-1-10 20:23 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
將uCOSii 加入到工程,編譯,如果報以下錯誤錯誤:
compiling ucos_ii.c...
linking...
.\out\test.axf: Error: L6200E: Symbol OSEventTbl multiply defined (by ucos_ii.o and os_core.o).
.\out\test.axf: Error: L6200E: Symbol OSFlagTbl multiply defined (by ucos_ii.o and os_core.o).
.\out\test.axf: Error: L6200E: Symbol OSTaskStatStk multiply defined (by ucos_ii.o and os_core.o).
.\out\test.axf: Error: L6200E: Symbol OSRdyTbl multiply defined (by ucos_ii.o and os_core.o).
.\out\test.axf: Error: L6200E: Symbol OSTaskIdleStk multiply defined (by ucos_ii.o and os_core.o).
.\out\test.axf: Error: L6200E: Symbol OSTCBPrioTbl multiply defined (by ucos_ii.o and os_core.o).
.\out\test.axf: Error: L6200E: Symbol OSTCBTbl multiply defined (by ucos_ii.o and os_core.o).
.... 還有很多
解決方法:將ucos_ii.c  從工程中移除。

如果出現以下未定義錯誤:
.\out\test.axf: Error: L6218E: Undefined symbol OSCtxSw (referred from os_core.o).
.\out\test.axf: Error: L6218E: Undefined symbol OSIntCtxSw (referred from os_core.o).
.\out\test.axf: Error: L6218E: Undefined symbol OSStartHighRdy (referred from os_core.o).
.\out\test.axf: Error: L6218E: Undefined symbol OS_CPU_SR_Restore (referred from os_core.o).
.\out\test.axf: Error: L6218E: Undefined symbol OS_CPU_SR_Save (referred from os_core.o).


是因為 os_cpu_a.s 沒有加入工程,將其加入工程即可解決問題。
------------------------------------------------------------------------
移植步驟:
1、修改OS_CPU.H 文件
    1、重定義與編譯器、uCOS II 有關的數據類型
typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;                    /* Unsigned  8 bit quantity                           */
typedef signed   char  INT8S;                    /* Signed    8 bit quantity                           */
typedef unsigned short INT16U;                   /* Unsigned 16 bit quantity                           */
typedef signed   short INT16S;                   /* Signed   16 bit quantity                           */
typedef unsigned int   INT32U;                   /* Unsigned 32 bit quantity                           */
typedef signed   int   INT32S;                   /* Signed   32 bit quantity                           */
typedef float          FP32;                     /* Single precision floating point                    */
typedef double         FP64;                     /* Double precision floating point                    */

typedef unsigned int   OS_STK;                   /* Each stack entry is 32-bit wide                    */
typedef unsigned int   OS_CPU_SR;                /* Define size of CPU status register (PSR = 32 bits) */

    2、定義中斷的實現方式,一般是為了實現臨界區代碼保護

#define  OS_CRITICAL_METHOD   3
#if OS_CRITICAL_METHOD == 3
#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
#endif

    3、定義棧的生長方式

            /*  堆棧1是從上往下長的,0-從下往上的生長方式         */
        #define  OS_STK_GROWTH        1          /* Stack grows from HIGH to LOW memory on ARM    */

    4、宏定義 優先級任務切換 函數,用于現場保護以及現場恢復實現任務切換
        #define  OS_TASK_SW()         OSCtxSw()        // 任務級任務切換


    5、定義開、關中斷的函數,在保護臨界區代碼時會用到。

#if OS_CRITICAL_METHOD == 3           /* See OS_CPU_A.ASM   */         
OS_CPU_SR  OS_CPU_SR_Save(void);
void         OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endif

    6、聲明函數 這些函數都是要自己實現或修改

void       OSCtxSw(void);                           // 任務級切換 觸發PendSV異常
void       OSIntCtxSw(void);                        // 中斷級切換 觸發PendSV異常
void       OSStartHighRdy(void);                // 運行最高優先級的任務
void       OS_CPU_PendSVHandler(void);         // 發生PendSV異常時被觸發,OSCtxSw()、OSIntCtxSw() 最終實現 即任務切換                                               
void       OS_CPU_SysTickHandler(void);        /* See OS_CPU_C.C                                    */
void       OS_CPU_SysTickInit(void);          // 系統時鐘節拍初始化 用于任務切換                                                  
INT32U     OS_CPU_SysTickClkFreq(void);        /* See BSP.C OS_CPU_SysTickInit(void);用來獲得硬件的時鐘頻率,這里是直接指定并沒有用上。*/
OS_CPU_PendSVHandler(void)、OS_CPU_SysTickHandler(void) 需要在 startup_LPC11xx.s 定義
           



2、修改OS_CPU_C.C  文件
1、修改OSTaskStkInt()函數
    主要修改OSTaskStkInit()函數,其他的HOOK函數根據需要實現(將文件OS_CFG.H中的#define constant OS_CPU_HOOKS_EN設為1,設為0表示不使用這些函數
    用戶創建任務時,OSTasKCreat()會調用OSTaskStkInt()函數初始化該任務的堆棧,并把返回的堆棧指針保存到該任務的TCB結構中
    的最前面的參數OSTCBStkPtr中,當該任務要被恢復時,任務切換函數從其TCB塊中取得其任務堆棧指針,依次將堆棧內容彈到處理器
    對應的CPSR、r0、r1,…,r12,lr,pc的寄存器中,完成現場的恢復和程序指針PC的返回。


// 創建任務時被調用 初始化任務堆棧  具體實現不是很明白
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)

{
    OS_STK *stk;
    (void)opt;                                   /* 'opt' is not used, prevent warning                 */
    stk       = ptos;                            /* Load stack pointer 獲取堆棧指針                    */


                                                 /* Registers stacked as if auto-saved on exception    */
    *(stk)    = (INT32U)0x01000000L;             /* xPSR                                               */
    *(--stk)  = (INT32U)task;                    /* Entry Point 保存任務函數地址                       */
    *(--stk)  = (INT32U)0xFFFFFFFEL;             /* R14 (LR) (init value will cause fault if ever used)*/
    *(--stk)  = (INT32U)0x12121212L;             /* R12                                                */
    *(--stk)  = (INT32U)0x03030303L;             /* R3                                                 */
    *(--stk)  = (INT32U)0x02020202L;             /* R2                                                 */
    *(--stk)  = (INT32U)0x01010101L;             /* R1                                                 */
    *(--stk)  = (INT32U)p_arg;                   /* R0 : argument  保存參數                            */


                                                 /* Remaining registers saved on process stack         */
    *(--stk)  = (INT32U)0x11111111L;             /* R11                                                */
    *(--stk)  = (INT32U)0x10101010L;             /* R10                                                */
    *(--stk)  = (INT32U)0x09090909L;             /* R9                                                 */
    *(--stk)  = (INT32U)0x08080808L;             /* R8                                                 */
    *(--stk)  = (INT32U)0x07070707L;             /* R7                                                 */
    *(--stk)  = (INT32U)0x06060606L;             /* R6                                                 */
    *(--stk)  = (INT32U)0x05050505L;             /* R5                                                 */
    *(--stk)  = (INT32U)0x04040404L;             /* R4                                                 */


    return (stk);
}



  2、實現  void  OS_CPU_SysTickInit (void)、void  OS_CPU_SysTickHandler (void)
        // 初始化SysTick 用于在固定時產生中斷

void  OS_CPU_SysTickInit (void)
{
    INT32U  cnts;
    /* cnts = OS_CPU_SysTickClkFreq() / OS_TICKS_PER_SEC; */
        cnts = 48000000 / OS_TICKS_PER_SEC;        // OS_TICKS_PER_SEC 10ms 產生一次中斷


    OS_CPU_CM3_NVIC_ST_RELOAD = (cnts - 1);
        OS_CPU_CM3_NVIC_ST_CURRENT = 0;


        /* Set Priority of SysTick to 2 (0-3, 0 is highest)   */
        cnts = OS_CPU_CM0_NVIC_SHPR3;
        cnts &= 0x00FFFFFF;
        cnts |= 0x80000000;
        OS_CPU_CM0_NVIC_SHPR3 = cnts;
                                                 /* Enable timer.                                      */
    OS_CPU_CM3_NVIC_ST_CTRL  |= OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC | OS_CPU_CM3_NVIC_ST_CTRL_ENABLE;
                                                 /* Enable timer interrupt.                            */
    OS_CPU_CM3_NVIC_ST_CTRL  |= OS_CPU_CM3_NVIC_ST_CTRL_INTEN;
}


    // SysTick中斷服務函數 用于產生系統節拍
void  OS_CPU_SysTickHandler (void)
{
    OS_CPU_SR  cpu_sr;

    OS_ENTER_CRITICAL();                         /* Tell uC/OS-II that we are starting an ISR          */
    OSIntNesting++;
    OS_EXIT_CRITICAL();
    OSTimeTick();                                /* Call uC/OS-II's OSTimeTick()                       */
    OSIntExit();                                 /* Tell uC/OS-II that we are leaving the ISR          */
}


3、修改OS_CPU_A.S 文件
  1、定義寄存器地址
      NVIC_INT_CTRL   EQU     0xE000ED04                              ; Interrupt control state register.
NVIC_SCB_SHPR3  EQU     0xE000ED20
NVIC_PENDSV_PRI EQU     0x00FF0000
NVIC_PENDSVSET  EQU     0x10000000                              ; Value to trigger PendSV exception.

  2、實現 OS_CPU_SR_Save()、OS_CPU_SR_Restore()、OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()、OS_CPU_PendSVHandler()
  
    // 實現OS_CPU_SR_Save()、OS_CPU_SR_Restore()

    // 通過保存中斷狀態來禁用、啟用中斷 用在
OS_CPU_SR_Save                    ; 保存中斷狀態    MRS     R0, PRIMASK           ; Set prio int mask to mask all (except faults)    CPSID   I    BX      LR
OS_CPU_SR_Restore                 ; 恢復中斷狀態    MSR     PRIMASK, R0    BX      LR

// 實現 OSStartHighRdy()
// 啟動優先級最高的任務
OSStartHighRdy
        ; 設置PendSV 異常優先級為最低
        ldr     r0, =NVIC_SCB_SHPR3                                               
        ldr     r1, [r0]
        ldr     r2, =NVIC_PENDSV_PRI
        orrs    r1, r1, r2
        str     r1, [r0]

    ; 初始化PSP設置為 0    MOVS    R0, #0                                              ; Set the PSP to 0 for initial context switch call    MSR     PSP, R0                                                ; PSP為0 告訴上下文切換,這是第一次運行
    ; 設置 任務運行狀態為 1    LDR     R0, =OSRunning                                      ; OSRunning = TRUE    MOVS    R1, #1    STRB    R1, [R0]
    ; 觸發PendSV 異常,實現任務切換     LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)    LDR     R1, =NVIC_PENDSVSET    STR     R1, [R0]
     ; PendSV 異常處理函數會關閉中斷,所以需要開中斷    CPSIE   I                                                   ; 使能中斷 Enable interrupts at processor level
OSStartHang    B       OSStartHang                                         ; Should never get here

[size=14.44444465637207px]// 實現 OSCtxSw() 任務級切換任務
// 觸發PendSV 異常,實現任務切換
OSCtxSw    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)    LDR     R1, =NVIC_PENDSVSET    STR     R1, [R0]    BX      LR

[size=14.44444465637207px]//
實現 OSIntCtxSw() 中斷級切換任務
// 觸發PendSV 異常,實現任務切換

OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR


;/* Pendsv 中斷函數 */
;/* 用于實現時間片輪轉法 中斷級任務調度、任務級中斷調度 切換上下文*/
; 進入PendSV時:
; xPSR、PC、LR、R12、R0~R3 已經在處理棧中被保存
; 處理模式切換到線程模式
; 棧是主堆棧
OS_CPU_PendSVHandler
    CPSID   I                                                      ; 關閉中斷,避免上下文切換時發送中斷。
    MRS     R0, PSP                             ; PSP is process stack pointer
    ;CBZ     R0, OS_CPU_PendSVHandler_nosave    ; Skip register save the first time
        cmp                r0, #0                                                            ; 如果獲取任務的SP 為0 則跳到 OS_CPU_PendSVHandler_nosave
        beq                OS_CPU_PendSVHandler_nosave

        ; 保存R3~R11和SP
    SUBS    R0, R0, #0x20                       ; Save remaining regs r4-11 on process stack
        stm     r0!, {r4-r7}
        mov     r1, r8
        mov     r2, r9
        mov     r3, r10
        mov     r4, r11
        stm     r0!, {r1-r4}
        subs    r0, r0, #0x20

        ; 將當前的堆棧指針給當前進程的任務塊
    LDR     R1, =OSTCBCur                       ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                            ; R0 is SP of process being switched out

                                                ; At this point, entire context of process has been saved
OS_CPU_PendSVHandler_nosave
    ; 調用 OSTaskSwHook() 函數 用于擴展
        mov     r0, lr
        push    {r0}
        ldr     r0, =OSTaskSwHook
        blx     r0
        pop     {r0}
        mov     lr, r0

        ; 獲取當前最高優先級的任務
    LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    ; 獲取當前就緒的線程
    LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]

        ; 得到新任務的SP和線程恢復 R4~R11
    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
        ldm     r0!, {r4-r7}
        ldm     r0!, {r1-r3}
        mov     r8, r1
        mov     r9, r2
        mov     r10, r3
        ldm     r0!, {r1}
        mov     r11, r1

        ; 載入新的SP和返回
    MSR     PSP, R0                                             ; Load PSP with new process SP
    mov     r0, lr
        movs    r1, #0x04
        orrs    r0, r0, r1
        mov     lr, r0
        CPSIE   I                                  ; 開啟中斷                                                                                               
    BX      LR                                                  ; Exception return will restore remaining context
    b       .
    END

移植uCOS II 的難點在于:函數的實現。
總結:
OS_CPU_C.C:
        void  OS_CPU_SysTickInit (void)、void  OS_CPU_SysTickHandler (void)
        任務調度,產生系統時鐘節拍,每一次節拍就切換一次當前就緒表中優先級最高的任務

OS_CPU_A.S:
        OS_CPU_SR_Save()、OS_CPU_SR_Restore():
        用于任務保存和恢復自身的中斷狀態。用于臨界區代碼。
       
        OSStartHighRdy():
        尋找就緒表中優先級最高的任務。

        OSCtxSw()、OSIntCtxSw()、OS_CPU_PendSVHandler()
        OSCtxSw()、OSIntCtxSw()都是通過觸發PendSV異常進行任務切換
        OSCtxSw():一般是在任務調用延時函數 如OSTimeDlyHMSM(0, 0, 0, 300); 時調用的。

        OSIntCtxSw():一般用在系統時鐘節拍中斷時,會采用這種方式調度新的任務。
        OS_CPU_PendSVHandler() 產生異常PendSV異常就進行一次任務切換







                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: av一级 | 欧美一区二区三区 | 亚洲国产精品一区二区三区 | 欧美小视频在线观看 | 日本免费视频 | 中文字幕高清一区 | 国产成人久久精品 | 久久99蜜桃综合影院免费观看 | 日韩欧美在| 亚洲性在线 | 国产一区亚洲 | 成人在线视 | 日韩视频一区二区三区 | 国产精品不卡 | 日韩欧美在线一区二区 | 五月婷婷中文 | 精品一区二区三区四区五区 | 国产精品1 | 国产精品日本一区二区在线播放 | 国产成人区 | 成人黄页在线观看 | 在线免费观看黄色网址 | 天天摸天天看 | 亚洲精品久久久一区二区三区 | 精品国产伦一区二区三区观看体验 | 欧产日产国产精品视频 | 午夜精品久久久久久久星辰影院 | 91香蕉嫩草 | 韩国av网站在线观看 | 99久久婷婷国产综合精品电影 | 亚洲一区精品在线 | 国产精品一区二区免费 | 久久久久久av | 国产欧美视频一区二区三区 | 911精品美国片911久久久 | 在线看片国产精品 | 国内自拍视频在线观看 | 91视频日本 | 一级免费看 | 欧美成人a | 国产精品五月天 |