0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

uCOS-II系統(tǒng)移植

汽車電子技術(shù) ? 來(lái)源:滑小稽筆記 ? 作者:電子技術(shù)園地 ? 2023-03-01 14:32 ? 次閱讀

23.1 操作系統(tǒng)概述

之前的實(shí)驗(yàn)都是利用單片機(jī)實(shí)現(xiàn)某個(gè)單一功能,但是有時(shí)候需要在兩個(gè)功能同時(shí)運(yùn)行,這時(shí)就需要引入操作系統(tǒng)的概念,操作系統(tǒng)(Operating System,簡(jiǎn)稱OS)是一種管理電腦硬件與軟件資源的程序,同時(shí)也是計(jì)算機(jī)系統(tǒng)的內(nèi)核與基礎(chǔ),操作系統(tǒng)大致包括5種功能:進(jìn)程管理,作業(yè)管理,存儲(chǔ)管理,設(shè)備管理與文件管理。

23.1.1 操作系統(tǒng)分類

操作系統(tǒng)有三種基本類型:多道程序系統(tǒng),分時(shí)系統(tǒng),實(shí)時(shí)系統(tǒng),最初操作系統(tǒng)是不支持這種微型單片機(jī)的運(yùn)行的,隨著科技的發(fā)展才產(chǎn)生了針對(duì)于這種M系列內(nèi)核的嵌入式操作系統(tǒng),常見(jiàn)的嵌入式操作系統(tǒng)有FreeeRTOSuCos,uC-Linux(一種Linux精簡(jiǎn)版本),在STM32中一般運(yùn)用FreeRTOS和uCos這兩種系統(tǒng),Linux由于必須有內(nèi)存才能運(yùn)行,一般Linux系統(tǒng)需要大約200M的存儲(chǔ)空間才能裝下,我們這里采用uCos-II系統(tǒng)為例來(lái)進(jìn)行嵌入式操作系統(tǒng)的移植實(shí)驗(yàn)。

23.1.2 uCOS簡(jiǎn)介

uCos系統(tǒng)最早出自于1992年美國(guó)嵌入式專家Jean J.Labrosse發(fā)表在《嵌入式系統(tǒng)編程》上的,并在該雜志的BBS上發(fā)布了源碼,發(fā)展到現(xiàn)在uCos-III已經(jīng)出來(lái),但是目前使用最廣泛的還是uCos-II,本單元我們采用uCos-II來(lái)進(jìn)行介紹。

   uCos-II是一個(gè)可以基于ROM運(yùn)行的,可裁剪的,搶占式,實(shí)時(shí)多任務(wù)內(nèi)核,采用C語(yǔ)言進(jìn)行編寫,這是一種專門為計(jì)算機(jī)的嵌入式應(yīng)用設(shè)計(jì)的,CPU硬件相關(guān)部分采用匯編語(yǔ)言編寫,執(zhí)行效率高,占用空間小,最小內(nèi)核可編譯至2Kbyte,uCos-II體系結(jié)構(gòu)如下圖所示。

圖片

從上圖可以發(fā)現(xiàn),我們移植系統(tǒng)的時(shí)候,只需要修改os_cpu.h,os_cpu_a.asm和os_cpu.c等三個(gè)文件即可,其中其中:os_cpu.h,進(jìn)行數(shù)據(jù)類型的定義,以及處理器相關(guān)代碼和幾個(gè)函數(shù)原型;os_cpu_a.asm,是移植過(guò)程中需要匯編完成的一些函數(shù),主要就是任務(wù)切換函數(shù);os_cpu.c,定義一些用戶HOOK函數(shù)。

圖中定時(shí)器的作用是為UCOS-II提供系統(tǒng)時(shí)鐘節(jié)拍,實(shí)現(xiàn)任務(wù)切換和任務(wù)延時(shí)等功能。這個(gè)時(shí)鐘節(jié)拍由OS_TICKS_PER_SEC(在os_cfg.h中定義)設(shè)置,一般我們?cè)O(shè)置uCos-II的系統(tǒng)時(shí)鐘節(jié)拍為1ms~100ms,具體根據(jù)你所用處理器和使用需要來(lái)設(shè)置。我們利用STM32F1的SYSTICK定時(shí)器來(lái)提供UCOS-II時(shí)鐘節(jié)拍。

uCos-II早期版本只支持64個(gè)任務(wù),但是從2.80版本開(kāi)始,支持任務(wù)數(shù)提高到255個(gè),不過(guò)對(duì)我們來(lái)說(shuō)一般64個(gè)任務(wù)都是足夠多了,一般很難用到這么多個(gè)任務(wù)。uCos-II保留了最高4個(gè)優(yōu)先級(jí)和最低4個(gè)優(yōu)先級(jí)的總共8個(gè)任務(wù),用于拓展使用,但實(shí)際上,uCos-II一般只占用了最低2個(gè)優(yōu)先級(jí),分別用于空閑任務(wù)(倒數(shù)第一)和統(tǒng)計(jì)任務(wù)(倒數(shù)第二),所以剩下給我們使用的任務(wù)最多可達(dá)255-2=253個(gè)(V2.91)。

