>
首页 » 技术文章 » μC/OS-Ⅱ在S3C44B0X处理器上的移植

μC/OS-Ⅱ在S3C44B0X处理器上的移植

作者:陆启帅,蒋兵华  时间:2006-10-28 23:45  来源:
摘 要:由于ARM处理器体系结构自身固有的硬件结构特点,使其对嵌入式实时操作系统(Real-Time Operating System)的运行提供了充分的硬件支持。文章简单地论述了如何将μC/OS-Ⅱ操作系统移植到ARM处理器中。

关键字:ARM处理器;μC/OS-Ⅱ操作系统;移植

引 言

嵌入式实时操作系统RTOS与通用操作系统相比较, 它具有实时性、可裁减、低资源占用等特点。而与传统的嵌入式设计方法相比, 实时多任务内核的运用允许程序员将具体的应用程序模块化, 更易于项目的开发。

μC/OS-Ⅱ的简介

目前市场上的商用嵌入式操作系统, 如Vxwork、PSOS和WindowSCE等已经十分成熟, 提供有力的开发和调试工具, 但开发成本昂贵, 实时嵌入式操作系统uCOS-II是基于优先级的抢占式实时多任务操作系统, 包含了实时内核、任务管理、时间管理、任务间通信同步(信号量, 邮箱, 消息队列)和内存管理等功能。绝大部分代码用C语言写成, 与硬件相关部分用汇编语言编写, 而且它的源代码是公开免费的。

μC/OS-Ⅱ是面向中小型嵌入式系统的。包含全部功能模块的内核大约为10KB, 如果经过裁减只保留核心代码, 则可压缩到3KB左右。RAM的应用量与系统中的任务数有关, 任务的堆栈要占用大量的RAM空间, 堆栈的大小取决于任务的局部变量、缓冲区大小及可能的中断嵌套层数。应用程序的精度由系统的时钟节拍决定, μC/OS-Ⅱ要用户提供周期性的时钟信号源, 用于实现时间延时和确认超时。

μC/OS-Ⅱ的工作原理如下: 首先把CPU初始化, 再进行操作系统初始化。主要完成任务控制块(TCB)初始化、TCB优先级表初始化、TCB链表初始化、事件控制块ECB链表初始化和空任务的创建等; 然后开始创建新任务, 并可在新创建的任务中再创建其它的新任务; 最后调用OSSTART()函数启动多任务调度。在多任务调度开始后, 启动时钟节拍源开始计时, 此节拍源给系统提供周期性的时钟中断信号, 实现延时和超时确认。当时钟中断来临时, 系统把正在执行的任务挂起, 保护现场, 进行中断处理, 判断有无任务延时到期, 若有则使该任务进入就绪态, 并把所有进入就绪态的任务的优先级进行比较, 通过任务切换去执行最高优先级的任务。若没有别的任务进入就绪态, 则恢复现场继续执行原任务。另一种的调度方式是任务级的调度, 是通过发软中断命令或依靠处理器在任务执行中调度。如任务要等待信号量或一个正在执行的任务被悬挂起来时, 就需要在此任务中调度, 找出目前处于就绪态的优先级最高的任务去执行。当没有任何任务进入就绪态时, 就去执行新任务。

μC/OS-Ⅱ的移植

本文是以三星公司的S3C44B0X微处理器作为基础, 在S3C44B0X微处理器上实现移植。S3C44B0X是ARMCPU嵌入式控制器总线结构, 特别适用于低成本、低功耗的应用。其CPU采用ARM公司的ARM7TDMIRISC结构。ARM7TDMI系统扩充包括thumB协处理器和32位乘法器等。

要实现μC/OS-Ⅱ的移植, 最关键的就是要修改与处理器类型有关部分的代码, 也就是进行以下几项工作:
(1)修改OS_CPU.H文件
(2)修改OS_CPU_C.C文件
(3)修改OS_CPU_A.ASM文件

OS_CPU.H文件
OS_CPU.H文件包括了用#definE语句定义的、与处理器相关的常数、宏以及类型。

数据类型
定义ARM中的数据类型

#definEunsigned charBOOLEAN;
#definEunsigned charINT8U; /*8位无符号整数*/
#definEsigned charINT8S; /*8位有符号整数*/
#definEunsigned inTINT16U; /*16位无符号整数*/
#definEsigned inTINT16S; /*16位有符号整数*/
#definEunsigned long INT32U; /*32位无符号整数*/
#definEsigned long INT32S; /*32位有符号整数*/
#definEfloaTFP32; /*单精度浮点数*/
#definEdoublEFP64; /*双精度浮点数*/
typedef unsigned inTOS_STK; /*堆栈入口宽度为16位*/

代码临界区
RTOS在进入系统临界区前必须关闭中断, 退出临界区后再开中断。μC/OS-Ⅱ定义了两个宏来开关中断: OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。为实现开关中断, 宏定义为:


栈增长方向
在μC/OS-Ⅱ中, 用OS_STK_GROWTH来设置堆栈的增长方向, OS_STK_GROWTH为0表示堆栈从低地址向高地址增长;OS_STK_GROWTH为1表示堆栈从高地址向低地址增长, 其宏定义为:

#definEOS_STK_GROWTH1;/*堆栈从高地址向低地址增长*/
#definEOS_STK_GROWTH0; /*堆栈从低地址向高地址增长*/

