Chinaunix首页 | 论坛 | 博客
  • 博客访问: 973908
  • 博文数量: 238
  • 博客积分: 2842
  • 博客等级: 少校
  • 技术积分: 2765
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-16 00:20
个人简介

stdlf

文章分类

全部博文(238)

文章存档

2013年(6)

2012年(13)

2011年(82)

2010年(89)

2009年(48)

我的朋友

分类: 嵌入式

2010-01-23 22:07:54

在ARM工程开发中,为了实现功能复杂的资源复用,提高软件功能设计效率,简化开发难度,需要采用高性能的实时嵌入式操作系统mC/OS-II作为软件设计平台。因此,将mC/OS-II移植到ARM开发平台是一项难度极高但十分必要的工作。通常移植工作对开发人员有非常高的要求,开发人员不仅要熟练掌握嵌入式系统的开发模式和方法,而且还要对操作系统、处理器和硬件系统的特性有深入的认识和研究。mC/OS-II移植工作已由作者独立完成,在实际应用后,证明mC/OS-II工作十分稳定。
移植的硬件平台采用高性能ARM7TDMI内核的AT91m40800嵌入式处理器,开发调试平台采用ARM SDT2.51,软件平台采用实时嵌入式操作系统mC/OS-II。

mC/OS-II实时操作系统的结构及可移植性分析
mC/OS-II操作系统特点
mC/OS-II是一个高性能的嵌入式实时操作系统,是由多任务、多中断和高效实时内核组成的一个有机整体。应用系统在实时内核的统一管理下协调工作,能够高效地实现任务切换、任务调度、任务间通信、同步、互斥、实时时钟管理、中断管理等功能。
为了提高系统的实时能力,mC/OS-II可以将一个复杂的应用划分为多个相互独立的任务,并根据任务的重要性来分配优先级。每个任务拥有自己的堆栈空间,并且当前任务运行时独占CPU资源。任务的调度完全由mC/OS-II的实时内核完成,主要包括任务的状态管理、选择最高优先权的任务、执行任务和撤消任务等。mC/OS-II内核还负责CPU时间分配,CPU时间总是优先分配给中断事件,其次是任务队列中当前优先级最高的任务。不同任务间的通信可以通过mC/OS-II提供的信号量、邮箱、消息队列等机制完成。
作为一个优秀的实时操作系统,mC/OS-II具有如下优点:
?可移植—绝大部分的mC/OS-II代码由ANSI C编写,只有和处理器相关的部分才使用汇编,这使得mC/OS-II便于移植;
?可裁减—如果只使用部分功能,可以通过条件编译来裁减mC/OS-II的代码;
?多任务—mC/OS-II可以管理64个任务,目前系统保留了8个,用户的应用程序最多可以有56个任务。每个任务的优先级不同,这意味着mC/OS-II不支持时间片轮转调度法;
?占先式—mC/OS-II是占先式的实时内核,它总是运行就绪条件下优先级最高的任务;
?可确定性—mC/OS-II的全部函数调用与服务的时间是可知的,mC/OS-II系统服务的时间不依赖于应用程序任务的多少;
?任务栈—每个任务有自己单独的堆栈;
?系统服务—mC/OS-II提供邮箱、消息队列、信号量、块大小固定的内存申请与释放、时间相关函数等;
?中断管理— 中断可以使正在执行的任务挂起,可能会在中断结束的时候发生任务切换,中断嵌套层数可达255层;
?稳定性与可靠性—mC/OS -II和mC/OS自1992年以来已经有几百个商业应用;
?公开源代码—使得系统在商业应用中具有明显的价格优势。
mC/OS-II的硬件和软件体系结构及可移植性分析
图1说明了mC/OS-II的结构及其与硬件的关系。
由图1可以看出,mC/OS-II的移植的主要工作是修改与处理器相关部分的代码,它们集中在三个文件中。其中,OS_CPU.H包含与处理器相关的常量、宏和结构体的定义;OS_CPU_C.C和 OS_CPU_ASM中定义了用于底层的任务切换,退出中断服务程序,在CPU级屏蔽中断、打开中断,对任务栈初始化以及时钟的中断服务程序的函数。
为了使应用程序运行于mC/OS-II上,还要相应地修改应用中使用的硬件设备驱动。
要使mC/OS-II正常运行,处理器必须满足以下要求:
1. 处理器的C编译器能够产生可重入代码。
2. 用C语言就可以打开和关闭中断。
3. 处理器支持中断,且能产生定时中断(通常在10~100Hz之间)。
4. 处理器支撑能够容纳一定容量数据(可能是几千字节)的硬件堆栈。
5. 处理器有将堆栈指针和其他CPU寄存器读出,并存储到堆栈或内存中的指令。
ARM7处理器及开发环境ARM SDT2.51所使用的编译器armcc可以满足上述要求。但是根据对mC/OS-II工作原理的分析,上述第3点并不是运行mC/OS-II所必需的。如果应用中不需要定时器,就没有必要在系统中加入时钟节拍功能。在某些系统中没有使用时钟节拍,应用中任务的切换完全依靠任务间的消息机制来完成,这大大提高了系统的实时性。上述要求是能够移植mC/OS-II全部代码的条件。
下面将结合mC/OS-II中与操作系统有关部分的功能分析、ARM7处理器体系结构说明mC/OS-II向ARM SDT开发环境的移植。