所謂的任務(wù),其實(shí)就是一個(gè)死循環(huán)函數(shù),該函數(shù)實(shí)現(xiàn)一定的功能,一個(gè)工程可以有很多這樣的任務(wù)(最多255個(gè)),uCos-II對(duì)這些任務(wù)進(jìn)行調(diào)度管理,讓這些任務(wù)可以并發(fā)工作(不是同時(shí)工作,并發(fā)只是各任務(wù)輪流占用CPU,而不是同時(shí)占用,任何時(shí)候還是只有1個(gè)任務(wù)能夠占用CPU),這就是uCos-II最基本的功能。

uCos-II的任何任務(wù)都是通過(guò)一個(gè)叫任務(wù)控制塊(TCB)的東西來(lái)控制的,每個(gè)任務(wù)管理塊有3個(gè)最重要的參數(shù):1,任務(wù)函數(shù)指針;2,任務(wù)堆棧指針;3,任務(wù)優(yōu)先級(jí);任務(wù)控制塊就是任務(wù)在系統(tǒng)里面的身份證(uCos-II通過(guò)優(yōu)先級(jí)識(shí)別任務(wù))

在uCos-II中,使用CPU的時(shí)候,優(yōu)先級(jí)高(數(shù)值?。┑娜蝿?wù)比優(yōu)先級(jí)低的任務(wù)具有優(yōu)先使用權(quán),即任務(wù)就緒表中總是優(yōu)先級(jí)最高的任務(wù)獲得CPU使用權(quán),只有高優(yōu)先級(jí)的任務(wù)讓出CPU使用權(quán)(比如延時(shí))時(shí),低優(yōu)先級(jí)的任務(wù)才能獲得CPU使用權(quán)。uCos-II不支持多個(gè)任務(wù)優(yōu)先級(jí)相同,也就是每個(gè)任務(wù)的優(yōu)先級(jí)必須不一樣。任務(wù)的調(diào)度其實(shí)就是CPU運(yùn)行環(huán)境的切換

uCos-II的每個(gè)任務(wù)都是一個(gè)死循環(huán)。每個(gè)任務(wù)都處在以下5種狀態(tài)之一的狀態(tài)下,這5種狀態(tài)是:睡眠狀態(tài)、就緒狀態(tài)、運(yùn)行狀態(tài)、等待狀態(tài)(等待某一事件發(fā)生)和中斷服務(wù)狀態(tài)。

(1)睡眠狀態(tài):任務(wù)在沒(méi)有被配備任務(wù)控制塊或被剝奪了任務(wù)控制塊時(shí)的狀態(tài)。

(2)就緒狀態(tài):系統(tǒng)為任務(wù)配備了任務(wù)控制塊且在任務(wù)就緒表中進(jìn)行了就緒登記,任務(wù)已經(jīng)準(zhǔn)備好了,但由于該任務(wù)的優(yōu)先級(jí)比正在運(yùn)行的任務(wù)的優(yōu)先級(jí)低,還暫時(shí)不能運(yùn)行,這時(shí)任務(wù)的狀態(tài)叫做就緒狀態(tài)。

(3)運(yùn)行狀態(tài):該任務(wù)獲得CPU使用權(quán),并正在運(yùn)行中,此時(shí)的任務(wù)狀態(tài)叫做運(yùn)行狀態(tài)。

(4)等待狀態(tài):正在運(yùn)行的任務(wù),需要等待一段時(shí)間或需要等待一個(gè)事件發(fā)生再運(yùn)行時(shí),該任務(wù)就會(huì)把CPU的使用權(quán)讓給別的任務(wù)而使任務(wù)進(jìn)入等待狀態(tài)。

(5)中斷服務(wù)狀態(tài):一個(gè)正在運(yùn)行的任務(wù)一旦響應(yīng)中斷申請(qǐng)就會(huì)中止運(yùn)行而去執(zhí)行中斷服務(wù)程序,這時(shí)任務(wù)的狀態(tài)叫做中斷服務(wù)狀態(tài)。

uCos-II任務(wù)的5個(gè)狀態(tài)轉(zhuǎn)換關(guān)系如圖

圖片

23.1.3 uCOS-II中與任務(wù)相關(guān)的函數(shù)

(1)創(chuàng)建進(jìn)程:OSTaskCreate

函數(shù)原型:OSTaskCreate( void( *task )( void *pd ), void *pdata, OS_STK *ptos, INTU prio )

