ucosII在ARM7上地移植.docx

上传人:b****8 文档编号:12543046 上传时间:2023-06-06 格式:DOCX 页数:13 大小:20.99KB
下载 相关 举报
ucosII在ARM7上地移植.docx_第1页
第1页 / 共13页
ucosII在ARM7上地移植.docx_第2页
第2页 / 共13页
ucosII在ARM7上地移植.docx_第3页
第3页 / 共13页
ucosII在ARM7上地移植.docx_第4页
第4页 / 共13页
ucosII在ARM7上地移植.docx_第5页
第5页 / 共13页
ucosII在ARM7上地移植.docx_第6页
第6页 / 共13页
ucosII在ARM7上地移植.docx_第7页
第7页 / 共13页
ucosII在ARM7上地移植.docx_第8页
第8页 / 共13页
ucosII在ARM7上地移植.docx_第9页
第9页 / 共13页
ucosII在ARM7上地移植.docx_第10页
第10页 / 共13页
ucosII在ARM7上地移植.docx_第11页
第11页 / 共13页
ucosII在ARM7上地移植.docx_第12页
第12页 / 共13页
ucosII在ARM7上地移植.docx_第13页
第13页 / 共13页
亲,该文档总共13页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

ucosII在ARM7上地移植.docx

《ucosII在ARM7上地移植.docx》由会员分享,可在线阅读,更多相关《ucosII在ARM7上地移植.docx(13页珍藏版)》请在冰点文库上搜索。

ucosII在ARM7上地移植.docx

ucosII在ARM7上地移植

uc/os-II在ARM7上的移植

1、移植的要求

要使µC/OS-Ⅱ正常运行于某处理器上,须满足以下要求:

1)处理器的C编译器能产生可重入代码;

2)可以在C语言代码中打开和关闭中断;

3)处理器支持中断,并且能产生定时中断(通常在10至100Hz之间);

4)处理器支持能够容纳一定量数据(可能是几千字节)的硬件堆栈;

5)处理器有将堆栈指针和其它CPU寄存器读出和存储到堆栈或内存中的指令。

2、移植过程

基于µC/OS-Ⅱ的硬/软件体系结构如下图。

教材P165图5-8

 

µC/OS-Ⅱ的移植集中在OS_CPU.h,OS_CPU_A.s,OS_CPU.c这三个文件上,下面分别详细介绍三个文件中的函数和需要修改或者编写的代码。

2.1OS_CPU.h的移植

该文件定义了和处理器及编译器相关的定义及一些全局函数声明。

由于ARM7处理器字长为32位,半字长为16位,字节为8位,因此在OS_CPU.h文件修改与编译器相关的定义如下:

typedefunsignedcharBOOLEAN;

typedefunsignedcharINT8U;

typedefsignedcharINT8S;

typedefunsignedshortINT16U;/*某些编译器中int是32位的,故统一用short表示*/

typedefsignedshortINT16S;

typedefunsignedlongINT32U;

typedefsignedlongINT32S;

typedeffloatFP32;

typedefdoubleFP64;

typedefunsignedlongOS_STK;/*堆栈宽度为32位,即ARM7种的字对齐方式*/

/*下面是与处理器相关的代码*/

#defineOS_CRITICAL_METHOD2/*使用方式2保护临界代码*/

#defineOS_ENTER_CRITICAL()ARMDisableInt()/*临界段代码保护宏定义*/

#defineOS_EXIT_CRITICAL()ARMEnableInt()

#defineOS_STK_GROWTH1/*定义堆栈生长方向为向下生长*/

#defineOS_TASK_SWOSCtxSw/*宏定义,用于非中断级的任务切换*/

/*下面开始声明全局函数声明,均是OS_CPU_A.S中需要编写的函数*/

externvoidOSCtxSw(void);/*声明任务级任务切换函数*/

externvoidOSIntCtxSw(void);/*声明中断级任务切换函数*/

externvoidARMDisableInt(void);/*声明中断禁止函数*/

externvoidARMEnableInt(void);/*声明中断恢复函数*/

