Chinaunix首页 | 论坛 | 博客
  • 博客访问: 120936
  • 博文数量: 26
  • 博客积分: 2000
  • 博客等级: 大尉
  • 技术积分: 335
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-26 22:27
文章分类

全部博文(26)

文章存档

2011年(1)

2009年(25)

我的朋友

分类:

2009-04-27 11:08:27

1、uC/OS-II介绍
      uC/OS-II(Micro Control Operation System Two)是一个可以基于ROM运行的、可裁减的、抢占式(见图1)实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和很多商业操作系统性能相当的实时操作系统(RTOS)。为了提供最好的移植性能,uC/OS-II最大程度上使用ANSI C语言进行开发,并且已经移植到近40多种处理器体系上,涵盖了从8位到64位各种CPU(包括DSP)。

      uC/OS-II可以简单的视为一个多任务调度器,在这个任务调度器之上完善并添加了和多任务操作系统相关的系统服务,如信号量、邮箱等。其主要特点有公开源代码,代码结构清晰、明了,注释详尽,组织有条理,可移植性好,可裁剪,可固化。内核属于抢占式,最多可以管理60个任务。从1992年开始,由于高度可靠性、鲁棒性和安全性,uC/OS-II已经广泛使用在从照相机到航空电子产品的各种应用中。

2、uC/OS-II在S3C2410上的可移植性
      所谓移植,就是使这个实时内核能在某个微处理器上运行。为了方便移植,大部分的uC/OS-II代码是用c语言写的,但仍需要用c和汇编语言写一些与处理器相关的代码,这是因为uC/OS-II在读写处理器寄存器时只能通过汇编语言来实现。由于uC/OS-II在设计时就已经充分考虑了可移植性,所以uC/OS-II的移植相对来说是比较容易的。
     
uC/OS-II的源代码具体包括以下的文件:
      a)PC.C、PC.H:源文件PC.H包含了对函数和环境的一些定义。
      b)OS_CORE.C、S_FLAG.C、OS_MBOX.C、OS_MEM.C、OS_MUTEX.C、OS_Q.C、OS_SEM.C、OS_TASK.C、OS_TIME.C、uCOS-II.C、uCOS-II.H:这些文件是uC/OS-II中所有与处理器类型无关部分的源代码。
      c)OS_CPU_A.S、OS_CPU_C.C、OS_CPU.H:这些文件是与处理器类型相关部分的源代码,在本实验系统中是面向80x86 处理器的。
      d)INCLUDES.H:给整个内核库提供了总体的include 文件。
      e)OS_CFG.H:uC/OS-II 的配置文件,定义使用uC/OS-II 中的哪些功能。
     
uC/OS-II的框架结构如图2。

      uC/OS-II的正常运行需要处理器平台满足以下要求:
      a)处理器的C编译器能产生可重入代码。
      b)用C语言就可以打开和关闭中断。
      c)处理器支持中断,并且能产生定时中断(通常在10至100Hz之间)。
      d)处理器支持能够容纳一定量数据(可能是几千字节)的硬件堆栈。
      e)处理器有将堆栈指针和其它CPU寄存器读出和存储到堆栈或内存中的指令。
      S3C2410处理器采用ARM920T内核,内部共有37个寄存器,其中R13通常用作堆栈指针,只要系统RAM空间允许,堆栈空间理论上没有限制。ARM处理器提供arm指令和Thumb指令两种指令集,每种指令集都包含有丰富的指令对堆栈进行操作,可以随意的对处理器中的寄存器进行堆栈操作。根据堆栈生长方向的不同,可以生成4种不同的堆栈,分别是满递增、空递增、满递减(此移植中使用的是满递减方式)、空递减。芯片内集成5个定时时钟,任何一个都可以产生定时中断,满足第三条要求。ADS集成开发环境的内置编译器可以产生可重入代码,并且支持内嵌汇编,C环境中可任意的进行开关中断操作。综上所述,
uC/OS-II完全可以移植到S3C2410上运行。

3、主体移植过程