函數(shù)參數(shù):

task:指向任務(wù)代碼的指針

pdata:任務(wù)開(kāi)始執(zhí)行時(shí),傳遞給任務(wù)的參數(shù)的指針

ptos:分配給任務(wù)的堆棧的棧頂指針

prio:分配給任務(wù)的優(yōu)先級(jí)

每個(gè)任務(wù)都有自己的堆棧,堆棧必須申明為OS_STK類型,并且由連續(xù)的內(nèi)存空間組成??梢造o態(tài)分配堆??臻g,也可以動(dòng)態(tài)分配堆??臻g。

(2)刪除進(jìn)程

函數(shù)原型:INT8U OSTaskDel( INT8U prio )

函數(shù)參數(shù):

prio:進(jìn)程的優(yōu)先級(jí),該函數(shù)是通過(guò)任務(wù)優(yōu)先級(jí)來(lái)實(shí)現(xiàn)任務(wù)刪除的

(3)請(qǐng)求刪除進(jìn)程

函數(shù)原型:INT8U OSTaskDelReq( INT8U prio )

函數(shù)參數(shù):

prio:進(jìn)程的優(yōu)先級(jí)

(4)修改進(jìn)程優(yōu)先級(jí)

函數(shù)原型:INT8U OSTaskChangePrio( INT8U oldprio, INT8U newprio )

函數(shù)參數(shù):

oldprio:進(jìn)程的源優(yōu)先級(jí)

newprio:進(jìn)程的新優(yōu)先級(jí)

(5)進(jìn)程掛起

函數(shù)原型:INT8U OSTaskSuspend( INT8U prio )

函數(shù)參數(shù):

prio:進(jìn)程的優(yōu)先級(jí)

任務(wù)掛起和任務(wù)刪除有點(diǎn)類似,任務(wù)掛起只是將被掛起任務(wù)的就緒標(biāo)志刪除,并做任務(wù)掛起記錄,并沒(méi)有將任務(wù)控制塊任務(wù)控制塊鏈表里面刪除,也不需要釋放其資源,而任務(wù)刪除則必須先釋放被刪除任務(wù)的資源,并將被刪除任務(wù)的任務(wù)控制塊也給刪了。被掛起的任務(wù),在恢復(fù)后可以繼續(xù)運(yùn)行。

(6)恢復(fù)進(jìn)程

函數(shù)原型:INT8U OSTaskResume( INT8U prio )

函數(shù)參數(shù):

prio:進(jìn)程的優(yōu)先級(jí)

23.2 uCos-II移植

我們將下載好的uCOS-II的源代碼解壓出來(lái)如下圖所示。

圖片

23.2.1 在工程中添加相應(yīng)的文件

(1)在工程目錄下建立UCOSII文件夾,并在該文件夾內(nèi)新建三個(gè)文件夾CONFIG,CORE和PORT

(2)將除了os_cfg_r.h和os_dbg_r.c這兩個(gè)文件以外的所有文件全部復(fù)制到CORE文件夾下

(3)在CONFIG文件夾中新建includes.h文件和os_cfg.h文件

(4)在PORT文件夾中新建os_cpu.h,os_cpu_a.asm,os_cpu_c.c這3個(gè)文件

(5)在工程中添加這三個(gè)目錄下的文件,如下圖所示。

圖片

注:不要把ucos-ii.c文件添加到UCOS-CORE分組中,否則會(huì)提示有重復(fù)定義錯(cuò)誤。

23.2.2 文件修改

我們編譯工程后可以發(fā)現(xiàn)報(bào)了11個(gè)錯(cuò)誤,但都是同一個(gè)錯(cuò)誤,如下圖所示。

圖片

我們?cè)谝浦驳臅r(shí)候并沒(méi)有發(fā)現(xiàn)這個(gè)文件,那是因?yàn)槲覀儾](méi)有用到這個(gè)文件,這個(gè)文件是在ucos-ii.h文件中引用的,我們跳轉(zhuǎn)到這個(gè)文件將其屏蔽掉。

:我們可以發(fā)現(xiàn)在修改的時(shí)候,文件雖然可以打開(kāi),但是修改不了,這是因?yàn)槲覀兿螺d的源碼都被設(shè)置成了只讀模式,在工程中只讀文件會(huì)有一個(gè)鑰匙的標(biāo)志,這就需要我們將文件的只讀屬性去掉即可。

圖片

圖片

去掉只讀屬性之后,我們會(huì)發(fā)現(xiàn)項(xiàng)目中的文件上鑰匙標(biāo)志消失了,如下圖所示。

圖片

此時(shí),我們就可以對(duì)文件內(nèi)容進(jìn)行修改了。打開(kāi)ucos_ii.h文件,屏蔽44行的文件引用,如下圖所示。

