九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
對(duì)uC/OS-II 移植到STM32F103VCT6理解

網(wǎng)上看了很多關(guān)于uC/OS-II移植的文章和資料,自己也模仿著做了一個(gè)移植,為了加深理解, 把自己的理解和思路記錄下來(lái),水平有限,歡迎拍磚~

我使用的芯片是ST的STM32F103VCT6,是Cortex-M3內(nèi)核,Cortex-M3內(nèi)核是ARM公司推出的最新的基于ARMv7構(gòu)架的面向微控制領(lǐng)域的處理器。要想移植uC/OS-II,首先要了解uC/OS-II的內(nèi)核結(jié)構(gòu)和Cortex-M3內(nèi)核編程模型:uC/OS-II的內(nèi)核結(jié)構(gòu)如下圖:


現(xiàn)在從上往下看,用戶的應(yīng)用程序在整個(gè)uC/OS-II 的架構(gòu)的最上方,用戶的自己的應(yīng)用程序就屬于這一層的范疇。

接下來(lái)下面的左邊是uC/OS-II 的與處理器無(wú)關(guān)的代碼, 這部分是uC/OS-II 的主要部分, 在移植過(guò)程中是不需要修改的。

右邊是uC/OS-II 與應(yīng)用程序相關(guān)的代碼,OS_CFG.H是為了實(shí)現(xiàn)uC/OS-II 內(nèi)核功能的裁剪。通過(guò)配置這個(gè)頭文件,uC/OS-II 可以方便的實(shí)現(xiàn)裁剪,以適應(yīng)不同的嵌入式系統(tǒng)。而INCLUDE.H則包含了所有的頭文件,INCLUDE.H是一個(gè)主頭文件,它出現(xiàn)在每個(gè).C文件的第1行??梢酝ㄟ^(guò)重新編輯INCLUDE.H,增加自己的頭文件,但頭文件必須添加在頭文件列表的最后。這樣在應(yīng)用程序包含頭文件時(shí)只需要將此頭文件包含進(jìn)去,就能包含uC/OS-II 的所有頭文件了。

最下面是uC/OS-II 與處理器相關(guān)的代碼,這部分是移植工作的只要內(nèi)容,如圖所示,有三個(gè)文件:OS-CPU.H ,OS_CPU_A.ASM和OS_CPU_C.C

OS-CPU.H 包括了用﹟define語(yǔ)句定義的、與處理器相關(guān)的常數(shù)、宏以及類型。 如下所示:

  1. /****************************************************************************** 
  2. *                   定義與處理器無(wú)關(guān)的數(shù)據(jù)類型 
  3. ******************************************************************************/  
  4.   
  5. typedef unsigned char  BOOLEAN;  
  6. typedef unsigned char  INT8U;           /* Unsigned  8 bit quantity       */  
  7. typedef signed   char  INT8S;           /* Signed    8 bit quantity       */  
  8. typedef unsigned short INT16U;          /* Unsigned 16 bit quantity       */  
  9. typedef signed   short INT16S;          /* Signed   16 bit quantity       */  
  10. typedef unsigned int   INT32U;          /* Unsigned 32 bit quantity       */  
  11. typedef signed   int   INT32S;          /* Signed   32 bit quantity       */  
  12. typedef float          FP32;            /* Single precision floating point*/  
  13. typedef double         FP64;            /* Double precision floating point*/  
  14.   
  15. //STM32是32位位寬的,這里OS_STK和OS_CPU_SR都應(yīng)該是32位數(shù)據(jù)類型  
  16. typedef unsigned int   OS_STK;          /* Each stack entry is 32-bit wide*/  
  17. typedef unsigned int   OS_CPU_SR;       /* Define size of CPU status register*/  

--->定義與處理器無(wú)關(guān)的數(shù)據(jù)類型:

在STM32處理器及keil MDK或者IAR編譯環(huán)境中可以通過(guò)查手冊(cè)得知short 類型是16位而int 類型是32位,這對(duì)于Cortex-M3內(nèi)核是一致的。故這部分代碼無(wú)需修改。 盡管μC/OS-II定義了float 類型和double類型,但為了方便移植它們?cè)讦藽/OS-II源代碼中并未使用。為了方便使用堆棧,μC/OS-II定義了一個(gè)堆棧數(shù)據(jù)類型。在Cortex-M3中寄存器為32位,故定義堆棧的長(zhǎng)度也為32位。Cortex-M3狀態(tài)寄存器為32位,定義OS_CPU_SR主要是為了在進(jìn)出臨界代碼段保存狀態(tài)寄存器。

--->臨界代碼斷:

μC/OS-II 為了保證某段代碼的完整執(zhí)行,需要臨時(shí)的關(guān)閉中斷,在這段代碼執(zhí)行完成之后再打開(kāi)中斷。這樣的代碼段稱作臨界代碼段。μC/OSII 通過(guò)定義兩個(gè)宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()來(lái)分別實(shí)現(xiàn)中斷的關(guān)閉和打開(kāi)。一般來(lái)說(shuō),采用方法3 來(lái)實(shí)現(xiàn)這兩個(gè)宏。這兩個(gè)宏分別定義如下

  1. #define      OS_CRITICAL_METHOD     3   
  2. #define      OS_ENTER_CRITICAL()      {cpu_sr = OS_CPU_SR_Save();}     
  3. #define      OS_EXIT_CRITICAL()           {OS_CPU_SR_Restore(cpu_sr);}   

函數(shù)OS_CPU_SR_Save() 和 OS_CPU_SR_Restore(cpu_sr) 在OS_CPU_A.ASM中定義。同時(shí)得注意,在使用這兩個(gè)宏之前,必須定義OS_CPU_SR  cpu_sr;  否則編譯時(shí)將出錯(cuò)。

--->棧的增長(zhǎng)方向

盡管μC/OS-II支持兩種方向生長(zhǎng)的棧,但對(duì)于以Cortex-M3為內(nèi)核的STM32微處理器來(lái)說(shuō),它支持向下增長(zhǎng)的滿棧,故需要定義棧增長(zhǎng)方向宏為1。即定義成如下形式

  1. #define   OS_STK_GROWTH    1   

--->任務(wù)級(jí)任務(wù)切換
任務(wù)級(jí)任務(wù)切換調(diào)用宏OS_TASK_SW()來(lái)實(shí)現(xiàn)。因?yàn)檫@個(gè)宏也是與處理器相關(guān)的,因此這個(gè)宏在OS_CPU_A.ASM中描述。
--->其他函數(shù)聲明
在OS_CPU.H 中,還聲明了以下幾個(gè)函數(shù),這幾個(gè)函數(shù)均在OS_CPU_A.ASM中實(shí)現(xiàn)。

  1. void OSCtxSw(void);   
  2. void OSIntCtxSw(void);      
  3. void OSStartHighRdy(void);     
  4. void OS_CPU_PendSVHandler(void);   
OS_CPU_A.ASM定義了與處理器相關(guān)的代碼

在OS_CPU_A.ASM中實(shí)現(xiàn)的是下面五個(gè)與處理器相關(guān)的函數(shù)。

  1. OS_CPU_SR_Save();   
  2. OS_CPU_SR_Restore();   
  3. OSStartHighRdy();   
  4. OSCtxSw();     
  5. OSIntCtxSw();     

下面介紹每個(gè)函數(shù)的具體實(shí)現(xiàn):

--->關(guān)中斷函數(shù)(OS_CPU_SR_Save())

定義方法3 來(lái)實(shí)現(xiàn)開(kāi)關(guān)中斷。即先保存當(dāng)前的狀態(tài)寄存器然后關(guān)中斷。故關(guān)中斷實(shí)現(xiàn)代碼如下

  1. OS_CPU_SR_Save   
  2.      MRS R0, PRIMASK;  
  3.      CPSID I   
  4.      BX LR   