3.1、设置与处理器及编译器相关的代码[OS_CPU.H]
      不同的编译器会使用不同的字节长度来表示同一数据类型,所以要定义一系列数据类型以确保移植的正确性。下面是uC/OS-II定义的一部分数据类型。
      typedef unsigned char BOOLEAN;
      typedef unsigned char INT8U; /* 无符号8位 */
      typedef signed char INT16S; /* 带符号8位 */
      typedef unsigned int INT16U; /* 无符号16位 */
      typedef signed int INT16S; /* 带符号16位 */
      typedef unsigned long INT32U; /* 无符号32位数 */
      typedef signed long INT32S; /* 带符号32位数 */
      typedef float FP32; /* 单精度浮点数 */
      typedef double FP64; /* 双精度浮点数 */
      typedef unsigned int OS_STK; /* 堆栈入口宽度 */
      typedef unsigned int OS_CPU_SR; /* 寄存器宽度 */
      uC/OS-II需要先关中断再访问临界区的代码,并且在访问完后重新允许中断。uC/OS-II定义了两个宏来禁止和允许中断:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL(),本移植实现这两个宏的汇编代码。
      /* Disable interrupts */
      #define OS_ENTER_CRITICAL() (cpu_sr=OSCPUSaveSR())
      /* Enable interrupts */
      #define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr))

      EXPORT OSCPUSaveSR
      OSCPUSaveSR
            mrs r1,cpsr
            mov r0,r1
            orr r1,r1,#0xc0
            msr cpsr_cxsf,r1
            mov pc,lr
      EXPORT OSCPURestoreSR
      OSCPURestoreSR
            msr cpsr_cxsf,r0
            mov pc,lr

3.2、用C语言实现与处理器任务相关的函数[OS_CPU_C.C]
      OSTaskStkInit()
      OSTaskCreateHook()
      OSTaskDelHook()
      OSTaskSwHook()
      OSTaskStatHook()
      OSTimeTickHook()
      实际需要修改的只有OSTaskStkInit()函数,其他五个函数需要声明,但不一定有实际内容。这五个函数都是用户定义的,所以OS_CPU_C.C中没有给出代码。如果需要使用这些函数,可以将文件OS_CFG.H中的#define OS_CPU_HOOKS_EN的值设为1,设为0表示不使用这些函数。
      OSTaskStkInit()函数由OSTaskCreate()或OSTaskCreateExt()调用,需要传递的参数是任务代码的起始地址、参数指针(pdata)、任务堆栈顶端的地址和任务的优先级,用来初始化任务的堆栈,初始状态的堆栈模拟发生一次中断后的堆栈结构。堆栈初始化工作结束后,OSTaskStkInit()返回新的堆栈栈顶指针,OSTaskCreate()或OSTaskCreateExt()将指针保存在任务的OS_TCB中。调用OSTaskStkInit()给任务做一个初始的任务上下文堆栈,形状如图3。

3.3、处理器相关部分汇编实现
      整个uC/OS-II移植实现中,只需要提供一个汇编语言文件,提供几个必须由汇编才能实现的函数。
      a)OSStartHighRdy()
      该函数在OSStart()多任务启动之后,负责从最高优先级任务的TCB控制块中获得该任务的堆栈指针sp,通过sp依次将CPU现场恢复,此时系统就将控制权交给用户创建的该任务的进程,直到该任务被阻塞或者被其他更高优先级的任务抢占了CPU。该函数仅仅在多任务启动时被执行一次,用来启动第一个,也就是最高优先级的任务执行。
      b)OSCtxSw()
      该函数是任务级的上下文切换函数,在任务因为被阻塞而主动请求与CPU调度时执行,主要工作是先将当前任务的CPU现场保存到该任务堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中恢复此任务的CPU现场,使之继续执行,从而完成一次任务切换。
      c)OSIntExit()
      该函数是中断级的任务切换函数,在时钟中断ISR中发现有高优先级任务在等待时,需要在中断退出后不返回被中断的任务,而是直接调度就绪的高优先级任务执行。其目的在于能
够尽快让高优先级的任务得到响应,保证系统的实时性能。
      d)OSTickISR()
      该函数是时钟中断处理函数,主要任务是负责处理时钟中断,调用系统实现的OSTimeTick函数,如果有等待时钟信号的高优先级任务,则需要在中断级别上调度其执行。另外两个相关函数是OSIntEnter()和OSIntExit(),都需要在ISR中执行。

4、测试
      至此代码移植过程已经完成,下一步工作就是测试。测试一个象uC/OS-II一样的多任务实时内核并不复杂,甚至可以在没有应用程序的情况下测试。换句话说,就是让这个实时内核在目标板上跑起来,让内核自己测试自己。这样做有两个好处:第一,避免使本来就复杂的事情更加复杂;第二,如果出现问题,可以知道问题出在内核代码上而不是应用程序。刚开始的时候可以运行一些简单的任务和时钟节拍中断服务例程。一旦多任务调度成功地运行了,再添加应用程序的任务就是非常简单的工作了。

5、结束语
      采用基于arm9的S3C2410嵌入式微处理器,可以使系统具备高性能的运算能力的同时便于与各种外设连接扩展,简化了硬件设计,维持小型化的同时降低了系统成本。uC/OS-II作为一个源代码公开的操作系统,在具体应用中稳定可靠,并且支持uIP、TCP/IP协议栈、ucGUI等,可扩展性强,功能强大。本系统采arm9+uC/OS-II开发设计,具有精度高、运行稳定、实时性好、抗干扰能力强、性价比高的特点,可以在各种工业场合中广泛应用,达到了设计的初衷。

 

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