版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第三章將μC/OS-Ⅱ移植到UP-Star實驗板上
3.1μC/OS-ⅡLED實例
3.2μC/OS-Ⅱ移植
3.3μC/OS-Ⅱ串口通信實例
3.4本章小結(jié)
在第二章工程ex2_3的基礎(chǔ)上,通過編寫和添加μC/OS-Ⅱ移植文件和內(nèi)核文件,進一步介紹μC/OS-Ⅱ的兩個實例。借助這兩個實例,深入說明μC/OS-Ⅱ移植到UP-Star實驗板上的方法。通常應(yīng)該在介紹了μC/OS-Ⅱ內(nèi)核之后再介紹μC/OS-Ⅱ的移植,這樣更方便讀者理解移植所需要做的工作。本書先介紹μC/OS-Ⅱ移植再介紹μC/OS-Ⅱ內(nèi)核,是因為移植μC/OS-Ⅱ所做的工作與S3C2410A芯片硬件密切相關(guān),只要對UP-Star實驗板和S3C2410A芯片比較熟悉,即使不了解μC/OS-Ⅱ,也可以學習移植;同時,移植完成后,后續(xù)各章節(jié)實例均可基于這個移植,在UP-Star實驗板上運行。本書是以實例帶動講解的方法編寫,所以需選擇先介紹μC/OS-Ⅱ的移植。讀者也可以先去閱讀第四章,再返回來閱讀本章。本章介紹的移植參考“μC/OS-ⅡandARMProcessorsApplicationNote(AN-1014)”文檔,基于μC/OS-ⅡV2.86,如果讀者用于其他μC/OS-Ⅱ的版本,需做一定的修改。
下面首先介紹一個基于UP-Star實驗板的μC/OS-Ⅱ?qū)嵗碙ED閃爍實例;然后再介紹μC/OS-Ⅱ移植需要做的工作。在第2.3節(jié)工程ex2_3的基礎(chǔ)上新建工程ex3_1,存儲目錄為D:\ZYUCOSII\ex3_1(此時的工程ex3_1與工程ex2_3完全相同,僅是工程名改為ex3_1),如圖3-1所示。
盡管是從工程ex2_3過渡到工程ex3_1,但事實上,讀者將會發(fā)現(xiàn),工程ex3_1將做很多重大的修改(以至于和圖3-1所示的工程ex3_1最初版本相比完全兩樣),以達到本節(jié)的程序設(shè)計目的。3.1μC/OS-ⅡLED實例圖3-1工程ex3_1的最初版本3.1.1實例ex3_1
為了清晰地說明實例ex3_1的創(chuàng)建過程,下面逐步介紹。
S1.在圖3-1的工作區(qū)中,移除“user”分組下的所有文件,刪除“asm”分組,添加“ports”分組和“ucosii”分組,如圖3-2所示。圖3-2工程ex3_1的工作區(qū)分組從圖3-2可以看出,工程ex3_1僅保留了工程ex2_3的設(shè)置(即“Project?|?Options…”菜單項彈出窗口的內(nèi)容),但實際的程序設(shè)計中會用到工程ex2_3已編寫的代碼。
S2.到目錄D:\ZYUCOSII\ex3_1下,刪除User子目錄下的所有文件,刪除子目錄ASM,然后新建子目錄ports和ucosii,將μC/OS-ⅡV2.86版軟件,即第1.2節(jié)提到的壓縮文件Micrium-μCos-Ⅱ-V286.ZIP解壓后的目錄Micrium-uCOS-II-V286\Micrium\SOFTWARE\μCOS-Ⅱ\Source下的14個文件拷貝到ucosii子目錄下,其中的文件os_cfg_r.h和os_dbg_r.c移動到ports目錄下,并把文件名中的“_r”去掉。此時的目錄D:\ZYUCOSII\ex3_1如圖3-3所示。從網(wǎng)站下載AN-1014.ZIP文件,在網(wǎng)站的“Support|ApplicationNotes”鏈接中,是關(guān)于“μC/OS-ⅡforARMProcessorsWorksinARMorThumbmode”的。將AN-1014.ZIP壓縮文件中的IAR子目錄下的os_cpu.h、os_cpu_a.asm和os_cpu_c.c三個文件拷貝到圖3-3中的ports文件夾中。
現(xiàn)在可以檢查一下圖3-3中各個文件夾下的內(nèi)容,在ports文件夾下有5個文件,依次為os_cfg.h、os_cpu.h、os_cpu_a.asm、os_cpu_c.c和os_dbg.c;在ucosii文件夾下有12個文件,依次為os_core.c、os_flag.c、os_mbox.c、ox_mem.c、os_mutex.c、ox_q.c、os_sem.c、os_task.c、os_time.c、os_tmr.c、ucos_ii.c和ucos_ii.h;user文件夾下沒有文件,現(xiàn)在,新建一個空文本文件,更名為app_cfg.h。在程序設(shè)計過程中,盡可能地不去修改ucosii文件夾下的文件。圖3-3目錄D:\ZYUCOSII\ex3_1下的文件夾
S3.回到圖3-2,向工作區(qū)中添加文件,即向ucosii分組中添加D:\ZYUCOSII\ex3_1\ucosii\ucos_ii.c文件,向ports分組中添加D:\ZYUCOSII\ex3_1\ports目錄下的os_cpu_a.s、os_cpu_c.c和os_dbg.c3個文件。新建3個文件,即includes.h、app.h和app.c文件,這3個文件均保存到D:\ZYUCOSII\ex3_1\User目錄下,并把app.c文件添加到工作區(qū)的user分組下。其中app.h文件內(nèi)容為空,includes.h文件和app.c文件的內(nèi)容如下:includes.h文件的內(nèi)容:
1/*FileName:includes.h
2**Byzhnyong@21
3**@2009-4-4
4**CopyrightReserved
5*/
6
7#include"stdio.h"
8#include"string.h"
9
10#include"..\\ucosii\\ucos_ii.h"
11
12#include"app.h"app.c文件的內(nèi)容:
1/*FileName:app.c
2**Byzhnyong@21
3**@2009-4-4
4**MainRoutine
5**CopyrightReserved
6*/7
8#include“includes.h”
9
10voidmain(void)
11{
12OSInit();
13
14OSStart();
15}
這里主程序文件即為app.c文件,相當于工程ex2_3中的zyMain.c的作用。至此,D:\ZYUCOSII\ex3_1\User目錄下有4個文件,即app.c、app.h、app_cfg.h和includes.h。其中app_cfg.h文件添加如下代碼:
S4.將目錄D:\ZYUCOSII\ex3_1\下所有文件的屬性修改為可讀可寫,即去掉“只讀”屬性。
S5.這時編譯工程ex3_1,即點擊菜單“Project|RebuildAll”,會出現(xiàn)多處“不能打開文件錯誤”,依次修改以下代碼:
(1)?ucos_ii.h第44行,由“#include<app_cfg.h>”改為“#include".\\user\\app_cfg.h"”;
(2)?ucos_ii.h第45行,由“#include<os_cfg.h>”改為“#include"..\\ports\\os_cfg.h"”;
(3)?ucos_ii.h第46行,由“#include<os_cpu.h>”改為“#include"..\\ports\\os_cpu.h"”;
(4)?os_cpu_c.c第24行,由“#include<ucos_ii.h>”改為“#include"..\\ucosii\\ucos_ii.h"”;
(5)?os_dbg.c第24行,由“#include<ucos_ii.h>”改為“#include"..\\ucosii\\ucos_ii.h"”;
(6)?ucos_ii.c第24行,由“#include<ucos_ii.h>”改為“#include"ucos_ii.h"”;
(7)?ucos_ii.c第28行,由“#include<os_core.c>”改為“#include"os_core.c"”;
(8)?ucos_ii.c第28行,由“#include<os_flag.c>”改為“#include"os_flag.c"”;
(9)?ucos_ii.c第28行,由“#include<os_mbox.c>”改為“#include"os_mbox.c"”;
(10)?ucos_ii.c第28行,由“#include<os_mem.c>”改為“#include"os_mem.c"”;
(11)?ucos_ii.c第28行,由“#include<os_mutex.c>”改為“#include"os_mutex.c"”;
(12)?ucos_ii.c第28行,由“#include<os_q.c>”改為“#include"os_q.c"”;
(13)?ucos_ii.c第28行,由“#include<os_sem.c>”改為“#include"os_sem.c"”;
(14)?ucos_ii.c第28行,由“#include<os_task.c>”改為“#include"os_task.c"”;
(15)?ucos_ii.c第28行,由“#include<os_time.c>”改為“#include"os_time.c"”;
(16)?ucos_ii.c第28行,由“#include<os_tmr.c>”改為“#include"os_tmr.c"”;
(17)?os_tmr.c第25行,由“#include<ucos_ii.h>”改為“#include"ucos_ii.h"”。
S6.新建文件bsp.h和bsp.c,保存在D:\ZYUCOSII\ex3_1\
ports目錄下,將bsp.c文件添加到工作區(qū)ports分組下,在includes.h文件末尾添加一條語句“#include"..\\ports\\bsp.h"”。其中,bsp.h文件內(nèi)容為空,bsp.c文件的內(nèi)容如下:1/*FileName:bsp.c
2**Byzhnyong@21
3**@2009-4-4
4**CopyrightReserved
5*/
6
7#include"..\\user\\includes.h"
8
9voidOS_CPU_ExceptHndlr(INT32Uexcept_type){}
10
11voidApp_TaskSwHook(void){}
1213voidApp_TaskCreateHook(OS_TCB*ptcb){}
14
15voidApp_TCBInitHook(OS_TCB*ptcb){}
16
17voidApp_TaskStatHook(void){}
18
19voidApp_TaskIdleHook(void){}
20
21voidApp_TaskDelHook(OS_TCB*ptcb){}
22
23voidApp_TimeTickHook(void){}現(xiàn)在編譯鏈接工程ex3_1,將正常編譯通過,沒有任何警告和錯誤,但實際的移植工作才剛剛開始。
S7.新建文件startup.s,保存在目錄D:\ZYUCOSII\ex3_1\
ports下,并將該文件添加到工作區(qū)ports分組下,該文件實現(xiàn)S3C2410上電復(fù)位后的芯片初始化工作,其代碼如下:
S8.進入到os_cpu_c.c文件的OSInitHookBegin函數(shù)中,即文件代碼的第136行,原始語句為“*pstk=(OS_STK)0;”,估計此處是軟件作者J.J.Labrosse先生的失誤,此處應(yīng)改為“*pstk++=(OS_STK)0;”。然后,在第147行和148行間插入一個函數(shù)調(diào)用語句,即在第147行處回車,添加語句“myInitHookBegin()”,這個函數(shù)是作者自定義的系統(tǒng)初始化函數(shù)。接著,在app_cfg.h的末尾添加語句“voidmyInitHookBegin(void);//MyInitCodefuncprototype”。最后,在bsp.c文件的末尾添加如下代碼:注意:上述代碼在bsp.c中的實際行號是從第25行開始的。myInitLED函數(shù)用于初始化LED燈,myInitTimer4用于初始化定時器4,定時器4用作μC/OS-Ⅱ時鐘節(jié)拍,定時中斷產(chǎn)生頻率為100Hz。
編寫bsp.h文件的代碼如下:
S9.編寫定時器4中斷入口和處理函數(shù),修改bsp.c文件中的OS_CPU_ExceptHndlr函數(shù)內(nèi)容如下:
1voidOS_CPU_ExceptHndlr(INT32Uexcept_type)
2{
3switch(except_type)
4{
5case6: //IRQInterrupt
6switch(INTOFFSET) //INTOFFSETissub-intentryNo.
7{18break;
19default:
20break;
21}
22}同時,在bsp.h中添加如下代碼:
1//InterruptController
2//---------------------------------------------------------
3//InterruptRequestStatus
4//InterruptModeControl
5//InterruptMaskControl
6//IRQPriorityControl
7//InterruptRequestStatus
8//InterruotRequestSourceOffset
9//SubSourcePending上述代碼可位于bsp.h的末尾或“//FunctionPrototype”注釋行前面(實際上,這些代碼可位于文件中的任意位置)。
S10.新建文件appfun.c,保存在目錄D:\ZYUCOSII\
ex3_1\User下,并將該文件添加到工作區(qū)user分組下,該文件用于存放用戶編寫的各種功能函數(shù),目前主要是關(guān)于LED燈點亮和熄滅的函數(shù),編寫該文件內(nèi)容如下:編寫app.h文件的代碼如下:
S11.修改app.c文件的內(nèi)容,創(chuàng)建一個任務(wù),用于控制LED燈的閃爍,其完整代碼如下:
1/*FileName:app.c
2**Byzhnyong@21
3**@2009-4-4
4**MainRoutine
5**CopyrightReserved
6*/
7
8#include“includes.h”
9
10voidmain(void)
11{
12OSInit();
13OSTaskCreate(AppTaskStart,(void*)0,&AppTaskStartStk
[TASK_STK_SIZE-1],0);
14OSStart();
15}目前,app.h的完整代碼如下:
1/*FileName:app.h
2**Byzhnyong@21
3**@2009-4-4
4**CopyrightReserved
5*/
6
7#ifdefMY_APP_GLOBALS
8#defineMY_APP文件appfun.c的完整代碼如下:
1/*FileName:appfun.c
2**Byzhnyong@21
3**@2009-4-4
4**CopyrightReserved
5*/
6
7#defineMY_APP_GLOBALS
8#include"includes.h"
9
S12.編譯鏈接工程ex3_1,在線仿真可以看到LED1和LED2間隔1秒交替點亮閃爍。最后的工程ex3_1如圖3-4所示。圖3-4移植完成后的工程ex3_1至此,工程ex3_1完成了,同時也完成了μC/OS-Ⅱ的移植,此時,目錄D:\ZYUCOSII\ex3_1下的子目錄及其文件和圖3-3一樣,子目錄user下有文件app.c、app.h、app_cfg.h、appfun.c和includes.h,這些文件均需要自己編寫;子目錄ports下有文件bsp.c、bsp.h、os_cfg.h、os_cpu.h、os_cpu_
a.asm、os_cpu_c.c、os_dbg.c和startup.s,其中,只有bsp.c、bsp.h和startup.s文件需自己編寫;子目錄ucosii下為12個μC/OS-Ⅱ內(nèi)核文件,即os_core.c、os_flag.c、os_mbox.c、ox_mem.c、os_mutex.c、ox_q.c、os_sem.c、os_task.c、os_time.c、os_tmr.c、ucos_ii.c和ucos_ii.h,這些文件均不需要自己編寫。通過對比工程ex3_1和工程ex2_3可知,兩個工程中需要自己編寫的代碼數(shù)量是差不多的,但是工程ex3_1上加載了μC/OS-Ⅱ操作系統(tǒng)。
μC/OS-Ⅱ原作者J.J.Labrosse指出移植μC/OS-Ⅱ是件輕松的事情,主要是因為μC/OS-Ⅱ本身的設(shè)計就考慮了移植,即移植的大部分工作原作者都給出來了。
Labrosse認為移植μC/OS-Ⅱ需要花費幾個小時至一周的時間不等,視編程人員對ARM芯片結(jié)構(gòu)的熟悉程度。通過上述關(guān)于μC/OS-ⅡV2.86的移植,筆者也有同樣的觀點,如果讀者自己研究移植代碼,將會發(fā)現(xiàn),移植μC/OS-Ⅱ工作的大部分時間都花在了閱讀“μC/OS-ⅡandARMProcessorsApplicationNote(AN-1014)”英文文檔上,一定意義上,編程人員的英文水平?jīng)Q定了他的移植水平。從現(xiàn)在開始,我們將開始基于μC/OS-Ⅱ嵌入式操作系統(tǒng)的面向任務(wù)程序設(shè)計工作,在調(diào)試這類程序時,借助μC/OS-Ⅱ的調(diào)試插件C-SPY更為直觀一些。在圖3-4中,點擊“Project|Options”菜單,進入如圖3-5所示的界面,選中“Debugger|Plugins”下的“μC/OS-Ⅱ”一項,點擊“OK”按鈕保存。然后回到圖3-4中,點擊“Project|DownloadandDebug”菜單進入如圖3-6所示的調(diào)試環(huán)境界面,這時菜單欄中有一項為“μC/OS-Ⅱ”,點擊該菜單項下的“TaskList”子菜單,將彈出任務(wù)一欄,如圖3-6所示。圖3-5設(shè)置μC/OS-Ⅱ調(diào)試插件圖3-6工程ex3_1顯示任務(wù)信息的調(diào)試窗口從圖3-6中可以看出,工程ex3_1中包含4個任務(wù),其中優(yōu)先級為0的任務(wù)為我們自己創(chuàng)建的任務(wù),因為沒有命名,所以“Name”一欄為“?”;還有3個系統(tǒng)任務(wù),即μC/OS-ⅡTmr、μC/OS-ⅡStat和μC/OS-ⅡIdle,優(yōu)先級分別為10、62和63。
下面首先從整體上解釋一下實例ex3_1,重點介紹為了移植μC/OS-Ⅱ我們所做的工作,然后,第3.2節(jié)將進一步介紹移植μC/OS-Ⅱ所需要做的工作,即摘錄“μC/OS-ⅡandARMProcessorsApplicationNote(AN-1014)”文檔中的一些內(nèi)容。3.1.2實例ex3_1注解
第3.1.1節(jié)實現(xiàn)了實例ex3_1及其功能,這里介紹這個實例是如何工作的。仿真(或系統(tǒng)上電之后)時,程序首先從startup.s開始執(zhí)行,實際上是從0x0地址開始執(zhí)行的(這里也暴露出了IAREWARM軟件的一個小缺點,好像快速中斷與普通中斷標號在反匯編窗口中沒有區(qū)分,但是這點對程序執(zhí)行毫無影響)。startup.s文件完成S3C2410A芯片的一些初始化工
作,例如,關(guān)閉看門狗的復(fù)位功能和中斷功能(這里暫時關(guān)閉了,以后會開啟這個功能,喂狗的時間周期小于10秒。注意看門狗定時器的定時功能依然工作);設(shè)置CPU時鐘工作頻率為192MHz(即FCLK的頻率為192MHz,PCLK為48MHz);設(shè)置存儲器管理器,將外部32MB的SDRAM配置在區(qū)塊6上;設(shè)置各種工作模式的堆棧指針;最后,將程序跳轉(zhuǎn)到C語言的主程序入口main。
startup.s的代碼均為匯編語言,不過這個代碼相對于《ARM原理與C程序設(shè)計》附錄四的啟動代碼來說,是非常簡單的。讀者還可以去閱讀“ARMIARAssemblerReferenceGuide”英文文檔來進一步學習EWARM下的匯編指示符表示方法,這個文檔位于EWARM安裝目錄的一個doc子目錄下。接著,程序指針進入到app.c文件,開始執(zhí)行OSInit()函數(shù),通過單步執(zhí)行將發(fā)現(xiàn),OSInit將首先調(diào)用函數(shù)OSInitHookBegin,再單步進入到OSInitHookBegin,可見我們自己定義的初始化函數(shù)myInitHookBegin就位于其中。即通過執(zhí)行myInitHookBegin函數(shù)就實現(xiàn)了系統(tǒng)的初始化,單步進入myInitHookBegin函數(shù),里面的代碼用于初始化系統(tǒng)異常向量表(這是μC/OS-Ⅱ移植要求必須做的),初始化LED顯示和定時器4,這里將定時器4設(shè)置減計數(shù)到0的頻率為100Hz,也就是說,如果定時器4開中斷后,其產(chǎn)生中斷信號的頻率為100Hz,就是用作μC/OS-Ⅱ的時鐘節(jié)拍頻率。然后,主程序文件app.c執(zhí)行完OSInit后,執(zhí)行OSTaskCreate創(chuàng)建一個任務(wù),這個任務(wù)的代碼位于appfun.c中,用于LED閃爍;接著,執(zhí)行OSStart函數(shù),單步進入OSStart函數(shù)后,可見該函數(shù)的內(nèi)容如下:第一次執(zhí)行OSStart時,變量OSRunning為OS_FALSE
(μC/OS-ⅡV2.86中真用OS_TRUE表示,假用OS_FALSE表示),所以會執(zhí)行第4~8行代碼,進行任務(wù)調(diào)度,并執(zhí)行優(yōu)先級最高的任務(wù)。在執(zhí)行完OSStartHighRdy函數(shù)后,將開放所有中斷,并且工作在管理(SVC)模式下(事實上,工程ex3_1幾乎總是工作在SVC模式下,除了極少數(shù)語句會工作在常規(guī)中斷(IRQ)模式下外)?,F(xiàn)在,IRQ中斷開放了,同時,μC/OS-Ⅱ會發(fā)現(xiàn)我們定義的任務(wù)AppTaskStart,并進入其代碼中運行(位于appfun.c中),函數(shù)AppTaskStart將首先打開定時器4中斷,然后再進入死循環(huán)中(所有任務(wù)都是死循環(huán)執(zhí)行的,不會返回)。為了清楚地說明具體的執(zhí)行路線,下面列出AppTaskStart任務(wù)中的死循環(huán)代碼:
1while(1)
2{
3LEDon(1);
4OSTimeDlyHMSM(0,0,1,0);
5LEDon(2);
6OSTimeDly(100);
7}任務(wù)AppTaskStart進入死循環(huán)后,首先執(zhí)行LEDon(1)(此處不妨假設(shè)定時器4中斷還沒有來到),使LED1號燈點亮;然后,執(zhí)行OSTimeDlyHMSM(0,0,1,0),這是一個μC/OS-Ⅱ延時函數(shù),進入這個函數(shù)后,實際上μC/OS-Ⅱ?qū)⑶袚Q到一個名為“μC/OS-ⅡIdle”的空閑任務(wù);空閑任務(wù)每隔0.01秒會收到定時器4中斷,進行任務(wù)調(diào)度;當OSTimeDlyHMSM(0,0,1,0)延時滿1秒(實際上任務(wù)AppTaskStart的延時計數(shù)達到1秒)后,任務(wù)會由空閑任務(wù)調(diào)度到AppTaskStart任務(wù),程序指針回到LEDon(2)語句執(zhí)行,關(guān)閉LED1號燈,點亮LED2號燈;然后,又進入到OSTimeDly(100)語句執(zhí)行,循環(huán)以上過程。函數(shù)OSTimeDlyHMSM(0,0,1,0)為延時函數(shù),四個參數(shù)的含義為時、分、秒、毫秒,由于定時器4的中斷頻率為100Hz,所以,最小的延時為10ms(它也有最大延時限制,但一般程序中不會越過這個最大限制)。而函數(shù)OSTimeDly用得更多一些,只有一個參量,表示延時時鐘節(jié)拍數(shù),如果時鐘節(jié)拍頻率為100Hz,則OSTimeDly(100)剛好延時1秒,與函數(shù)OSTimeDlyHMSM(0,0,1,0)的功能完全相同。
讀者可能會對上述介紹有些迷茫,相信在學習完第四章后,將會完全理解上述過程。畢竟,本章的主要目的在于移植μC/OS-ⅡV2.86,而不是詳細介紹其任務(wù)調(diào)度過程。
J.J.Labrosse先生編寫的“μC/OS-ⅡandARMProcessorsApplicationNote,AN-1014Rev.F”移植文檔有56頁,關(guān)于μC/OS-Ⅱ的移植工作介紹得非常細致全面,是移植μC/OS-Ⅱ必讀的參考資料。本節(jié)除摘錄了其中一些主要內(nèi)容外,還結(jié)合第3.1節(jié)進行了必要的補充。3.2μC/OS-Ⅱ移植由第3.1節(jié)知,工程ex3_1的文件結(jié)構(gòu)如圖3-7所示。除了底層硬件UP-Star外,軟件部分可以分為四部分,即用戶編寫的應(yīng)用程序、μC/OS-Ⅱ內(nèi)核文件、μC/OS-Ⅱ移植文件和BSP(BoardSupportPackage)板級支持包文件。圖3-7顯示了各個部分之間的關(guān)系:移植文件屏蔽了硬件的具體操作細節(jié),為μC/OS-Ⅱ內(nèi)核文件服務(wù);μC/OS-Ⅱ內(nèi)核文件管理著系統(tǒng)的所有資源,為應(yīng)用程序服務(wù);當應(yīng)用程序需要直接訪問底層硬件時,可借助于BSP文件。圖3-7工程ex3_1文件結(jié)構(gòu)工程ex3_1中移植相關(guān)的文件保存在D:\ZYUCOSII\ex3_1\
ports中(其中也包含了BSP板級支持包文件),這個目錄下有8個文件,如圖3-8所示。習慣上也可把BSP文件bsp.h和bsp.c歸類為移植文件。圖3-8中,bsp.h文件主要是宏定義一些S3C2410A芯片外設(shè)寄存器地址和自定義函數(shù)聲明;startup.s文件為啟動代碼文件,用于初始化CPU時鐘和存儲器配置等,并跳轉(zhuǎn)到C語言入口地址;os_dbg.c文件主要為μC/OS-Ⅱ及其配置提供在線調(diào)試信息;os_cfg.h文件為μC/OS-Ⅱ定義配置常量。其中,bsp.h和startup.s文件內(nèi)容的說明可參閱第3.1節(jié)。os_cfg.h文件內(nèi)容將在第五章的5.7節(jié)介紹。下面重點介紹其余四個文件的內(nèi)容,即os_cpu.h、os_cpu_c.c、os_cpu_a.asm和bsp.c文件。圖3-8工程ex3_1中的移植文件3.2.1os_cpu.h文件
os_cpu.h文件有241行代碼,限于篇幅,這里不給出完整的代碼了,第3.1節(jié)介紹了獲得該文件代碼的方法。移植μC/OS-Ⅱ時,需要考慮不同的編譯器可能對數(shù)據(jù)類型的定義不盡相同。例如,在EWARM中,short為16位有符號整型,而int為32位有符號整型。為了適應(yīng)不同的編譯系統(tǒng),移植人員需要查看編譯器關(guān)于基本數(shù)據(jù)類型的定義,在EWARM中,可以作如下的自定義數(shù)據(jù)類型:這樣,如果定義無符號16位整型數(shù),使用類型INT16U即可。注意上述代碼的第11行和12行,第11行定義了類型OS_STK,專門用于定義堆棧;第12行定義了類型OS_CPU_SR,專門用于定義CPSR寄存器變量,用于臨時保存CPSR的值。這兩行自定義類型的主要目的在于增強程序的可讀性。程序中那些執(zhí)行過程中不能被中斷的代碼,稱為Critical代碼段,常被譯為臨界(段)代碼,本書采用這一譯法。因為這類代碼往往用于設(shè)置硬件寄存器或初始化外設(shè),實際上是表示硬件狀態(tài)切換的代碼,有一種狀態(tài)“邊界”臨時轉(zhuǎn)換的含義,故譯為“臨界段”比較合適。臨界段代碼中中斷是關(guān)閉的,所以臨界段代碼一般比較短小,進入臨界段前需要關(guān)閉中斷;離開臨界段后要恢復(fù)CPSR寄存器的狀態(tài)。μC/OS-Ⅱ在os_cpu.h中宏定義了兩個函數(shù),分別用于關(guān)閉中斷和恢復(fù)CPSR寄存器狀態(tài),其代碼如下:
μC/OS-Ⅱ有三種中斷管理的方法,一般使用方法3,即上述第1行代碼中宏定義OS_CRITICAL_METHOD為3;第15~16行代碼為宏函數(shù),即調(diào)用OS_CPU_SR_Save()函數(shù)保存當前CPSR寄存器的值,并關(guān)閉中斷;調(diào)用OS_CPU_SR_
Restore(cpu_sr)函數(shù)恢復(fù)CPSR的值,注意這里是“恢復(fù)”,如果原來的中斷是關(guān)閉的,則調(diào)用OS_CPU_SR_Restore后,中斷仍然是關(guān)閉的,即不能用OS_EXIT_CRITICAL來開中斷!如果OS_CPU_INT_DIS_MEAS_EN大于0,還將調(diào)用第9行和第11行的兩個函數(shù),對中斷關(guān)閉期間進行計數(shù),用于統(tǒng)計中斷關(guān)閉的時長。第8行和第10行末尾的“\”是續(xù)行符,表示其下的一行代碼和當前行代碼是同一行代碼。
在os_cpu_a.asm中可以找到如下代碼:上述代碼的解釋為:第1行定義標號OS_CPU_SR_Save,即函數(shù)名;第2行將CPSR的值保存到R0寄存器,R0的值為函數(shù)的返回值;第3行,R0的值與OS_CPU_ARM_CONTROL
_INT_DIS常量(值為0xC0)取或,送入R1寄存器,此時R1的第7位和第6位為1;第4行將R1的值寫入CPSR的控制域,即CPSR的第7位和第6位寫為1;第5行跳轉(zhuǎn)。同理,第8行定義標號OS_CPU_SR_Restore,即函數(shù)名;第9行將R0的值寫入CPSR寄存器的控制位域,此處R0為全局參數(shù),即函數(shù)OS_CPU_SR_Restore的參數(shù);第10行跳轉(zhuǎn)。
S3C2410A芯片封裝ARM920T核,其堆棧增長方向為由內(nèi)存高地址向低地址,故在os_cpu.h中定義:
#defineOS_STK_GROWTH1/*StackgrowsfromHIGHtoLOWmemoryonARM*/
任務(wù)級的切換調(diào)用宏函數(shù)OS_TASK_SW(),這個宏函數(shù)位于os_cpu.h中:
#defineOS_TASK_SW()OSCtxSw()
用戶需要編寫的異常處理函數(shù)也位于os_cpu.h中,即
voidOS_CPU_ExceptHndlr(INT32Uexcept_type);
os_cpu.h中的其他代碼請讀者自己閱讀,這里不再說明。這個文件在移植時不需要做任何修改!3.2.2os_cpu_c.c文件
os_cpu_c.c文件第24行改為“#include"..\\ucosii\\ucos_ii.h"”,即添加包括文件路徑。該文件主要用于實現(xiàn)一些“鉤子”函數(shù),即OSInitHookBegin()、OSInitHookEnd()、OSTaskCreateHook()、OSTaskDelHook()、OSTaskIdleHook()、OSTaskStatHook()、OSTaskStkInit()、OSTaskSwHook()、OSTCBInitHook()和OSTimeTickHook()函數(shù)。之所以稱之為鉤子函數(shù),是由于這個函數(shù)放置在相應(yīng)的函數(shù)中調(diào)用,用于擴充調(diào)用它們的函數(shù)的功能,就像一個鉤子一樣掛在那里,這些函數(shù)大部分可以為空函數(shù)。例如,OSInitHookBegin函數(shù)位于OSInit函數(shù)開頭,即進入OSInit函數(shù)后,首先執(zhí)行OSInitHookBegin函數(shù),而我們自定義的系統(tǒng)初始化函數(shù)就位于OSInitHookBegin函數(shù)中,如下:上述代碼的第24行為我們自定義的系統(tǒng)初始化函數(shù)。其中第12行代碼原文中沒有“++”,是筆者添上去的,估計是J.J.Labrosse先生的失誤,盡管這里“++”意義不是很大。第15行至19行代碼為定義異常堆棧首地址。在μC/OS-ⅡV2.86中要求所有異常模式下的堆棧共用一個,其大小為OS_CPU_
EXCEPT_STK_SIZE,定義在文件os_cpu.h或app_cfg.h中。全部的10個鉤子函數(shù)中,只有OSTaskStkInit函數(shù)是必須編寫的。每個任務(wù)都是一個死循環(huán),任務(wù)創(chuàng)建后就保存在內(nèi)存中了,任務(wù)被“調(diào)用”的含義嚴格意義上講是返回到某個任務(wù)去執(zhí)行!這個概念很重要,這是μC/OS-Ⅱ嵌入式操作系統(tǒng)下函數(shù)調(diào)用與普通芯片級程序下函數(shù)調(diào)用的不同之處。因此任務(wù)被“調(diào)用”執(zhí)行時,即程序指針從某個任務(wù)返回到該任務(wù)時,要做一系列的出棧操作,即恢復(fù)該任務(wù)的執(zhí)行環(huán)境。但事實上,任務(wù)被創(chuàng)建時并沒有執(zhí)行任務(wù),當然也不會有入棧操作,所以,必須在OSTaskStkInit函數(shù)中進行模擬的入棧操作,即讓任務(wù)創(chuàng)建時看起來有一個入棧的過程。在任務(wù)創(chuàng)建時首先會調(diào)用OSTaskStkInit函數(shù),目的就是完成任務(wù)的入棧操作,并且這個入棧操作與OSStartHighRdy(位于os_cpu_a.asm中)出棧操作必須對應(yīng)!這里OSTaskStkInit函數(shù)的代碼如下所示:再強調(diào)一下,每個任務(wù)都是一個死循環(huán)函數(shù),一個任務(wù)被“調(diào)用”執(zhí)行時,實際上是返回到那個任務(wù)去執(zhí)行,而不是調(diào)用那個任務(wù)!返回一個任務(wù)去執(zhí)行,應(yīng)首先恢復(fù)這個任務(wù)的執(zhí)行環(huán)境,即執(zhí)行一個出棧操作。任務(wù)在創(chuàng)建時必須調(diào)用OSTaskStkInit函數(shù)“制造”一個入棧操作,即與返回到任務(wù)時的出棧操作完全相反的操作。而這個入棧操作意義不大,只有任務(wù)的入口地址和參數(shù)有效,即上述代碼的第10行和第24行,其余行的入棧操作只是對應(yīng)出棧過程而已,入棧的數(shù)值可以隨意選取。第26或27行很重要,根據(jù)ARM工作模式或Thumb工作模式設(shè)定入棧的CPSR的值(當出棧時這個值用于恢復(fù)CPSR的值,從而開放中斷)。
os_cpu_c.c文件在移植時,除了前述在OSInitHookBegin中添加自定義的初始化函數(shù)myInitHookBegin外,其余內(nèi)容不需要修改。用戶添加鉤子功能時,不需要直接在os_cpu_c.c的各個鉤子函數(shù)中添加代碼,而只需要在各鉤子函數(shù)中調(diào)用的“應(yīng)用鉤子函數(shù)”中添加代碼即可。例如:程序設(shè)計人員不需要直接在OSTaskCreateHook中添加代碼,而只需要在App_TaskCreateHook(上述代碼的第21行)函數(shù)中添加代碼,而這個App_TaskCreateHook函數(shù)一般放在bsp.c或其他用戶編寫的程序文件中。這樣做的好處在于保持μC/OS-Ⅱ內(nèi)核代碼和移植代碼的完整性,不同的用戶使用時,可清楚地劃分哪些是自己添加的代碼,哪些是μC/OS-Ⅱ的代碼,當程序出現(xiàn)調(diào)試或運行錯誤時,可以集中精力從自己添加的代碼中尋找錯誤。各個鉤子函數(shù)中調(diào)用的“應(yīng)用鉤子函數(shù)”為:OSTaskCreateHook調(diào)用App_TaskCreateHook,在μC/OS-Ⅱ調(diào)用OSTaskCreate或OSTaskCreateExt創(chuàng)建一個任務(wù)時調(diào)用該函數(shù),用戶可以在此添加特殊功能的移植代碼;OSTaskDelHook調(diào)用App_TaskDelHook,在刪除一個任務(wù)(使任務(wù)處于休眠態(tài))時調(diào)用該函數(shù);OSTaskIdleHook調(diào)用App_TaskIdleHook,μC/OS-Ⅱ進入空閑狀態(tài)時調(diào)用該函數(shù),一般地,可在該函數(shù)中添加使CPU工作于低功耗狀態(tài)的代碼;
OSTaskStatHook調(diào)用App_TaskStatHook,統(tǒng)計任務(wù)中調(diào)用該函數(shù);OSTaskSwHook調(diào)用App_TaskSwHook,任務(wù)級切換時調(diào)用該函數(shù);OSTCBInitHook調(diào)用App_TCBInitHook,在OS_TCBInit函數(shù)創(chuàng)建了TCB后,調(diào)用該函數(shù);OSTimeTickHook調(diào)用App_TimeTickHook,在每個時鐘節(jié)拍都會調(diào)用該函數(shù)。每個鉤子函數(shù)的調(diào)用位置很重要,后續(xù)章節(jié)中還會介紹。此外,讀者可去查看μC/OS-Ⅱ源代碼,以便了解到鉤子函數(shù)更準確詳細的調(diào)用位置。3.2.3os_cpu_a.asm文件
os_cpu_a.asm文件有843行代碼,在學習《ARM原理與C程序設(shè)計》一書后,幾乎可以讀懂全部代碼。我們認為,讀懂這個文件的全部代碼是有必要的,這些代碼中包含了對異常處理的一個精湛的方法,可以讓讀者收獲很大;而且,這些代碼寫得相當出色和專業(yè),是學習匯編語言的典范例子。
這里只講述OSStartHighRdy函數(shù),其余內(nèi)容讀者在學習完第四章后,再去自行研究。
為了介紹的方便,把OSStartHighRdy函數(shù)的內(nèi)容羅列如下:上述代碼中,第1行為標號,也用作C函數(shù)名;第3行設(shè)置CPSR的值,進入SVC模式,關(guān)閉普通中斷和快速中斷;第5~7行,調(diào)用函數(shù)OSTaskSwHook,調(diào)用的方法為首先將保存了OSTaskSwHook跳轉(zhuǎn)地址的地址存入R0寄存器,將PC的當前值保存到LR中,跳轉(zhuǎn)到R0地址處,此時的R0處為一個跳轉(zhuǎn)地址,于是進入到OSTaskSwHook執(zhí)行;第9~11行依次為_OS_Running的值保存到R0中,R1的值賦為1,將R1的值即1寫入到_OS_Running地址處,而_OS_Runing地址處的值定義為OSRunning,所以,這幾句執(zhí)行的結(jié)果為OSRunning賦為1(即真);在os_cpu_a.asm的第822行,有語句“_OS_TCBHighRdy:DC32OSTCBHighRdy”,第14~16行依次為將_OS_
TCBHighRdy的值寫入R0中,再將_OS_TCBHighRdy地址處的值寫入R0中,最后,以_OS_TCBHighRdy地址處的值為地址,將該地址里存儲的值寫入SP中,即堆棧指針指向新的TCB堆棧(參考第四章);第18行將CPSR出棧,出棧的值賦給SPSR,第18行與第21行聯(lián)合完成了對第3.2.2節(jié)OSTaskStkInit中入棧后堆棧的出棧操作(假設(shè)屬于同一個任務(wù)的調(diào)用)。上述內(nèi)容在學習了第四章后再去理解將更加容易一些。此外,os_cpu_a.asm中的OSCtxSw和OSIntCtxSw也是極為重要的代碼段,需要認真學習。3.2.4bsp.c文件
bsp.c文件屬于BSP(板級支持包)文件,廣義上,也可以視為移植文件,因為μC/OS-Ⅱ內(nèi)核文件的正常運作也需要這個文件中的部分函數(shù)。從第3.1.1節(jié)中可以找到這個文件完整的代碼,這里僅需要介紹第3.1.1節(jié)第S9步中提到的一些代碼,為方便起見,將這些代碼羅列如下:14
15break;
16default:
17break;
18}
19break;
20default:
21break;
22}
23}上述函數(shù)OS_CPU_ExceptHndlr是用戶需要編寫的中斷處理函數(shù)。第3行判斷參數(shù)except_type的值,如果為6,表示為IRQ普通中斷。這時在第6行進一步判斷INTOFFSET的值,如果為14,表示為定時器4的中斷,此時在第9行調(diào)用OSTimeTick函數(shù)進入系統(tǒng)時鐘節(jié)拍處理,這個函數(shù)是非常重要的,如果節(jié)拍太慢,系統(tǒng)的實時性會變差;如果節(jié)拍太快,系統(tǒng)的負擔加重,一般設(shè)為10~100Hz。第11~13行與定時器4的中斷處理相關(guān),參見《ARM原理與C程序設(shè)計》第170頁或“S3C2410AUser’sManual”第14章。當定時器4中斷發(fā)生后,os_cup_a.asm中的異常處理函數(shù)將會觸發(fā)OS_CPU_ExceptHndlr函數(shù),進一步調(diào)用OSTimeTick函數(shù),進入系統(tǒng)節(jié)拍處理。
至此,讀者應(yīng)回到第3.1節(jié)反復(fù)運行工程ex3_1,多設(shè)置一些斷點,或把時鐘節(jié)拍加長到10秒以上單步運行(筆者在初次學習μC/OS-Ⅱ移植時,曾把時鐘節(jié)拍延長到19.08845秒),以體會移植代碼是如何工作的。本節(jié)在第3.1節(jié)工程ex3_1的基礎(chǔ)上,添加串口通信功能,生成工程ex3_2。在工程ex3_2中的AppTaskStart任務(wù)中,再新建3個任務(wù),即AppTaskOne、AppTaskTwo和AppTaskThree。其中,AppTaskOne每隔一秒點亮LED1燈一次;AppTaskTwo每隔2秒點亮LED2燈一次;AppTaskThree每隔4秒點亮LED3燈一次。當燈點亮時,串口調(diào)試助手同步顯示被點亮的LED燈號。
3.3μC/OS-Ⅱ串口通信實例3.3.1實例ex3_2
按第3.1節(jié)的方法新建工程ex3_2,保存目錄為D:\ZYUCOSII\ex3_2,工程ex3_2的工作區(qū)如圖3-9所示(這時的工程ex3_2與工程ex3_1功能完全相同,只是工程名和存儲目錄不同而已)。圖3-9工程ex3_2的最初版本為了清楚地介紹工程ex3_2的創(chuàng)建過程,下面分步進行:
S1.在app.c文件中創(chuàng)建任務(wù)AppTaskStart時,將其優(yōu)先級指定為5,即OSTaskCreate函數(shù)的最后一個參數(shù)為5,完整的app.c文件內(nèi)容如下:
1/*FileName:app.c
2**Byzhnyong@21
3**@2009-4-4
4**MainRoutine
5**CopyrightReserved
6*/
7
本書后面章節(jié)的幾乎所有實例的主程序文件與上述代碼完全相同,即有意義的代碼只有第8行和第10~15行等7行,程序的功能主要在appfun.c文件中實現(xiàn)。
S2.在bsp.h文件的末尾,添加一行串口0初始化函數(shù)聲明語句,即
voidmyInitUART0(void);//InitializeUART0
在bsp.h文件中添加對串口0寄存器地址的宏定義語句,如下:
1//---------------------------------------------------------
2//UART0
3//---------------------------------------------------------上述代碼可以放置在bsp.h的任何位置。
在bsp.c文件的末尾,添加上述函數(shù)myInitUART0的函數(shù)體,即
1//InitializeUART0
2voidmyInitUART0(void)
3{
4//SetGPH3:2asRXD0:TXD0
5GPHCON=0xA0;
6
7//SetUART0Baudrate:4800bps,8-bit,1-bitstop
8UFCON0=0x0;
9UMCON0=0x0;
10ULCON0=0x03;
11UCON0=0x05;
12UBRDIV0=0x270;
13}在bsp.c文件的myInitHookBegin函數(shù)內(nèi)添加一條語句,即“my
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國節(jié)能5號銅瓦數(shù)據(jù)監(jiān)測研究報告
- 2025至2030年中國耳插數(shù)據(jù)監(jiān)測研究報告
- 2025至2030年中國硬脂醇數(shù)據(jù)監(jiān)測研究報告
- 2025至2030年中國電泳活扳手數(shù)據(jù)監(jiān)測研究報告
- 二零二五年度房屋租賃合同補充協(xié)議3篇
- 二零二五版智慧家居項目營銷策劃合作協(xié)議3篇
- 二零二五年度夫妻財產(chǎn)分割協(xié)議起訴離婚程序規(guī)范指引3篇
- 二零二五版生態(tài)循環(huán)農(nóng)業(yè)養(yǎng)殖委托合同3篇
- 二零二五年度商鋪租賃合同范本個人商鋪租賃專用3篇
- 旅行社承包經(jīng)營合同
- 開題報告:AIGC背景下大學英語教學設(shè)計重構(gòu)研究
- 師德標兵先進事跡材料師德標兵個人主要事跡
- 連鎖商務(wù)酒店述職報告
- 石油化工企業(yè)環(huán)境保護管理制度預(yù)案
- 2024年山東省煙臺市初中學業(yè)水平考試地理試卷含答案
- 《實踐論》(原文)毛澤東
- 抗腫瘤治療所致惡心嘔吐護理
- 第三單元名著導(dǎo)讀《紅星照耀中國》(公開課一等獎創(chuàng)新教學設(shè)計+說課稿)
- 壓力鋼管制造安裝及驗收規(guī)范
- 2024-2030年中國14-丁二醇(BDO)行業(yè)市場現(xiàn)狀供需分析及重點企業(yè)投資評估規(guī)劃分析研究報告
- YYT 0681.11-2014 無菌醫(yī)療器械包裝試驗方法 第11部分:目力檢測醫(yī)用包裝密封完整性
評論
0/150
提交評論