這也是宏OS_ENTER_CRITICAL()的最終實(shí)現(xiàn)。


--->恢復(fù)中斷函數(shù)(OS_CPU_SR_Restore())

這是宏OS_EXIT_CRITICAL()的最終實(shí)現(xiàn)。也就是將狀態(tài)寄存器的內(nèi)容從R0中恢復(fù),然后跳轉(zhuǎn)回去。此函數(shù)完成的將中斷狀態(tài)恢復(fù)到關(guān)中斷前的狀態(tài)。其代碼如下:

  1. OS_CPU_SR_Restore   
  2.         MSR  PRIMASK,  R0   
  3.         BX LR   

Cortex-M3處理器有單獨(dú)的指令來(lái)打開(kāi)或者關(guān)閉中斷,所以這兩個(gè)函數(shù)實(shí)現(xiàn)起來(lái)很簡(jiǎn)單。

--->啟動(dòng)最高優(yōu)先級(jí)任務(wù)運(yùn)行(OSStartHighRdy())

OSStart()調(diào)用OSStartHighRdy()來(lái)啟動(dòng)最高優(yōu)先級(jí)任務(wù)的運(yùn)行,從而啟動(dòng)整個(gè)系統(tǒng)。OSStartHighRdy()主要完成以下幾項(xiàng)工作:

① 為任務(wù)切換設(shè)置PendSV的優(yōu)先級(jí)

② 為第一次任務(wù)切換設(shè)置棧指針為0,

③ 設(shè)置OSRunning = TRUE,以表明系統(tǒng)正在運(yùn)行

④ 觸發(fā)一次PendSV,打開(kāi)中斷等待第一次任務(wù)的切換。

--->任務(wù)級(jí)和中斷級(jí)任務(wù)切換

因?yàn)镃ortex-M3 進(jìn)入異常自動(dòng)保存寄存器R3-R0,R12,LR,PC和xPSR這種的特殊機(jī)制,這兩個(gè)函數(shù)都是觸發(fā)一次PendSV來(lái)實(shí)現(xiàn)任務(wù)的切換。首先是微處理器自動(dòng)保存上面提到的寄存器,然后把當(dāng)前的堆棧指針保存到任務(wù)的棧中,將要切換的任務(wù)的優(yōu)先級(jí)和任務(wù)控制塊的指針賦值給運(yùn)行時(shí)的最高優(yōu)先級(jí)指針和運(yùn)行時(shí)的任務(wù)控制塊指針,最后再把要運(yùn)行的任務(wù)的堆棧指針賦值給微處理器的堆棧指針,這樣就可以退出中斷服務(wù)程序了。中斷服務(wù)程序退出的時(shí)候?qū)⒆詣?dòng)出棧R3-R0,R12,LR,PC 和xPSR。具體的PendSV服務(wù)程序的偽代碼如下:

  1. OS_CPU_PendSVHandler:  
  2.    //進(jìn)入異常,處理器自動(dòng)保存R3-R0,R12,LR,PC和xPSR     
  3.    if (PSP != NULL) //判斷不是開(kāi)始第一次任務(wù)  
  4.    {   
  5.       保存R4-R11到任務(wù)的堆棧;  
  6.       OSTCBCur->OSTCBStkPtr = SP; //保存堆棧的指針到任務(wù)控制塊  
  7.     }   
  8.    OSTaskSwHook();  //實(shí)現(xiàn)用戶擴(kuò)展功能而定義的鉤子  
  9.    OSPrioCur = OSPrioHighRdy; //設(shè)置運(yùn)行任務(wù)為最高優(yōu)先級(jí)就緒任務(wù)  
  10.    OSTCBCur = OSTCBHighRdy; //設(shè)置運(yùn)行的任務(wù)控制塊為最高  
  11.    //就緒任控制塊務(wù)  
  12.    PSP = OSTCBHighRdy->OSTCBStkPtr;//將要切換的任務(wù)堆棧指  
  13.    //針賦給微處理器的堆棧指  
  14.    //針從而實(shí)現(xiàn)切換  
  15.    從堆棧中恢復(fù)R4-R11;   
  16.    從異常中返回;  
  17.    //退出異常,處理器自動(dòng)恢復(fù)R3-R0,R12,LR,PC和xPSR     