externvoidOSTickISR(void);/*声明时钟中断服务函数*/

2.2OS_CPU_C.C文件

移植OS_CPU_C.C文件时,需要编写的是任务堆栈初始化函数OSTaskStkInit和时钟节拍中断服务钩子函数OSTimeTickHook。

在µC/OS-II中,每一个任务都有自己的任务堆栈,当发生任务切换或者中断时,其CPU使用权被剥脱,为了任务能被再次运行,那么这个被打断的任务所用到的处理器的寄存器内容均应得到保存,按照ARM7处理器的压栈和入栈指令的特点,设计任务堆栈如下任务堆栈的结构:

CPSR

R0

R1

……

R12

LR(R14)

PC(R15)

根据任务堆栈结构示意图,OS_STK函数编写如下:

#defineSVCMODE0x13/*定义svc模式的命令字,用户任务运行在svc模式下*/

OS_STK*OSTaskStkInit(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT16Uopt)

{

OS_STK*stk;/*定义堆栈指针*/

opt=opt;

stk=(OS_STK)ptos;/*保存任务堆栈栈顶指针*/

*--stk=(OS_STK)task;/*用来保存PC,初始化成任务入口地址在被保护存现场的则是该任务运行时被中断时的地址*/

*--stk=(OS_STK)task;/*用来保存LR*/

*--stk=0;/*r12*/

*--stk=0;/*r11*/

*--stk=0;/*r10*/

*--stk=0;/*r9*/

*--stk=0;/*r8*/

*--stk=0;/*r7*/

*--stk=0;/*r6*/

*--stk=0;/*r5*/

*--stk=0;/*r4*/

*--stk=0;/*r3*/

*--stk=0;/*r2*/

*--stk=0;/*r1*/

*--stk=(INT32U)pdata;/*在ARM的编译建议中,r0用于参数传递*/

*--stk=(SVC32MODE|0x40);/*用来保存CPSR,并禁止FIQ,由于任务和操作系统均运行在svc模式,被中断到其他模式再返回后仍然回到svc模式,故SPSR没有用到*/

return((OS_STK*)stk);/*返回任务堆栈的指针*/

}

说明:

用户创建任务时,OSTaskCreat()会调用OSTaskStkInit函数初始化该任务的堆栈,并把返回的堆栈指针保存到该任务的TCB结构中的最前面的参数OSTCBStkPtr中,当该任务要被恢复时,任务切换函数从其TCB块中取得其任务堆栈指针,依次将堆栈内容弹到处理器对应的CPSR、r0,r1,…,r12,lr,pc的寄存器中,完成现场的恢复和程序指针PC的返回。

另一个需要编写的函数是OSTimeTickHook,该函数被时钟节拍中断服务函数OSTickISR中的OSTimeTick函数调用,用来清除时钟节拍中断发生设备的请求。

本移植方案使用S3C44B0X处理器的RTC模块的tick中断作为时钟节拍中断,该函数编写如下:

voidOSTimeTickHook(void)

{

rI_ISPC=((INT32U)0x01)<<20;/*清RTC模块的tick中断*/

}

注意:

用户也可不修改此函数,但是必须在OSTickISR中执行清除发生节拍中断的设备的中断请求标志,为便于说明,本文将利用内核提供给用户的OSTimeTickHook函数来完成清中断的任务。

另外几个hook函数不必去改它们。

至此,OS_CPU.C编写完成。

2.3OS_CPU_A.S文件的移植

该文件是移植过程中唯一需要用汇编语言来实现的文件,也是移植的重点和难点所在。

在这个文件里,需要编写的函数有OSStartHighRdy,OSCtxSW,OSIntCtxSW,OSTickISR,ARMDisableInt,ARMEnableInt几个。

下面先结合us/os的任务切换的过程分析一下这几个函数的作用。

1)OSStartHighRdy()函数

当程序执行内核的OSStart函数时,表示多任务系统开始启动,OSStart函数将调用OSStartHighRdy函数从最高优先级任务的TCB块中获得该任务的堆栈指针,通过该指针,依次从该任务的任务堆栈中恢复CPU的现场。