圖片

此時(shí)會(huì)發(fā)現(xiàn)報(bào)更多的錯(cuò)誤,此時(shí)我們進(jìn)行新建文件的修改。

(1)os_cpu_a.asm文件詳解

①這部分代碼主要用于定義外部變量,IMPORT表示這是一個(gè)外部變量,不是在本程序內(nèi)定義的,EXPORT則表示這些函數(shù)位于該文件內(nèi),供其他文件調(diào)用,類似于C語(yǔ)言中的extern關(guān)鍵字。

IMPORT  OSRunning
  IMPORT  OSPrioCur
  IMPORT  OSPrioHighRdy
  IMPORT  OSTCBCur
  IMPORT  OSTCBHighRdy
  IMPORT  OSIntNesting
  IMPORT  OSIntExit
  IMPORT  OSTaskSwHook


  EXPORT  OSStartHighRdy
  EXPORT  OSCtxSw
  EXPORT  OSIntCtxSw
  EXPORT  OS_CPU_SR_Save
  EXPORT  OS_CPU_SR_Restore
  EXPORT  PendSV_Handler

②EQU和C語(yǔ)言中的define關(guān)鍵字一樣,用于宏定義,定義了一些寄存器的地址

NVIC_INT_CTRL    EQU    0xE000ED04      ;中斷控制寄存器
NVIC_SYSPRI2    EQU    0xE000ED20      ;系統(tǒng)優(yōu)先級(jí)寄存器
NVIC_PENDSV_PRI  EQU    0xFFFF0000      ;PendSV中斷和系統(tǒng)節(jié)拍中斷
NVIC_PENDSVSET    EQU    0x10000000      ;觸發(fā)軟件中斷的值
  PRESERVE8


  AREA    |.text|, CODE, READONLY
  THUMB

③OS_CPU_SR_Save和OS_CPU_SR_Restore是用于開(kāi)關(guān)中斷的匯編函數(shù),通過(guò)給PRIMASK寫1來(lái)關(guān)閉中斷,寫0來(lái)開(kāi)啟中斷,這里也可以使用CPS指令來(lái)快速開(kāi)關(guān)中斷

OS_CPU_SR_Save
  MRS    R0, PRIMASK            ;讀取PRIMASK到R0,R0為返回值 
  CPSID  I                ;PRIMASK=1,關(guān)中斷(NMI和硬件FAULT可以響應(yīng))
  BX    LR                ;返回


OS_CPU_SR_Restore
  MSR    PRIMASK, R0            ;讀取R0到PRIMASK中,R0為參數(shù)
  BX    LR                ;返回

④OSStartHighRdy是由OSStart()調(diào)用,用來(lái)開(kāi)啟多任務(wù),如果多任務(wù)開(kāi)啟失敗就會(huì)進(jìn)入OSStartHang函數(shù)中

OSStartHighRdy
  LDR     R4, =NVIC_SYSPRI2        ;設(shè)置PendSV優(yōu)先級(jí)
  LDR     R5, =NVIC_PENDSV_PRI
  STR     R5, [R4]
  MOV     R4, #0              ;設(shè)置PSP=0
  MSR     PSP, R4
  LDR     R4, =OSRunning          ;設(shè)置OSRunning=1
  MOV     R5, #1
  STRB    R5, [R4]
  ;切換到最高優(yōu)先級(jí)的任務(wù)
  LDR     R4, =NVIC_INT_CTRL        ;R4=NVIC_INT_CTRL
  LDR     R5, =NVIC_PENDSVSET      ;R5=NVIC_PENDSVSET
  STR     R5, [R4]
  CPSIE   I                ;開(kāi)啟所有中斷
OSStartHang
  B       OSStartHang            ;死循環(huán)

⑤這兩個(gè)函數(shù)都用于任務(wù)切換,它們的本質(zhì)都是觸發(fā)PendSV中斷,具體切換過(guò)程在PendSV的中斷函數(shù)中進(jìn)行,其中OSCtxSw是任務(wù)級(jí)切換,OSIntCtxSw是中斷級(jí)切換,是從中斷退出時(shí)切換到一個(gè)任務(wù)中,從中斷切換到任務(wù)的過(guò)程中,CPU的寄存器入棧工作已經(jīng)完成。

OSCtxSw
  PUSH    {R4, R5}
  LDR     R4, =NVIC_INT_CTRL        ;觸發(fā)PendSV異常
  LDR     R5, =NVIC_PENDSVSET
  STR     R5, [R4]              ;向NVIC_INT_CTRL寫入NVIC_PENDSVSET觸發(fā)PendSV中斷
  POP     {R4, R5}
  BX      LR