這樣很容易寫出PendSV中斷服務(wù)程序的代碼了。


OS_CPU_C.C定義了與CPU相關(guān)的C函數(shù)和鉤子函數(shù)、

這個(gè)文件中包含10個(gè)函數(shù),具體如下:

  1. OSInitHookBegin ();    
  2. OSInitHookEnd ();   
  3. OSTaskCreateHook ();   
  4. OSTaskDelHook ();     
  5. OSTaskIdleHook ();     
  6. OSTaskStatHook ();    
  7. OSTaskStkInit ();    
  8. OSTaskSwHook ();    
  9. OSTCBInitHook ();    
  10. OSTimeTickHook ();   
這10個(gè)函數(shù)有9個(gè)是為了擴(kuò)展用戶功能而定義的鉤子函數(shù),這些鉤子函數(shù)可以都為空函數(shù),也可以加上一些用戶需要的擴(kuò)展功能。另外一個(gè)不是鉤子函數(shù),

它是OSTaskStkInit ()。這個(gè)函數(shù)的功能是當(dāng)一個(gè)任務(wù)被創(chuàng)建時(shí),它完成這個(gè)任務(wù)堆棧的初始化。這個(gè)函數(shù)首先將用戶為任務(wù)分配的堆棧頂?shù)刂焚x值給一個(gè)棧指針變量,然后再通過(guò)這個(gè)棧指針向任務(wù)的棧空間寫入初值。這個(gè)初值無(wú)關(guān)緊要,為0就可以了。這個(gè)函數(shù)的代碼時(shí)下如下:

  1. /* 
  2. ********************************************************************************************************* 
  3. *                                        INITIALIZE A TASK'S STACK 
  4. * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the 
  5. *              stack frame of the task being created.  This function is highly processor specific. 
  6. * Arguments  : task          is a pointer to the task code 
  7. *              p_arg         is a pointer to a user supplied data area that will be passed to the task 
  8. *                            when the task first executes. 
  9. *              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to 
  10. *                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then 
  11. *                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if 
  12. *                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address 
  13. *                            of the stack. 
  14. *              opt           specifies options that can be used to alter the behavior of OSTaskStkInit(). 
  15. *                            (see uCOS_II.H for OS_TASK_OPT_xxx). 
  16. * Returns    : Always returns the location of the new top-of-stack once the processor registers have 
  17. *              been placed on the stack in the proper order. 
  18. * Note(s)    : 1) Interrupts are enabled when your task starts executing. 
  19. *              2) All tasks run in Thread mode, using process stack. 
  20. ********************************************************************************************************* 
  21. */  
  22.   
  23. OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)  
  24. {  
  25.     OS_STK *stk;  
  26.   
  27.   
  28.     (void)opt;                                   /* 'opt' is not used, prevent warning                 */  
  29.     stk       = ptos;                            /* Load stack pointer                                 */  
  30.   
  31.                                                  /* Registers stacked as if auto-saved on exception    */  
  32.     *(stk)    = (INT32U)0x01000000L;             /* xPSR                                               */  
  33.     *(--stk)  = (INT32U)task;                    /* Entry Point                                        */  
  34.     *(--stk)  = (INT32U)0xFFFFFFFEL;             /* R14 (LR) (init value will cause fault if ever used)*/  
  35.     *(--stk)  = (INT32U)0x12121212L;             /* R12                                                */  
  36.     *(--stk)  = (INT32U)0x03030303L;             /* R3                                                 */  
  37.     *(--stk)  = (INT32U)0x02020202L;             /* R2                                                 */  
  38.     *(--stk)  = (INT32U)0x01010101L;             /* R1                                                 */  
  39.     *(--stk)  = (INT32U)p_arg;                   /* R0 : argument                                      */  
  40.   
  41.                                                  /* Remaining registers saved on process stack         */  
  42.     *(--stk)  = (INT32U)0x11111111L;             /* R11                                                */  
  43.     *(--stk)  = (INT32U)0x10101010L;             /* R10                                                */  
  44.     *(--stk)  = (INT32U)0x09090909L;             /* R9                                                 */  
  45.     *(--stk)  = (INT32U)0x08080808L;             /* R8                                                 */  
  46.     *(--stk)  = (INT32U)0x07070707L;             /* R7                                                 */  
  47.     *(--stk)  = (INT32U)0x06060606L;             /* R6                                                 */  
  48.     *(--stk)  = (INT32U)0x05050505L;             /* R5                                                 */  
  49.     *(--stk)  = (INT32U)0x04040404L;             /* R4                                                 */  
  50.   
  51.     return (stk);  
  52. }  

