uCOSII在ARM微处理器上的移植和编译课程设计报告书.docx
《uCOSII在ARM微处理器上的移植和编译课程设计报告书.docx》由会员分享,可在线阅读,更多相关《uCOSII在ARM微处理器上的移植和编译课程设计报告书.docx(23页珍藏版)》请在冰豆网上搜索。
uCOSII在ARM微处理器上的移植和编译课程设计报告书
ARM原理与应用报告
一、设计内容
1.用ADS1.2IDE软件进行程序代码编译设计,生成可执行的输出文件,并显示运行结果,实现uC/OS-II 内核在ARM处理器上移植。
2.uC/OS-II 在ARM 微处理器上的移植及编译。
二、设计目的与要求
目的:
ARM原理与应用课程设计是学生理论联系实际的重要实践教学环节,是对学生进行的一次专业训练,也是对学生掌握和应用嵌入式系统相关知识能力的有效测试。
通过ARM原理与应用课程设计,使学生初步了解嵌入式系统软件开发的一般过程和基本设计方法,使学生进一步巩固和加深所学的专业理论知识,培养学生文献查阅、报告撰写等基本技能;培养学生独立分析和解决工程实际问题的能力;培养学生的团队协作精神、创新意识、严肃认真的治学态度和严谨求实的工作作风。
要求:
1)了解uC/OS-II内核的主要结构。
2)掌握将uC/OS-II内核移植到ARM处理器上的基本方法。
3)在给定的设备(UP-TECHPXA270-S嵌入式开发平台、PC机、WinXP、ADS1.2集成开发环境、仿真器驱动程序、超级终端通讯程序)上加以实验,学会自己分析、找出解决问题的方法。
4)对设计中遇到的问题和困难,独立思考,查阅资料,分析、观察、判断、试验、再判断以寻找答案。
5)分析结果,写出设计总结报告论述自己的观点,并应将参考资料列在报告后面以备查询。
内容尽量翔实(如上机过程、环境搭建),其中必须有按自己所理解、用自己的语言所描述的内容。
三、设计环境或器材、原理与说明
环境:
硬件:
PC机,博创UP-TECHPXA27-S目标板ARM7TDMI微处理器,串口线,并口JTAG转换线;
软件:
MS.Virtual.PC.2004,WindowsXP系统,ADS1.2IDE编译环境,LPC2000FlashUtility烧写程序、超级终端通讯程序.
原理与说明:
1.《ARM原理与应用》课程设计题目涉及ARM应用的诸多方面,须经过思考和认真的学习,有一定难度,在深度方面主要要求学生对具体ARM指令的分析理解,目标板ARM处理器的硬件认识了解,ADS1.2IDE软件的操作能力,解读uC/OS-II内核的自学能力以及自我解决问题的能力。
2.µc/os-ii是一个完整的,可移植、可固化、可裁减的占先式实时多任务内核,它功能强大,支持56个用户任务,支持信号量、邮箱、消息队列等多种常用的进程间通信机制。
公开源代码,程序可读性强、移植性好,同时可免费获得。
lpc2119是由philips生产的一款32位arm7tdmi-s微处理器,其核心为高性能的32位risc体系结构,并具有高密度的16位指令集和极低的功耗。
具有零等待128K字节的片内Flash,16k的Sram,无需扩展存储器,使系统更为简单、可靠。
四、设计过程(步骤)或程序代码
源代码:
1.OS_CPU.H文件
该文件定义了和处理器相关的定义及一些全局函数声明。
由于ARM7处理器字长为32位,半字长为16位,字节为8位,因此在OS_CPU.h文件修改了一些相关定义以确保uC/OS-Ⅱ的可移植性:
#ifndef__OS_CPU_H__
#define__OS_CPU_H__
#ifdefOS_CPU_GLOBALS
#defineOS_CPU_EXT
#else
#defineOS_CPU_EXTextern
#endif
typedefunsignedcharBOOLEAN;
typedefunsignedcharINT8U;/*Unsigned8bitquantity*/
typedefsignedcharINT8S;/*Signed8bitquantity*/
typedefunsignedintINT16U;/*Unsigned16bitquantity*/
typedefsignedintINT16S;/*Signed16bitquantity*/
typedefunsignedlongINT32U;/*Unsigned32bitquantity*/
typedefsignedlongINT32S;/*Signed32bitquantity*/
typedeffloatFP32;/*Singleprecisionfloatingpoint*/
typedefdoubleFP64;/*Doubleprecisionfloatingpoint*/
typedefunsignedintOS_STK;/*Eachstackentryis16-bitwide*/
typedefunsignedintOS_CPU_SR;/*DefinesizeofCPUstatusregister(PSR=32bits)*/
#defineBYTEINT8S/*Definedatatypesforbackwardcompatibility...*/
#defineUBYTEINT8U/*...touC/OSV1.xx.Notactuallyneededfor...*/
#defineWORDINT16S/*...uC/OS-II.*/
#defineUWORDINT16U
#defineLONGINT32S
#defineULONGINT32U
从上面定义可看出,uC/OS-Ⅱ代码不使用C的short,int和long等数据类型,这是因为它们是与编译器相关的,不可移植。
uC/OS-Ⅱ需要先禁止中断再访问代码的临界段,并且在访问后重新允许中断,这就使得uC/OS-Ⅱ能够保护临界段代码免受多任务或中断服务例程的破坏。
uC/OS-Ⅱ对关中断以及开中断的宏定义如下:
#defineOS_CRITICAL_METHOD3
#ifOS_CRITICAL_METHOD==3
/*criticalsectionmacrosuse"method3"(savetolocalvar"cpu_sr")*/
externintINTS_OFF(void);/*ASMroutinestotwiddlebits*/
externvoidINTS_ON(void);
#defineOS_ENTER_CRITICAL(){cpu_sr=INTS_OFF();}
#defineOS_EXIT_CRITICAL(){if(cpu_sr==0)INTS_ON();}
#else
#errorpleasedefinecriticalmethod
#endif
#defineOS_STK_GROWTH1/*StackgrowsfromHIGHtoLOWmemoryon80x86*/
//#defineOS_TASK_SW()OSCtxSw()
#endif/*__OS_CPU_H__*/
uC/OS-Ⅱ可以处理从下往上长以及从上往下长两种堆栈方式,但由于ARM处理器的堆栈都是从上往下生长,也就是高地址到低地址的生长方向,因此宏定义如下:
#defineOS_STK_GROWTH1/*堆栈从上往下增长,1向上,0向下*/
2.OS_CPU_C.C文件
在这个文件里主要是OSTaskStkInit()函数和一些钩子函数,需要关心的是OSTaskStkInit()。
OSTaskStkInit()是任务堆栈初始化函数,它由任务建立函数OSTaskCreateExt()调用,用于初始化任务的堆栈,堆栈的结构初始化成看起来刚刚发生过中断一样,所有的寄存器都被入栈。
在ARM体系结构下,任务堆栈空间由高至低依次将保存着pc、lr、r12、r11、r10、…、r1、r0、cpsr、spsr。
OSTaskStkInit()函数有四个参数,task,pdata,ptos,opt,它们和建立任务所使用的参数是一致的。
函数返回堆栈指针所指的地址。
当我们使用OSTaskCreateExt()来建立任务时,就把上述四个参数传递给OSTaskStkInit()函数,初始化好堆栈,再返回给OSTaskCreateExt()堆栈指针,继续走下去。
OSTaskStkInit()函数代码最后,使用R0来传递参数,这是符合ARM汇编的规范,使用R0来传递第一个参数。
#include"includes.h"/*fromuCOSdirectory*/
//#include"ipport.h"/*fromInternichedirectory*/
/*ARMCPU"supervisor"modeforPSRregisters,withINTsenabled*/
#defineSUPMODE0x13
OS_STK*OSTaskStkInit(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT16Uopt)
{unsignedint*stk;
stk=(unsignedint*)ptos;/*加载堆栈指针*/
//USE_ARG(opt);
opt++;/*buildastackforthenewtask*/
/*建立任务环境,ADS1.2使用满递减堆栈*/
*--stk=(unsignedint)task;/*pc*/
*--stk=(unsignedint)task;/*lr*/
*--stk=12;/*r12*/
*--stk=11;/*r11*/
*--stk=10;/*r10*/
*--stk=9;/*r9*/
*--stk=8;/*r8*/
*--stk=7;/*r7*/
*--stk=6;/*r6*/
*--stk=5;/*r5*/
*--stk=4;/*r4*/
*--stk=3;/*r3*/
*--stk=2;/*r2*/
*--stk=1;/*r1*/
*--stk=(unsignedint)pdata;/*r0,第一个参数使用R0传递*/
*--stk=(SUPMODE);/*cpsr*/
*--stk=(SUPMODE);/*spsr*/
return((OS_STK*)stk);}
#ifOS_CPU_HOOKS_EN
voidOSTaskCreateHook(OS_TCB*ptcb)/*任务创建钩子函数,当任务被创建时调用该函数*/
{ptcb=ptcb;}/*ptcb没有用,是为了防止编译器警告*/
voidOSTaskDelHook(OS_TCB*ptcb)/*任务删除钩子函数,当任务被删除时调用该函数*/
{ptcb=ptcb;}/*ptcb没有用,是为了防止编译器警告*/
voidOSTaskSwHook(void){}/*任务切换函数,可以在执行其他操作时进行上下文切换。
*/
voidOSTaskStatHook(void){}/*任务统计钩子函数*/
voidOSTimeTickHook(void){}
voidOSTCBInitHook(OS_TCB*ptcb)
{ptcb=ptcb;}/*PreventCompilerwarning*/
voidOSTaskIdleHook(void){}
voidOSInitHookEnd(void){}
voidOSInitHookBegin(void){}
#endif
3.OS_CPU_A.S文件
该文件的是移植的关键所在,在本文件中必须完成四个函数的编写工作,它们分别为OSIntCtxSw(),OSCtxSw(),OSStartHighRdy()和OSTickISR()。
其中前两个函数是重中之重,它们必须用汇编语言编写,主要完成任务环境的切换工作。
AREA|subr|,CODE,READONLY
EXPORTOSIntCtxSw
EXPORTOS_TASK_SW
EXPORTINTS_OFF
EXPORTINTS_ON
INTS_OFF
mrsr0,cpsr;currentCSR
movr1,r0;makeacopyformasking
orrr1,r1,#0xC0;maskoffintbits
msrCPSR_cxsf,r1;disableints(IRQandFIQ)
andr0,r0,#0x80;returnFIQbitfromoriginalCSR
movpc,lr;return
INTS_ON
mrsr0,cpsr;currentCSR
bicr0,r0,#0xC0;maskonints
msrCPSR_cxsf,r0;enableints(IRQandFIQ)
movpc,lr;return
;Externalsymbolsweneedtheaddressesof
IMPORTOSTCBCur
addr_OSTCBCurDCDOSTCBCur
IMPORTOSTCBHighRdy
addr_OSTCBHighRdyDCDOSTCBHighRdy
IMPORTOSPrioCur
addr_OSPrioCurDCDOSPrioCur
IMPORTOSPrioHighRdy
addr_OSPrioHighRdyDCDOSPrioHighRdy
IMPORTIRQStack;FIQ_STACK
OSIntCtxSw
;postFIQContextswitcher.ThisiscalledfromOSIntExitwhenahookedISR
;wantstoreturninthecontextofanothertask.Weloadthenewtaskscontext
;(fromOSPrioHighRdy)anddothereturnfrominterrupt.
;GetpointertostackwhereISR_FiqHandlersavedinterruptedcontext
;ISRentryonlysavesfirstsevenregsandLR.
;
;addr7,sp,#24;savepointertoregisterfile,wemustadjustthispointertothepositionthatjustEnterInterrupt
LDRsp,=IRQStack;IRQ_STACK;testtodelit
subr7,sp,#4;r7isthepositionthatjustEnterInterrupt
;ChangeARMCPUtoSVCmodeforstackoperations.
;ThisgetstheCPUofftheinterruptstackandbacktothe
;interruptedtask'sstack,whichistheonewewanttoalter.
;
mrsr1,SPSR;getsuspendedPSR
orrr1,r1,#0xC0;disableIRQ,FIQ.
msrCPSR_cxsf,r1;switchmode(sholdbeSVC_MODE)
;PSR,SP,LRregsarenowrestoredtotheinterruptedSVC_MODE.
;nowsetupthetask'sstackframeasOS_TASK_SWdoes...
;ldrr0,[r7,#52];getIRQ'sLR(tasksPC)fromIRQstack//r0-r12
ldrr0,[r7];getIRQ'sLR(tasksPC)fromIRQstack
subr0,r0,#4;ActualPCaddressis(saved_LR-4)
STMFDsp!
{r0};savetaskPC
STMFDsp!
{lr};saveLR
sublr,r7,#52;//wesavether0-r12whenweenterIRQ.
;movlr,r7;saveFIQstackptrinLR(goingtonuker7)
ldmfdlr!
{r0-r12};getsavedregistersfromFIQstack
STMFDsp!
{r0-r12};saveregistersontaskstack
;savePSRandPSRfortaskontask'sstack
MRSr4,CPSR
bicr4,r4,#0xC0;leaveinterruptbitsinenabledmode
STMFDsp!
{r4};savetask'scurrentPSR
MRSr4,SPSR
STMFDsp!
{r4};SPSRtoo
;OSPrioCur=OSPrioHighRdy//changethecurrentprocess
LDRr4,addr_OSPrioCur
LDRr5,addr_OSPrioHighRdy
LDRBr6,[r5]
STRBr6,[r4]
;Getpreemptedtasks'sTCB
LDRr4,addr_OSTCBCur
LDRr5,[r4]
STRsp,[r5];storespinpreemptedtasks'sTCB
;GetnewtaskTCBaddress
LDRr6,addr_OSTCBHighRdy
LDRr6,[r6]
LDRsp,[r6];getnewtask'sstackpointer
;OSTCBCur=OSTCBHighRdy
STRr6,[r4];setnewcurrenttaskTCBaddress
LDMFDsp!
{r4}
MSRSPSR_cxsf,r4
LDMFDsp!
{r4}
BICr4,r4,#0xC0;wemustexittonewtaskwithintsenabled
MSRCPSR_cxsf,r4
LDMFDsp!
{r0-r12,lr,pc}
;voidOS_TASK_SW(void)
;Performacontextswitch.
;Onentry,OSTCBCurandOSPrioCurholdthecurrentTCBandpriority
;andOSTCBHighRdyandOSPrioHighRdycontainthesameforthetask
;tobeswitchedto.
;Thefollowingcodeassumesthatthevirtualmemoryisdirectly
;mappedintophysicalmemory.Ifthisisnottrue,thecachemust
;beflushedatcontextswitchtoavoidaddressaliasing.
OS_TASK_SW
STMFDsp!
{lr};savepc
STMFDsp!
{lr};savelr
STMFDsp!
{r0-r12};saveregistersandretaddress
MRSr4,CPSR
STMFDsp!
{r4};savecurrentPSR
MRSr4,SPSR
STMFDsp!
{r4};saveSPSR
;OSPrioCur=OSPrioHighRdy
LDRr4,addr_OSPrioCur
LDRr5,addr_OSPrioHighRdy
LDRBr6,[r5]
STRBr6,[r4]
;GetcurrenttaskTCBaddress
LDRr4,addr_OSTCBCur
LDRr5,[r4]
STRsp,[r5];storespinpreemptedtasks'sTCB
;GethighestprioritytaskTCBaddress
LDRr6,addr_OSTCBHighRdy
LDRr6,[r6]
LDRsp,[r6];getnewtask'sstackpointer
;OSTCBCur=OSTCBHighRdy
STRr6,[r4];setnewcurrenttaskTCBaddress
;restoretask'smoderegsiters
LDMFDsp!
{r4}
MSRSPSR_cxsf,r4
LDMFDsp!
{r4}
MSRCPSR_cxsf,r4
;returninnewtaskcontext
LDMFDsp!
{r0-r12,lr,pc}
;voidOSStartHighRdy(void)
;Startthetaskwiththehighestpriority;
EXPORTOSStartHighRdy
OSStartHighRdy
LDRr4,addr_OSTCBCur;GetcurrenttaskTCBaddress
LDRr5,addr_OSTCBHighRdy;GethighestprioritytaskTCBaddress
LDRr5,[r5