由于任务在堆栈初始化时,已经设定了弹出到程序指针寄存器PC的是该任务函数的入口地址,因此,OSStartHighRdy函数只需依次弹出任务栈内容到处理器寄存器,该任务便将得以运行。

2)OSCtxSw()函数

该函数是任务级的上下文切换函数,当任务被阻塞而主动请求CPU开始任务调度时执行,其过程是将当前任务的的CPU现场保存到该任务堆栈中去,然后从OSTCBHighRdy中获得更高优先级任务的堆栈指针,再从该指针指向的堆栈中恢复此任务的CPU现场,使之继续执行,从而完成一次任务级别的切换。

下为此函数的伪代码。

voidOSCtxSw(void)

{

保存处理器寄存器;/*将欲挂起的任务的CPU寄存器压入当前堆栈*/

OSTCBCur->OSTCBStkPtr=sp;/*OSTCBCur目前指向的是被打断的任务TCB,此操作将该任务的栈顶指针保存到其OSTCBStkPtr中去,便于下次恢复时从这里获取栈顶指针*/

OSTCBCur=OSTCBHighRdy;/*OSTCBHighRdy指向的是就绪的高优先级任务的TCB,将其装载到OSTCBCur中来*/

SP=OSTCBHighRdy->OSTCBStkPtr;/*取得就绪的高优先级任务的栈顶指针*/

恢复该任务的现场();/*于是便可通过刚取得的栈顶指针恢复该任务*/

执行中断返回指令;/*若OSCtxSw含有软中断指令则需中断返回,本移植不使用软中断*/

}

3)OSIntCtxSw()函数

该函数用于中断级的上下文切换。

由于CPU响应时钟节拍中断后,处理器从svc进入了irq模式,并进入时钟节拍中断服务函数OSTickISR,OSTickISR函数发现若有高优先级任务需要运行,则系统不返回中断前的任务,而直接调度就绪的高优先级任务使之尽快得到执行,以保证实时性能。

但是由于OSTickISR函数一开始已经保存过任务中断前的CPU现场,因此OSIntCtxSW()不需要再进行类似的操作。

当OSTickISR调用OSIntExit函数找出需要运行的更高优先级任务后,OSIntExit会将该任务的TCB指针放在OSTCBHighRdy中,然后OSIntExit在最后调用OSIntCtxSW函数来从OSTCBHighRdy中获取堆栈指针然后恢复该高优先级任务的现场,使得其继续执行,并不再返回时钟节拍中断服务程序。

显然,OSIntCtxSW函数的过程和OSCtxSW函数的后半部分操作相同,因此,OSCtxSW可以借用OSIntCtxSW的代码。

4)OSTickISR()函数

在CPU响应时钟节拍中断后,程序指针PC发生跳转后进入该函数,由于OSTickISR调用OSTimeTick函数使得所有的延时节拍不为0的任务延时节拍数减1,并调用OSIntExit函数来找出就绪的高优先级任务,若需要切换,则最后由OSIntCtxSw来完成新任务的调度,否则仍然返回到被时钟节拍中断的任务。

OSTickISR函数的伪码和注释:

voidOSTickISR(void)

{

保存处理器寄存器;/*注意在irq模式下保存CPSR_svc时,要先强制切换到svc模式*/

调用OSIntEnter();/*防止在嵌套的中断中发生调度*/

给产生中断的设备清中断;/*本操作已由OSTimeTick中的OSTimeTickHook函数完成*/

调用OSTimeTick();/*将所有任务不为0的延时节拍数减1*/

调用OSIntExit();/*检索就绪任务,并将需要调度的高优先级任务的堆栈指针存到OSTCBHighRdy中去,然后调用OSIntCtxSW恢复该任务的现场*/

恢复处理器寄存器;

执行中断返回指令;/*若没有中断级任务切换,则返回到中断前的任务*/

}

5)ARMDisableInt和ARMEnableInt函数