mC/OS-II向ARM SDT2.51开发环境的移植
将mC/OS-II向ARM移植,需要修改与处理器相关的数据类型和函数。修改数据类型的声明,需要对ARM处理器的字长及开发平台编译器使用的数据类型进行综合分析。修改与处理器相关的函数,需要对ARM处理器体系结构,ARM汇编程序的编写,操作系统在任务或中断切换时对被中断的任务的现场保护和恢复机制进行综合分析。下文将结合ARM处理器说明数据类型及相关函数的修改。
数据类型及宏的声明
移植中对OS_CPU.H的修改主要是,改变了与处理器有关的数据类型和宏定义。
由于不同处理器有不同字长,mC/OS-II的移植需要重新定义一系列的数据类型。使用armcc编译器,Char类型长度8位,Short类型长度16位,Int和Long类型长度32位。ARM寄存器都是32位的,所以将堆栈数据类型OS_STK声明为32位。所有的堆栈都必须使用OS_STK声明。
在该文件中,还将开关中断的宏OS_ENTER_CRITICAL和OS_EXIT_CRITCAL定义为OS_CPU_ASM.S中的函数ARMDisableINT和ARMEnableINT。
mC/OS-II任务堆栈及任务切换
ARM处理器模式及寄存器
ARM处理器共有7种运行模式,如表1所示。
mC/OS-II作为操作系统可以工作在sys模式和svc模式下。
ARM处理器共有31个通用寄存器(包括程序计数器PC)和6个状态寄存器(PSR),具体组成为:
?未备份寄存器R0~R7。在所有的处理器模式下指的都是同一个物理寄存器。
?备份寄存器R8~R12。每个寄存器对应两个不同的物理寄存器。
?R13和R4,每个寄存器对应6个不同的物理地址,usr模式和sys模式公用一个物理寄存器,其余每个模式有各自的R13和R14。寄存器R13常用做栈指针(sp),R14存放函数或异常模式的返回地址。
?程序计数器R15。
?当前程序状态寄存器(CPSR)和5个备份程序状态寄存器(SPSR)。
mC/OS-II任务堆栈
mC/OS-II为每个任务建立堆栈,用于保存处理器的寄存器。其结构体定义为OS_STK[16],保存处理器工作模式(svc模式)的R0~R12、R14、CPSR和SPSR。
mC/OS-II在OS_CPU_C.C中由任务堆栈初始化函数OSTaskStkInit,需要将任务栈内的CPSR和SPSR设为svc模式。
mC/OS-II的任务切换
mC/OS-II的任务调度函数OSShed()获得当前就绪的优先级最高任务的TCB(任务控制块)指针,存入全局变量OSTCBHighRdy,将当前任务的TCB指针存入OSTCBCur。然后调用函数OS_TASK_SW()进行最底层的任务切换。
OS_CPU_ASM.S内的任务切换函数OS_TASK_SW()完成的工作有两步:将被挂起任务的微处理器寄存器推入任务堆栈(OSTCBCur->OSTCBSTK),然后将较高优先级的任务的寄存器从栈(OSTCBHighRdy->OSTCBSTK)恢复到寄存器。
屏蔽中断与开中断
PSR寄存器格式说明
程序寄存器构造如下:
位 31 30 29 28 27-----
N Z C V
-----7 6 5 4 3 2 1 0
I F T 工作模式
I位为1屏蔽处理器的外部中断,为0允许外部中断。
F位为1屏蔽处理器的快速中断,为0允许快速中断。
屏蔽中断与开中断
OS_CPU_ASM.S中的屏蔽中断函数ArmDisableInt()将CPSR的I位置1实现在处理器级将中断屏蔽;开中断函数ArmEnableInt()将CPSR的I位置0允许处理器响应中断。
进入中断程序和中断返回程序
ARM处理器的中断处理程序
处理器响应IRQ异常中断时的处理过程是,在irq模式的R14保存程序返回的地址;在irq模式的SPSR保存CPSR;切换到irq模式,将CPSR中断位(I位)置1,跳转到中断向量的地址。
mC/OS-II的中断服务程序
在OS_CPU_ASM.S中的时钟中断服务程序OSTickISR是标准的中断服务程序,函数的入口写入AIC的中断向量表,其实现的过程是:向m40800的AIC_IVR写入任意的数,读取m40800的状态寄存器清除中断,保护CPU寄存器入栈,调用OSIntEnter对中断嵌套标志加1。调用中断服务程序OSTimeTick,调用OSIntExit判断是否需要任务切换,如果需要会调用OSIntCtxSW来进行任务切换。此处没有调用任务切换函数OS_TASK_SW()是因为CPU寄存器入栈的工作已经在进入中断时完成。
OSIntCtxSW是OS_CPU_ASM内的函数,完成的工作如下:向m40800的AIC_EOICR寄存器写入值,将IRQ栈内保存的中断CPU寄存器的值写入被中断的任务栈,将就绪的高优先级的任务栈内容写入对应的CPU寄存器。
OSTickISR是标准的中断服务程序,其他设备的中断服务程序可以仿照这一程序的结构编写,只是对应的设备寄存器地址不同。
测试mC/OS-II内核
基于上述分析,对与处理器有关的4个汇编函数(ArmIntEnter,ArmIntExit,OSIntCtxSw,OS_Task_Sw),一个C函数(OSTaskStkInit)及相关的数据类型和宏定义进行分析修改就是mC/OS-II移植需要做的工作。
一旦代码移植结束,下一步工作就是测试。测试一个mC/OS-II的多任务实时内核需要细致地考虑测试步骤。调试的过程应该由简到繁,可以从一些最简单的任务,甚至在没有应用程序的情况下开始测试。这样做有两个好处:第一,避免使原本复杂的事情更加复杂;第二,如果出现问题,可以知道问题出现在内核代码上而不是应用程序。刚开始的时候,可以添加一些简单的任务和时钟节拍的中断服务例程。一旦多任务调度成功运行了,再添加应用程序就非常简单了。
在实际测试中,按照由简到繁的过程不断使测试变得复杂,如下所述:
1. 添加三个任务,每个任务通过m40800的一个PIO口控制一个LED,在三个任务间互抛信号量。测试mC/OS-II系统内任务调度,任务间通信机制是否工作正确;测试移植的任务栈结构和任务切换函数OS_Task_SW是否正确(见图2)。
2. 在上一步的基础上,打开时钟中断,但没有任务调用OSTimeDly等与时钟中断有关的操作。在时钟中断的OSTimeTickHook中通过一个PIO控制一个LED的亮灭。测试时钟中断的中断服务程序OSTimeTickISR和中断后没有任务切换的情况系统运行是否正确(见图3)。
3. 在上一步的基础上,三个基本任务中的延时使用OSTimeDly实现,即在时钟中断的中断服务程序完成后需要任务切换。测试移植的OSIntCtxSW是否正确(见图4)。
4. 在上一步的基础上,加入第四个任务Task4和串口收数中断,在中断服务程序中将收到字节放入邮箱,在Task4等待邮箱,被唤醒后从串口发出收到的字节。这种情况接近一般工程设计的应用情况(见图5)。

mC/OS-II向其他基于ARM7内核芯片的移植
以上所述的移植工作大部分针对ARM7内核,但其中涉及到中断控制器及时钟控制器的代码是针对Atmel公司的AT91m40800芯片的专用外设编写的,在向其他基于ARM7内核的芯片移植mC/OS-II时,只需修改相关外设的驱动程序或系统中OS_CPU文件的相关代码即可。在使用中,还完成了将mC/OS-II向三星公司的S3C44B0芯片移植的工作。

阅读(699) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~