OSIntCtxSw
  PUSH    {R4, R5}
  LDR     R4, =NVIC_INT_CTRL        ;觸發(fā)PendSV異常
  LDR     R5, =NVIC_PENDSVSET
  STR     R5, [R4]              ;向NVIC_INT_CTRL寫入NVIC_PENDSVSET觸發(fā)PendSV中斷
  POP     {R4, R5}
  BX      LR
  NOP

⑥這部分代碼才是真正的任務(wù)切換函數(shù),通過(guò)觸發(fā)PendSV中斷來(lái)進(jìn)入該函數(shù)內(nèi)進(jìn)行任務(wù)切換

PendSV_Handler
  CPSID  I                                ;任務(wù)切換過(guò)程中必須關(guān)閉所有中斷
  MRS    R0, PSP                          ;如果在用PSP堆棧,則可以忽略保存寄存器
  CBZ    R0, PendSV_Handler_Nosave    ;如果PSP為0就轉(zhuǎn)移到PendSV_Handler_Nosave


  SUBS    R0, R0, #0x20                                        ;R0-=20H
  STM     R0, {R4-R11}


  LDR     R1, =OSTCBCur
  LDR     R1, [R1]
  STR     R0, [R1]


PendSV_Handler_Nosave
    PUSH    {R14}              ;保存R14的值
    LDR     R0, =OSTaskSwHook        ;調(diào)用OSTaskSwHook()
    BLX     R0
    POP     {R14}


    LDR     R0, =OSPrioCur
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]


    LDR     R0, =OSTCBCur
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]


    LDR     R0, [R2]              ;R0作為新任務(wù)的SP
    LDM     R0, {R4-R11}            ;從堆棧中恢復(fù)R4-R11
    ADDS    R0, R0, #0x20
    MSR     PSP, R0              ;用新任務(wù)的SP加載PSP
    ORR     LR, LR, #0x04          ;確保LR的bit2為1,返回后使用進(jìn)程堆棧
    CPSIE   I                ;開(kāi)啟所有中斷
    BX      LR                ;中斷返回


  end

(2)os_cpu.h文件詳解

①這部分主要用于定義一些數(shù)據(jù)類型,其中重點(diǎn)關(guān)注OS_STK這個(gè)數(shù)據(jù)類型,我們?cè)诙x任務(wù)堆棧的時(shí)候就是該類型數(shù)據(jù),這是一個(gè)32位的數(shù)據(jù)類型,按字節(jié)算的話實(shí)際堆棧大小是我們定義的4倍。

typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;
typedef signed   char  INT8S;
typedef unsigned short INT16U;
typedef signed   short INT16S;
typedef unsigned int   INT32U;
typedef signed   int   INT32S;
typedef float          FP32;
typedef double         FP64;


typedef unsigned int   OS_STK;
typedef unsigned int   OS_CPU_SR;

②這部分代碼定義了堆棧的增長(zhǎng)方向,任務(wù)機(jī)切換的宏定義OS_TASK_SW,如果OS_CRITICAL_METHOD被定義為3的話那么進(jìn)出臨界段的宏定義分別為OS_ENTER_CRITICAL和OS_EXIT_CRITICAL,這兩個(gè)函數(shù)都是用匯編語(yǔ)言編寫的

//OS_CRITICAL_METHOD = 1 :直接使用處理器的開(kāi)關(guān)中斷指令來(lái)實(shí)現(xiàn)宏 
//OS_CRITICAL_METHOD = 2 :利用堆棧保存和恢復(fù)CPU的狀態(tài) 
//OS_CRITICAL_METHOD = 3 :利用編譯器擴(kuò)展功能獲得程序狀態(tài)字,保存在局部變量cpu_sr


#define  OS_CRITICAL_METHOD   3     //進(jìn)入臨界段的方法


#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


void       OSCtxSw(void);
void       OSIntCtxSw(void);
void       OSStartHighRdy(void);
void       OSPendSV(void);


#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR  OS_CPU_SR_Save(void);
void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endif
OS_CPU_EXT INT32U OSInterrputSum;

(3)sys.h文件修改

添加關(guān)于條件編譯的定義,在文件中添加以下代碼即可。

#define SYSTEM_SUPPORT_OS 1

當(dāng)宏定義為1的時(shí)候,編譯器在編譯的時(shí)候會(huì)只編譯滿足條件的代碼,當(dāng)為0時(shí),這部分代碼不會(huì)被編譯。

(4)delay.c文件修改

①添加Sys_Tick中斷服務(wù)函數(shù)與函數(shù)定義