ARMDisableInt是用来暂时禁止FIQ及IRQ中断的函数,ARMEnableInt则是恢复ARMDisableInt执行前的中断使能状态,二者成对使用,用来保护临界段代码不被中断破坏。

本移植使用方式2,即在进入临界段代码前关中断,完成后恢复先前的中断使能状态。

下面给出OS_CPU_A.S的全部内容和注释。

;*****OS_CPU_A.S文件汇编代码开始*****

AREA|subr|,CODE,READONLY;声明为代码段

;*****OSStartHighRdy代码开始*****

EXPORTOSStartHighRdy;关键词EXPORT表示声明此函数被其他文件使用,下同

IMPORTOSTaskSwHook;关键词IMPORT声明此函数/参量在其他文件中定义,下同

IMPORTOSTCBHighRdy

IMPORTOSRunning

OSStartHighRdy;使就绪表中任务最高的优先级的任务开始运行

BLOSTaskSwHook;调用用户的Hook函数,空函数

LDRr4,=OSRunning;将OSRunning置1,声明多任务OS开始运行

MOVr5,#1

STRBr5,[r4]

LDRr4,=OSTCBHighRdy;伪指令,取得存储OSTCBHighRdy的地址

LDRr4,[r4];得到最高优先级任务的任务堆栈地址

LDRsp,[r4];切换到新任务的堆栈

LDMFDsp!

{r4};从新任务堆栈中读取第一个参数(CPSR)到(r4)

MSRcpsr_cxsf,r4;再传给cpsr,堆栈中的CPSR弹出到CPU的cpsr寄存器

LDMFDsp!

{r0-r12,lr,pc};依次恢复该任务r0~r12,lr,pc,切换到该任务

;*****下面开始OSCtxSw函数,完成任务级的任务切换*****

EXPORTOSCtxSw

IMPORTOSPrioCur

IMPORTOSPrioHighRdy

IMPORTOSTCBCur

IMPORTOSTaskSwHook

IMPORTOSTCBHighRdy;该变量指向任务切换后即将运行的任务的OS_TCB

OSCtxSw

STMFDsp!

{lr};OSCtxSw是被调用的,lr的值就是调用前的PC值,入栈

STMFDsp!

{r0-r12,lr};将lr和其他寄存器入栈

MRSr4,cpsr;通过MRS指令将cpsr入栈

STMFDsp!

{r4};被挂起的当前任务的寄存器保存完毕,下面接着保存该

;任务的堆栈指针,以便下次恢复时,可以找到其堆栈指针,便可恢复其寄存器

LDRr4,=OSTCBCur;得到当前TCB块的地址,传给r4

LDRr5,[r4];将OSTCBCur中的值传给r5,注意OSTCBCur存的是指针

STRsp,[r5];将当前任务的sp传到OSTCBCur存的指针中去

;*****下面OSCtxSw准备恢复优先级更高的就绪任务,这部分可共用OSIntCtxSw的代码

 

*****

;*****OSIntCtxSw函数开始*****

EXPORTOSIntCtxSw

IMPORTOSTaskSwHook

OSIntCtxSw;准备任务切换

BLOSTaskSwHook;调用Hook函数,此为空函数

LDRr4,=OSTCBHighRdy

LDRr4,[r4];将高优先级的任务栈顶指针存到r4中

LDRr5,=OSTCBCur

STRr4,[r5];OSTCBCur=OSTCBHighRdy

LDRr6,=OSPrioHighRdy;取出高优先级

LDRBr6,[r6];优先级,字节传送

LDRr5,=OSPrioCur

STRBr6,[r5];OSPrioCur=OSPrioHighRdy

LDRsp,[r4];从r4中取得要恢复的任务的栈顶指针

LDMFDsp!

{r4};弹出任务栈中的第一个参数,即cpsr

MSRcpsr_cxsf,r4;首先开始恢复cpsr

LDMFDsp!

{r0-r12,lr,pc};依次恢复r0~r12,lr,pc,任务切换

;*****OSTickISR开始*****

EXPORTOSTickISR

IMPORTOSIntEnter