其他的鉤子函數(shù)都為空函數(shù)。

(1)    OSTaskStkInit( )  初始化任務(wù)的棧結(jié)構(gòu)

              OSTaskCreate( )和OSTaskCreatExt()通過(guò)調(diào)用它來(lái)初始化任務(wù)的棧結(jié)構(gòu);因此,堆??雌饋?lái)就像中斷剛發(fā)生過(guò)一樣,所有的寄存器都保存在堆棧中。另外,在初始化堆棧以后,OSTaskStkInit( )應(yīng)當(dāng)返回堆棧指針?biāo)赶虻牡刂贰?br>(2)    OSTaskCreateHook( )
              每當(dāng)添加任務(wù)時(shí),OS-TCBInit()函數(shù)都會(huì)調(diào)用OSTaskCreateHook( )
函數(shù),當(dāng)其被調(diào)用時(shí),它會(huì)收到指向剛剛建立任務(wù)的任務(wù)控制塊的指針。這樣,它就可以訪問(wèn)任務(wù)控制塊結(jié)構(gòu)的所有的成員了。若用OSTaskCreate()建立任務(wù),OSTaskCreateHook( )的功能是有限的;但若使用OSTaskCreateExt()建立任務(wù)時(shí),會(huì)得到OS-TCB中的擴(kuò)展指針(OSTCBExtPtr)。該指針可用來(lái)訪問(wèn)任務(wù)的附加數(shù)據(jù),如浮點(diǎn)寄存器、MMU寄存器、任務(wù)計(jì)數(shù)器、以及調(diào)試信息??梢詸z查OS-TCBInit()看做了哪些工作。
(3)    OSTaskDelHook( )
              在任務(wù)從就緒列表或等待列表中被刪除后,OSTaskDel()就會(huì)調(diào)用OSTaskDelHook( )。當(dāng)調(diào)用其時(shí),它會(huì)收到一個(gè)指向正在被刪除任務(wù)的任務(wù)控制塊的指針,使它可以訪問(wèn)任務(wù)控制塊結(jié)構(gòu)的所有的成員。
(4)    OSTaskSwHook( )
              任務(wù)切換時(shí)被調(diào)用,可以直接訪問(wèn)OSTCBCur和OSTCBHighRdy這2個(gè)全局變量。OSTCBCur指向?qū)⒈磺袚Q出去的任務(wù)的任務(wù)控制塊,OSTCBHighRdy指向新任務(wù)的任務(wù)控制塊。
(5)    OSTaskIdleHook( )
              OSTaskIdle()可調(diào)用OSTaskIdleHook( )實(shí)現(xiàn)CPU的低功耗模式。
(6)    OSTaskStatHook( )
              每秒都會(huì)被統(tǒng)計(jì)任務(wù)OSTaskStat()調(diào)用一次,可以用其擴(kuò)展統(tǒng)計(jì)任務(wù)功能。例如,可以跟蹤并顯示每個(gè)任務(wù)的執(zhí)行時(shí)間、每個(gè)任務(wù)所用的CPU份額以及每個(gè)任務(wù)執(zhí)行的頻率等等。