#include "includes.h"
//支持UCOSII
#ifdef  OS_CRITICAL_METHOD
#define delay_osrunning    OSRunning              //OS是否運(yùn)行標(biāo)記,0,不運(yùn)行;1,在運(yùn)行
#define delay_ostickspersec  OS_TICKS_PER_SEC            //OS時(shí)鐘節(jié)拍,即每秒調(diào)度次數(shù)
#define delay_osintnesting  OSIntNesting                //中斷嵌套級(jí)別,即中斷嵌套次數(shù)
#endif
//systick中斷服務(wù)函數(shù),使用OS時(shí)用到
void SysTick_Handler()
{
  //OS開(kāi)始跑了,才執(zhí)行正常的調(diào)度處理
  if( delay_osrunning==1 )
  {
    OSIntEnter() ;                        //進(jìn)入中斷
    OSTimeTick() ;                      //調(diào)用ucos的時(shí)鐘服務(wù)程序
    OSIntExit() ;                        //觸發(fā)任務(wù)切換軟中斷
  }
}

②時(shí)鐘初始化函數(shù)修改

void SysTick_Init( u8 SYSCLK )
{
#if SYSTEM_SUPPORT_OS
  u32 reload;
#endif
   SysTick->CTRL &= ~( 1<<2 ) ;                  //SYSTICK使用外部時(shí)鐘源
  fac_us = SYSCLK/8 ;                      //fac_us都需要使用
#if SYSTEM_SUPPORT_OS
  reload = SYSCLK/8 ;                      //每秒鐘的計(jì)數(shù)次數(shù),單位為K     
  reload *= 1000000/delay_ostickspersec ;              //根據(jù)delay_ostickspersec設(shè)定溢出時(shí)間
  fac_ms = 1000/delay_ostickspersec ;                //代表OS可以延時(shí)的最少單位
  SysTick->CTRL |= 1<<1 ;                    //開(kāi)啟SYSTICK中斷
  SysTick->LOAD = reload ;                    //每1/delay_ostickspersec秒中斷一次
  SysTick->CTRL |= 1<<0 ;                    //開(kāi)啟SYSTICK
#else
  fac_ms = ( u16 )fac_us*1000 ;                  //代表每個(gè)ms需要的systick時(shí)鐘數(shù)
#endif
}

首先要做根據(jù)UCOSII中定義的OS_TICKS_PER_SEC來(lái)計(jì)算出SysTick的裝載值reload,開(kāi)啟SysTick中斷,將reload值寫進(jìn)SysTick的LOAD寄存器中,最后開(kāi)啟SysTick,開(kāi)啟SysTick后還要編寫其中斷服務(wù)函數(shù)。

③微秒級(jí)別延時(shí)函數(shù)