IMPORTOSTimeTick

IMPORTOSIntExit

LINK_SAVEDCD0;用来保存时钟节拍中断前的lr,以便计算出pc而使之入栈

PSR_SAVEDCD0;用来保存中断前的spsr,中断产生时,svc模式下的cpsr存到spsr

OSTickISR;时钟节拍中断服务程序入口,需要用户在主函数中安装

STMFDsp!

{r4};因为r4下面要使用,故先保存r4到irq模式的堆栈中

LDRr4,=LINK_SAVE;准备保存LR,SPSR,以便得到中断前的pc和cpsr_svc

STRlr,[r4];LINK_SAVE=lr_irq,此时lr=PC(中断发生前)+4

MRSlr,spsr;lr已保存,用lr取得spsr(保存的是中断前的cpsr)

STRlr,[r4,#4];PSR_SAVE=spsr_irq

LDMFDsp!

{r4};恢复r4

ORRlr,lr,#0x80;在上下文切换前,屏蔽irq中断。

注意lr存的是中断前的cpsr

MSRcpsr_cxsf,lr;中断产生前是svc模式,故必须要切换到此模式下保存现场

SUBsp,sp,#4;按任务栈结构,空一个空间预留给PC

STMFDsp!

{r0-r12,lr};依次保存lr、r12~r0

LDRr4,=LINK_SAVE;准备保存pc,取得存svc模式下发生中断前lr的地址

LDRlr,[r4,#0]

SUBlr,lr,#4;中断前的pc=LINK_SAVE-4,此前lr为异常前pc+4的值

STRlr,[sp,#(14*4)];保存pc到任务栈中预留的空间

LDRr4,[r4,#4];开始保存cpsr,r4=PSR_SAVE,即中断前的cpsr_svc

STMFDsp!

{r4};保存svc模式下任务的cpsr,寄存器保护完毕

LDRr4,=OSTCBCur;下面开始将该堆栈指针传给OSTCBCur所指向的指针

LDRr4,[r4];便于OSIntExit函数判断是否当前任务优先级最高

STRsp,[r4];在OSTCBCur->OSTCBstkptr保存被中断的任务的栈顶指针

BLOSIntEnter;异常前的上下文保存好之后,开始准备中断服务,将OSIntNesting++

BLOSTimeTick;将所有延时节拍不为1的任务的节拍数都减1,并清中断标志

BLOSIntExit;将OSIntNesting--,并判断是否有高优先级任务就绪,若有,

;则调用OSIntCtxSw()调度该任务并不再返回;若没有则返回到这里

LDMFDsp!

{r4};这里sp存的仍是调用OSIntEnter前的sp,即被中断的任务栈顶指针

MSRcpsr_cxsf,r4;从堆栈中恢复中断前任务的cpsr,注意此时irq才被重新允许

LDMFDsp!

{r0-r12,lr,pc};恢复中断前任务的r0-r12,lr和pc,返回被中断的任务

;******OSTickISR函数代码完成,下面是临界段代码前后开关中断的函数******

EXPORTARMDisableInt

ARMDisableInt

MRSr0,cpsr;由于任务和内核都运行在svc模式下,因此可方便地操作cpsr

STMFDsp!

{r0};保存当前的cpsr

ORRr0,r0,#0xc0;屏蔽FIQ,IRQ中断

MSRcpsr_c,r0;回写cpsr,只屏蔽IRQ中断

MOVpc,lr;返回

EXPORTARMEnableInt

ARMEnableInt;必须和ARMDisableInt成对使用

LDMFDsp!

{r0};弹出在ARMDisableInt中被保存的cpsr

MSRcpsr_c,r0;恢复关中断前的cpsr

MOVpc,lr;返回

END;汇编代码结束

;*****OS_CPU_A.S文件结束******

4小结

这里较详细地叙述了轻量级的实时内核µC/OS-II在ARM7处理器(S344B0X)的移植过程,并给出了简练而实用的代码,移植代码和移植思想对于µC/OS-II在其他ARM处理器上的移植具有较强的借鉴意义。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2