ucos-II在ARM7上的移植

发布时间 : 星期五 文章ucos-II在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.1 OS_CPU.h的移植

该文件定义了和处理器及编译器相关的定义及一些全局函数声明。由于ARM7 处理器字长为32位,半字长为16位,字节为8位,因此在OS_CPU.h文件修改与编译器相关的定义如下: typedef unsigned char BOOLEAN; typedef unsigned char INT8U; typedef signed char INT8S;

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

typedef signed short INT16S; typedef unsigned long INT32U; typedef signed long INT32S; typedef float FP32; typedef double FP64;

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

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

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

#define OS_ENTER_CRITICAL() ARMDisableInt() /*临界段代码保护宏定义*/ #define OS_EXIT_CRITICAL() ARMEnableInt()

#define OS_STK_GROWTH 1 /*定义堆栈生长方向为向下生长 */ #define OS_TASK_SW OSCtxSw /*宏定义,用于非中断级的任务切换*/

/*下面开始声明全局函数声明,均是OS_CPU_A.S中需要编写的函数*/ extern void OSCtxSw(void); /*声明任务级任务切换函数*/ extern void OSIntCtxSw(void); /*声明中断级任务切换函数*/ extern void ARMDisableInt(void); /*声明中断禁止函数*/ extern void ARMEnableInt(void); /*声明中断恢复函数*/ extern void OSTickISR(void); /*声明时钟中断服务函数*/

2.2 OS_CPU_C.C文件

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

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

点,设计任务堆栈如下任务堆栈的结构: CPSR R0 R1 …… R12 LR(R14) PC(R15)

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

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

OS_STK * OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) {

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中断作为时钟节拍中断,该函数编写如下:

void OSTimeTickHook(void) {

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

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

另外几个hook函数不必去改它们。至此,OS_CPU.C编写完成。

联系合同范文客服:xxxxx#qq.com(#替换为@)