(7)    OSTimeTickHook( )
              每個(gè)時(shí)鐘節(jié)拍都會(huì)被OSTimeTick()調(diào)用。
(8)    OSInitHookBegin( )
進(jìn)入OSInit()函數(shù)后,OSInitHookBegin( )就立即被調(diào)用,添加其原因在于,這個(gè)函數(shù)使得用戶可以將自己特定代碼也放在OSInit()中,使代碼簡(jiǎn)潔明了。
(9)    OSInitHookEnd( )
              與OSInitHookBegin( )相似,只是它在OSInit()函數(shù)返回之前被調(diào)用。
(10)OSTCBInitHook( )
             OS-TCBInit()函數(shù)在調(diào)用OSTaskCreateHook( )之前,會(huì)先調(diào)用OSTCBInitHook( )。原因在于,用戶可以在OSTCBInitHook( )中做一些與初始化控制塊OS-TCB有關(guān)的處理;在OSTaskCreateHook( )中做一些以初始化任務(wù)有關(guān)的處理。同OSTaskCreateHook( )一樣,OSTCBInitHook( )會(huì)收到指向新添加任務(wù)的任務(wù)控制塊的指針。

這樣整個(gè)移植的代碼就介紹完了。整個(gè)移植的過(guò)程比較容易。剩下的工作就是編寫用戶任務(wù)了


下面說(shuō)一下Cortex-M3內(nèi)核編程模型:

           Cortex-M3內(nèi)部有20個(gè)寄存器,其模型為圖3-1所示[9]。其中通用寄存器為R0~R12。R13~R15有特殊的用途:R13用于堆棧指針(SP);R14用作鏈接寄存器(LR);R15用作程序計(jì)數(shù)器(PC)。程序狀態(tài)寄存器有三個(gè),分別記錄處理器在三種類型模式下的狀態(tài)。

          它的三種狀態(tài)類型如下所述。Cortex-M3特殊的工作模式和狀態(tài)可以分為特權(quán)級(jí)線程模式、特權(quán)級(jí)處理者模式和用戶級(jí)線程模式。

          Cortex-M3只支持Thumb指令(包括Thumb指令和Thumb2指令)。故在程序中若想跳轉(zhuǎn)到ARM指令狀態(tài)將會(huì)引發(fā)一個(gè)錯(cuò)誤。

          Cortex-M3中斷采用NVIC(嵌套向量中斷控制器)來(lái)管理。除了復(fù)位、不可屏蔽中斷和硬故障外其他的中斷可以配置。它在響應(yīng)中斷進(jìn)入中斷服務(wù)程序時(shí)硬件將自動(dòng)將R0 R3, R12, LR, PSR  ‐ 和PC壓棧,中斷服務(wù)程序結(jié)束時(shí),又將它們自動(dòng)彈出。這個(gè)入棧出棧順序極其重要。在后面講到的PendSV中會(huì)用到。

         Cortex-M3內(nèi)核還粗線條的定義了存儲(chǔ)映射。在每一個(gè)范圍對(duì)應(yīng)哪一種外設(shè)都在內(nèi)核構(gòu)架上定義好了,半導(dǎo)體廠商可以根據(jù)自己具體的需要來(lái)實(shí)現(xiàn)存儲(chǔ)映射的細(xì)節(jié)。這一點(diǎn)很方便代碼在不同廠商生產(chǎn)的微處理器上移植。Cortex-M3寄存器模型如下所示:









本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
uC/OS
UC/OS-II的詳細(xì)移植筆記 兩種處理器的移植比較(S1C33209&&S3C44BOX)
移植時(shí)的一些概念
μC/OS-Ⅱ的移植問(wèn)題
μC/OS移植到ATmega128
uCOS II的移植步驟
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服