void delay_us( u16 nus )
{
#if SYSTEM_SUPPORT_OS
  u32 ticks, told, tnow, tcnt=0 ;
  u32 reload = SysTick->LOAD ;                  //LOAD的值
  ticks = nus*fac_us ;                                        //需要的節(jié)拍數(shù)
  OSSchedLock() ;                        //禁止調(diào)度,防止打斷us延時(shí)
  told = SysTick->VAL ;                                        //剛進(jìn)入時(shí)的計(jì)數(shù)器值
  while( 1 )
  {
    tnow = SysTick->VAL ;
    if( tnow!=told )
    {
      //這里注意一下SYSTICK是一個(gè)遞減的計(jì)數(shù)器
      if( tnow

④毫秒級(jí)別延時(shí)函數(shù)

void delay_ms( u16 nms )
{
#if SYSTEM_SUPPORT_OS
  //如果OS已經(jīng)在跑了,并且不是在中斷里面(中斷里面不能任務(wù)調(diào)度)
  if( ( delay_osrunning==1 )&&( delay_osintnesting==0 ) )
  {
    //延時(shí)的時(shí)間大于OS的最少時(shí)間周期
    if( nms>=fac_ms )
      OSTimeDly( nms/fac_ms ) ;                //UCOSII延時(shí)
    nms %= fac_ms ;                      //延時(shí)太短,采用普通方式延時(shí)
  }
  delay_us( ( u32 )( nms*1000 ) ) ;                  //普通方式延時(shí)
#else
  u32 temp ;
  SysTick->LOAD = ( u32 )nms*fac_ms ;              //時(shí)間加載(SysTick->LOAD為24bit)
  SysTick->VAL = 0x00 ;                      //清空計(jì)數(shù)器
  SysTick->CTRL = 0x01 ;                    //開(kāi)始倒數(shù)
  do
  {
    temp = SysTick->CTRL ;
  }while( ( temp&0x01 )&&!( temp&( 1<<16 ) ) ) ;          //等待時(shí)間到達(dá)
  SysTick->CTRL = 0x00 ;                    //關(guān)閉計(jì)數(shù)器
  SysTick->VAL = 0x00 ;                      //清空計(jì)數(shù)器
#endif
}

(5)usart1.c文件修改

①添加頭文件定義

#if SYSTEM_SUPPORT_OS

#include "includes.h"

#endif

②修改串口中斷服務(wù)函數(shù)

void USART1_IRQHandler()
{
#if SYSTEM_SUPPORT_OS
  OSIntEnter() ;
#endif
  //接收到數(shù)據(jù)
  if( USART1->SR&( 1<<5 ) )
  {
    if( USART1->DR=='\\n' )
    {
      USART1_Data.Len = USART1_Rx_Count ;
      USART1_Rx_Count = 0 ;
      USART1_Data.State = 1 ;
    }
    USART1_Data.Buffer[ USART1_Rx_Count ] = USART1->DR ;
    USART1_Rx_Count ++ ;
  }
#if SYSTEM_SUPPORT_OS
  OSIntExit() ;
#endif
}

23.3 實(shí)驗(yàn)例程

例程:利用移植完成的ucos-ii系統(tǒng)新建兩個(gè)任務(wù),并且在兩個(gè)任務(wù)中打印自定義的任務(wù)名稱。

#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "includes.h"
/****************************************************
Name    :Task01
Function  :任務(wù)1
Paramater  :None
Return    :None
****************************************************/
#define TASK01_PRIO  7                                          //設(shè)置任務(wù)優(yōu)先級(jí)
#define TASK01_SIZE  64                                          //設(shè)置任務(wù)堆棧大小
OS_STK TASK01_STK[ TASK01_SIZE ] ;                                    //任務(wù)堆棧
void Task01( void *pdata )
{
  while( 1 )
  {
    printf( "Task1 Run\\r\\n" ) ;
    delay_ms( 1000 ) ;
  }
}
/****************************************************
Name    :Task02
Function  :任務(wù)2
Paramater  :None
Return    :None
****************************************************/
#define TASK02_PRIO  6                                          //設(shè)置任務(wù)優(yōu)先級(jí)
#define TASK02_SIZE  64                                          //設(shè)置任務(wù)堆棧大小
OS_STK TASK02_STK[ TASK02_SIZE ] ;                                    //任務(wù)堆棧
void Task02( void *pdata )
{
  while( 1 )
  {
    printf( "Task2 Run\\r\\n" ) ;
    delay_ms( 2000 ) ;
  }
}
/****************************************************
Name    :Start
Function  :開(kāi)始任務(wù)
Paramater  :None
Return    :None
****************************************************/
#define START_PRIO  10                                          //開(kāi)始任務(wù)的優(yōu)先級(jí)設(shè)置為最低
#define START_SIZE  64                                          //設(shè)置任務(wù)堆棧大小
OS_STK START_STK[ START_SIZE ] ;                                    //任務(wù)堆棧
void Start( void *pdata )
{
    OS_CPU_SR cpu_sr=0 ;
  pdata = pdata ;
    OS_ENTER_CRITICAL() ;                                        //進(jìn)入臨界區(qū)(無(wú)法被中斷打斷)
   OSTaskCreate( Task01, ( void * )0, ( OS_STK* )&TASK01_STK[ TASK01_SIZE-1 ], TASK01_PRIO ) ;
   OSTaskCreate( Task02, ( void * )0, ( OS_STK* )&TASK02_STK[ TASK02_SIZE-1 ], TASK02_PRIO ) ;
  OSTaskSuspend( START_PRIO ) ;                                    //掛起起始任務(wù)
  OS_EXIT_CRITICAL() ;                                        //退出臨界區(qū)(可以被中斷打斷)
}
/****************************************************
Name    :Main
Function  :主函數(shù)
Paramater  :None
Return    :None
****************************************************/
int main()
{
   STM32_Clock_Init( 9 ) ;                                        //系統(tǒng)時(shí)鐘設(shè)置
  SysTick_Init( 72 ) ;                                        //延時(shí)初始化
  USART1_Init( 72, 115200 ) ;                                      //串口初始化為115200
  OSInit() ;
   OSTaskCreate( Start, ( void * )0, ( OS_STK * )&START_STK[ START_SIZE-1 ], START_PRIO ) ;      //創(chuàng)建起始任務(wù)
  OSStart() ;
   while( 1 ) ;
}

將程序下載進(jìn)單片機(jī),打開(kāi)串口助手可以看到以下的效果。

圖片

通過(guò)時(shí)間可以看出,Task2的任務(wù)2s打印一次數(shù)據(jù),Task1的任務(wù)1s打印一次數(shù)據(jù),和我們程序所寫一致,所以說(shuō)明UCOS-II系統(tǒng)移植成功。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    UCOS-II系統(tǒng)移植問(wèn)題

    這幾天剛剛開(kāi)始學(xué)習(xí)UCOS-II系統(tǒng)移植,我用的是野火開(kāi)發(fā)板。資料上說(shuō)是對(duì)startup_stm32f10x_hd.s 文件進(jìn)行修改,但是我修改不了,這文件好像是不能修改。想問(wèn)問(wèn)學(xué)過(guò)的人指點(diǎn)指點(diǎn)
    發(fā)表于 09-12 12:27

    ucOS-II入門經(jīng)典教程

    ucOS-II入門經(jīng)典教程,ucOS-II入門經(jīng)典教程
    發(fā)表于 11-06 10:07 ?0次下載

    盤古STM32F103開(kāi)發(fā)板移植uCOS-II詳細(xì)說(shuō)明

    盤古STM32F103開(kāi)發(fā)板移植uCOS-II詳細(xì)說(shuō)明
    發(fā)表于 03-02 17:29 ?13次下載

    uCOS-ii中文書

    學(xué)習(xí)uCOS-ii的最好中文教材,uCOS-ii中文書(邵貝貝)
    發(fā)表于 08-24 18:31 ?0次下載

    uCOS-II原理1

    原理uCOS-II
    發(fā)表于 12-20 22:58 ?5次下載

    uCOS-II原理2

    uCOS-II原理2
    發(fā)表于 12-20 22:53 ?0次下載

    uCOS-II原理3

    uCOS-II原理3
    發(fā)表于 12-20 22:52 ?0次下載

    在W78E58處理器上移植uCOS-II

    在W78E58處理器上移植uCOS-II
    發(fā)表于 01-08 14:27 ?12次下載

    uCOS-II嵌入式操作系統(tǒng)介紹與移植

    電子發(fā)燒友網(wǎng)站提供《uCOS-II嵌入式操作系統(tǒng)介紹與移植.ppt》資料免費(fèi)下載
    發(fā)表于 05-03 08:00 ?19次下載

    uCOS-II在MSP430移植

    uCOS-II在MSP430移植
    發(fā)表于 10-12 17:24 ?9次下載
    <b class='flag-5'>uCOS-II</b>在MSP430<b class='flag-5'>移植</b>

    手把手盤古STM32開(kāi)發(fā)板移植uCOS-II教程

    手把手盤古STM32開(kāi)發(fā)板移植uCOS-II教程
    發(fā)表于 10-16 09:38 ?22次下載

    STM32入門學(xué)習(xí)筆記之uCOS-II系統(tǒng)移植1

    之前的實(shí)驗(yàn)都是利用單片機(jī)實(shí)現(xiàn)某個(gè)單一功能,但是有時(shí)候需要在兩個(gè)功能同時(shí)運(yùn)行,這時(shí)就需要引入操作系統(tǒng)的概念,操作系統(tǒng)(Operating System,簡(jiǎn)稱OS)是一種管理電腦硬件與軟件資源的程序
    的頭像 發(fā)表于 02-16 16:13 ?2451次閱讀
    STM32入門學(xué)習(xí)筆記之<b class='flag-5'>uCOS-II</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>移植</b>1

    STM32入門學(xué)習(xí)筆記之uCOS-II系統(tǒng)移植2

    之前的實(shí)驗(yàn)都是利用單片機(jī)實(shí)現(xiàn)某個(gè)單一功能,但是有時(shí)候需要在兩個(gè)功能同時(shí)運(yùn)行,這時(shí)就需要引入操作系統(tǒng)的概念,操作系統(tǒng)(Operating System,簡(jiǎn)稱OS)是一種管理電腦硬件與軟件資源的程序
    的頭像 發(fā)表于 02-16 16:13 ?1359次閱讀
    STM32入門學(xué)習(xí)筆記之<b class='flag-5'>uCOS-II</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>移植</b>2

    STM32入門學(xué)習(xí)筆記之uCOS-II系統(tǒng)移植3

    之前的實(shí)驗(yàn)都是利用單片機(jī)實(shí)現(xiàn)某個(gè)單一功能,但是有時(shí)候需要在兩個(gè)功能同時(shí)運(yùn)行,這時(shí)就需要引入操作系統(tǒng)的概念,操作系統(tǒng)(Operating System,簡(jiǎn)稱OS)是一種管理電腦硬件與軟件資源的程序
    的頭像 發(fā)表于 02-16 16:13 ?536次閱讀

    STM32入門學(xué)習(xí)筆記之uCOS-II系統(tǒng)移植4

    之前的實(shí)驗(yàn)都是利用單片機(jī)實(shí)現(xiàn)某個(gè)單一功能,但是有時(shí)候需要在兩個(gè)功能同時(shí)運(yùn)行,這時(shí)就需要引入操作系統(tǒng)的概念,操作系統(tǒng)(Operating System,簡(jiǎn)稱OS)是一種管理電腦硬件與軟件資源的程序
    的頭像 發(fā)表于 02-16 16:13 ?936次閱讀
    STM32入門學(xué)習(xí)筆記之<b class='flag-5'>uCOS-II</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>移植</b>4