OS_CPU_C.C文件
在此文件中, 要求我们必须编写10个简单的C函数, 唯一必要的函数是OsTaskStkInt()函数。其他9个函数必须声明, 但可以不包含任何代码。OsTaskStkInt()由任务创建函数OSTaskCreate()或OSTaskCreateEXT()调用, 用来初始化任务的堆栈。

Void OSTaskStkInT(void (*task)(void *pd),void *pdata,void *ptos, INT16Uopt)
{unsigned inT*stk;
stk=(unsigned int*)ptos; /*装载堆栈指针*/
*--stk=(unsigned int)task; /*pc*/
*--stk=(unsigned int)task; /*lr*/
*--stk=0; /*r1-r12*/
*--stk=(unsigned int)pdata; /*r0*/
*--stk=(SVC32MODE/0x0); /*cpsrIRQ,关闭FIQ*/
*--stk=(SVC32MODE/0x0); /*spsrIRQ,关闭FIQ*/
return ((void*)stk);}
void OStaskCreateHook ()
void OStaskDelHook ()
void OStaskSwHook ()
void OStaskStatHook ()
void OSTimeTickHook ()
void OStaskIdleHook ()
void OStaskHookBegin ()
void OStaskHookend ()

OS_CPU_A.ASM文件
在此文件中需改写4个简单汇编语言函数:OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()和OSTickISR()。

OSStartHighRdy()函数
该函数由Osstart()函数调用, 功能是运行优先级最高的就绪任务, 代码为:

LDRr4,addr_OSTCBCur; /*得到当前任务的TCB地址*/
LDRr5,addr_OSTCBHighRdy; /*得到高优先级任务的TCB地址*/
LDRr5,[r5]; /*得到堆栈指针*/
LDRsp,[r5]; /*切换到新的堆栈*/
STRr5,[r4]; /*设置新的当前任务的TCB地址*/
LDMFD sp! , {r4}; /*从栈顶得到新的声明*/
LDMFD sp! , {r0-r12,lr,pc}; /*恢复任务环境*/
RETI; /*中断返回, 开始新的任务*/

OSCtxSw()函数
OSCtxSw()函数是一个任务级的任务切换函数。软中断向量指向此函数。在μC/OS-Ⅱ中, 如果任务调用了某个函数, 而该函数的执行结果可能造成系统任务的重新调度, 则在函数的末尾会调用OSSched(),OSSched()查找当前就绪最高优先级的任务, 如果不是当前任务, 则找该任务的TCB地址, 并复制到变量OSTcbHigh-Rdy()中, 然后通过宏OS_TASK_SW()执行软中断调用OSCtxSw()进行任务切换。变量OSTCBCur始终包含指向当前运行任务TCB的指针, 代码如下:

STMFD sp! ,{lr}; /*保存PC指针*/
STMFD sp! ,{r0-r12}; /*保存寄存器文件和RET地址*/
STMFD sp! ,{r4}; /*保存当前PSR*/
LDRr4,addr_OSTCBCur; /*得到当前任务的TCB地址*/
STRsp,[r5]; /*保存栈指针在占先任务的TCB上*/
LDRr6,addr_OSTCBHighRdy;/*取得高优先级任务的TCB地址*/
LDRsp,[r6]; /*得到新任务的堆栈指针*/
LDMFD sp!,{r4} ; /*设置当前新任务的TCB地址*/

OSIntCtxSw()函数
OSIntCtxSw()函数进行中断级任务切换。中断可能引起任务切换, 在中断服务程序的最后会调用OSIntExit()函数检查任务就绪状态, 如果需要任务切换则调用OSIntCtxSw()函数。其代码如下:

LDMIA sp! ,{a1-v1,lr}
SUBSpc,lr,#4
MOV r12,lr
MRSlr,SPSR
AND lr,lr,#0xFFFFFFE0
MSRCPSR_cxsf,lr

OSTickISR()函数
OSTickISR()是中断处理函数, 其主要任务是处理时钟中断,调用系统实现的OSTimeTick()函数, 如果有等待时钟信号的高优先级任务, 则需要在中断级别上调度执行。其代码如下:

ORRr0,r0,#0x80; /*设置中断禁止标志*/
MSRCPSR_cxsf,r0; /*中断结束*/
LDRr0,=I_ISPC
LDRr1,=BIT_TIMER0
LDREQ pc,=_CON_SW

结束语

嵌入式实时操作系统RTOS的使用使得应用程序的设计过程大为简化。并且程序的可读性、可靠性、可扩展性有很大的改善。本文从实际出发, 论述了μC/OS-II操作系统在ARM处理器移植。经过移植后的操作系统经过测试, 运行稳定, 并达到了实时系统的要求。

相关推荐

市场紧俏 三星决定自主研发ARM处理器

三星  ARM处理器  2013-08-02

运营商搅局手机OS市场:储备核心技术

智能手机  OS  2013-07-10

诺基亚CEO:推行双OS战略 高端继续专注于WP

诺基亚  OS  2013-02-26

黄仁勋:明年NVIDIA世界首发64bit ARM处理器

NVIDIA  ARM处理器  2012-01-17

新思使创意电子ARM处理器频率达到1GHz

新思  ARM处理器  2011-12-15

惠普正式分拆webOS全球事业部 保留硬件部门

惠普  OS  2011-09-07
在线研讨会
焦点