前言
本教程是基于STM32F103RBT6基礎(chǔ)工程進(jìn)行移植,同系列的stm32同樣適用,只不過基礎(chǔ)工程要另外準(zhǔn)備,其中本教程使用到的基礎(chǔ)工程里面有個SYSTEM的文件夾(如果使用其他工程建議可以把該文件夾復(fù)制過去使用),里面的函數(shù)是由正點原子團(tuán)隊提供,這里也是參考原子出品的“STM32F1UCOS開發(fā)手冊”,想了解更加具體的教程可以自己去網(wǎng)上搜一下。這是stm32學(xué)習(xí)論壇,里面有豐富的學(xué)習(xí)資源。 本教程使用到的文件:工程文件與word; 訪問密碼:912b(如果你準(zhǔn)備按照該教程進(jìn)行移植,開始之前請先下載該文件,鏈接失效可以評論回復(fù),看到后會處理)注意:請使用MDK5打開工程! 1、準(zhǔn)備工作 (1)stm32F103RBT6基礎(chǔ)工程:這里以跑馬燈為例 (2)UCOSII源碼:官網(wǎng)下載 (3)準(zhǔn)備文件:PORT和CONFIG 2、移植 (1)在基礎(chǔ)工程中建立新文件夾用來存放源碼:
(2)向三個文件夾添加UCOSII源碼,首先向CORE文件夾添加(UCOSII源碼):至于為什么不要那兩個文件,后續(xù)再談,先照著做。 然后向CONFIG文件夾添加文件:將“準(zhǔn)備工作”里面“必需文件”下的CONFIG全部復(fù)制到這里來: 其中includes.h里面定義了一些頭文件,如圖,:

os_cfg.h主要用來配置和裁剪UCOSII的。 最后是向PORT文件夾添加文件,如上所述,直接將“必需文件”下的PORT直接復(fù)制過來: 這里的文件是關(guān)鍵,移植需要修改幾乎都在這里,因為這里PORT下的文件已經(jīng)是修改好的,下一步添加到工程時不用再修改就能在stm32上跑,這里后續(xù)再講,先移植好一個成功的工程先。
(3)配置工程
a 我們打開基礎(chǔ)工程,將UCOSII添加到工程里面:


 添加成功后:  別忘了添加路徑: b 編譯工程,處理錯誤 上面步驟成功之后,現(xiàn)在可以編譯工程了, 提示打不開“app_cfg.h”文件,跟蹤錯誤: 再重新編譯一下, 發(fā)現(xiàn)錯誤,重復(fù)定義了,我們stm32f10x_it.h里面的注釋掉: 這時候編譯,發(fā)現(xiàn)工程已經(jīng)沒有錯誤了,因為我們是引用了正點原子提供的system函數(shù),所以還要按照他們的規(guī)則去修改一下一些文件。 c 修改sys.h頭文件 打開sys.h:  因為 system 里面的文件適用于裸板也適用移植了操作系統(tǒng)的,所以宏定義要按需更改。 再編譯,提示 ”TRUE” 沒有定義,把 ”TRUE” 改為“ OS_TRUE ”,再編譯: 同理,將stm32f10x.h里面的注釋掉:

再編譯,這時候發(fā)現(xiàn)已經(jīng)沒有錯誤了: 如果還有錯誤,請根據(jù)錯誤提示自行解決。 如此,UCOSII就已經(jīng)移植完成了,下面寫個個測試程序看看能不能成功即可。 d 測試是否移植成功, 程序:(將下面代碼直接復(fù)制到main函數(shù)里面,原先的都刪掉,編譯,下載驗證,如果LED0和LED1以不同的頻率閃爍說明移植成功) #include"led.h" #include"delay.h" #include"sys.h" #include"usart.h" #include"includes.h" //開始任務(wù) #defineSTART_TASK_PRIO 10 #defineSTART_STK_SIZE 128 OS_STKSTART_TASK_STK[START_STK_SIZE]; void start_task(void*pdata); //LED0任務(wù) #defineLED0_TASK_PRIO 7 #defineLED0_STK_SIZE 64 OS_STKLED0_TASK_STK[LED0_STK_SIZE]; void led0_task(void*pdata); //LED1任務(wù) #defineLED1_TASK_PRIO 6 #defineLED1_STK_SIZE 64 OS_STKLED1_TASK_STK[LED1_STK_SIZE]; void led1_task(void*pdata); intmain(void) { delay_init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); uart_init(115200); LED_Init(); OSInit(); //UCOSII初始化 OSTaskCreate(start_task,(void*)0,(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO);//創(chuàng)建開始任務(wù) OSStart(); //系統(tǒng)啟動 } void start_task(void*pdata) { OS_CPU_SRcpu_sr=0; pdata=pdata; OSStatInit(); OS_ENTER_CRITICAL(); //臨界 OSTaskCreate(led0_task,(void*)0,(OS_STK*)&LED0_TASK_STK[LED0_STK_SIZE-1],LED0_TASK_PRIO);//創(chuàng)建LED0任務(wù) OSTaskCreate(led1_task,(void*)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);//創(chuàng)建LED1任務(wù) OSTaskSuspend(START_TASK_PRIO);//開始任務(wù)掛起 OS_EXIT_CRITICAL(); } //LED0任務(wù) void led0_task(void*pdata) { while(1) { GPIO_ResetBits(GPIOA,GPIO_Pin_8); delay_ms(80); GPIO_SetBits(GPIOA,GPIO_Pin_8); delay_ms(80); } } //LED1任務(wù) void led1_task(void*pdata) { while(1) { GPIO_ResetBits(GPIOD,GPIO_Pin_2); delay_ms(300); GPIO_SetBits(GPIOD,GPIO_Pin_2); delay_ms(300); } }
3 移植過程講解 (1)如果參考上面的步驟你已經(jīng)完成了系統(tǒng)的移植的話,接下來講解一下移植過程中主要需要修改的文件,首先是os_cpu_a.asm,前面已經(jīng)說過這些需要修改的文件都是官方提供的代碼,我們只需要根據(jù)自身的硬件體系結(jié)構(gòu)進(jìn)行修改即可: os_cpu_a.asm主要是一些匯編代碼,我們在工程中打開,主要關(guān)注的是這幾個函數(shù): EXPORT的意思這些函數(shù)在本文件定義供其他文件調(diào)用。
a OSStartHighRdy函數(shù)
OSStartHighRdy是由OSStart()函數(shù)調(diào)用的,這是第一個任務(wù),用來開啟多任務(wù),多任務(wù)開啟失敗的話調(diào)用OSStartHang函數(shù)。需要移植的原因是這里的寄存器都要根據(jù)STM32的結(jié)構(gòu)來進(jìn)行修改,這里已經(jīng)是修改好了的。
bOSCtxSw函數(shù)和OSIntCtxSw函數(shù)
兩個函數(shù)都是用來做任務(wù)切換,區(qū)別在于OSCtxSw是任務(wù)級,OSIntCtxSw是中斷級切換。OSCtxSw函數(shù)在 OSSched函數(shù)中負(fù)責(zé)保存當(dāng)前任務(wù)對應(yīng)的處理器寄存器到堆棧中,并將任務(wù)中需要恢復(fù)的處理器寄存器從堆棧中恢復(fù)出來。OSIntCtxSw函數(shù)主要保存當(dāng)前任務(wù)堆棧指針,并將新任務(wù)對應(yīng)的處理器寄存器從堆棧中恢復(fù)出來。
 這里也是已經(jīng)移植好了的。其他的都可以暫時先不用理會。
(2)移植os_cpu.h
os_cpu.h主要定義了一些數(shù)據(jù)類型,μCOS-II為了保證可移植性,程序中沒有直接使用 int,unsignedint 等定義,而是自己定義了一套數(shù)據(jù)類型,如 INT16U 表示 16 位無符號整型,對于 STM32 這樣的 32 位內(nèi)核,INT16U 是unsigned short型,如果是16位的處理器,則是unsignedint型。如圖示:
這里尤其注意OS_STK類型,這里是32位的。
接下來是定義棧的增長方向,CM3棧是由高地址向低地址增長的,
定義 OS_TASK_SW 宏。OS_TASK_SW 宏是 uC/OS-II 從低優(yōu)先級任務(wù)切換到高優(yōu)先級任務(wù)時的調(diào)用,可以采用下面兩種方式定義:如果處理器支持軟中斷,可以使用軟中斷將中斷向量指向OSCtxSw 函數(shù);
不同的硬件的位數(shù)不一樣,棧的增長方向也不一樣,自然都要修改。
(3)移植os_cpu_c.c文件
os_cpu_c.c 主要定義了系統(tǒng)需要的鉤子函數(shù),其中必須需要移植的是OSTaskStkInit函數(shù),這個函數(shù)在任務(wù)創(chuàng)建時被調(diào)用,它負(fù)責(zé)初始化任務(wù)的堆棧結(jié)構(gòu),其他的鉤子函數(shù)可以暫時不用理會,有興趣的可以自行了解。
堆棧初始化函數(shù)OSTaskStkInit是由任務(wù)創(chuàng)建函數(shù)OSTaskCreate()和OSTaskCreateExt()這兩個函數(shù)調(diào)用,用于在創(chuàng)建任務(wù)的時候初始堆棧,從上面的代碼中可以看出就是在任務(wù)堆棧中保存寄存器的值。
這里要注意一下入棧順序,要根據(jù)CM3的體系,其中CM3硬件會自動將FPSCR、XPSR、PC、LR、R12、R0-R3入棧,入棧順序遵照Stackframe,剩下的R4-R11需要手動入棧。
移植UCOSII到stm32三個文件改動基本不大,主要是OS_CPU_A.ASM需要改動,其他的都是默認(rèn)和CM3的體系相近,不用做出大的改動即可移植成功。
至此,UCOSII移植就已經(jīng)全部完成了。
本教程主要是為了對系統(tǒng)移植的過程有個大概了解,其中的細(xì)節(jié)沒有進(jìn)行分析,因技術(shù)水平有限,有錯漏之處歡迎指出或有更好的學(xué)習(xí)建議也希望可以回復(fù)交流,共同學(xué)習(xí)、進(jìn)步。
謝謝!
|