摘 要:实时嵌入式操作系统的应用日益广泛,本论文将DSP技术与嵌入式操作系统结合起来,分析探讨了面向DSP内核的嵌入式实时操作系统的设计,重点研究了嵌入式操作系统对DSP处理器内核的移植,分析探讨了移植的前提条件及修改问题,对于进一步提高面向DSP技术的嵌入式操作系统的研究应用具有一定借鉴意义。
关键词:DSP设计;嵌入式系统;实时操作系统;内核移植
1 引言
嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可剪裁,适应应用系统对功能、可靠性、成本、体积、功耗等综合性严格要求的专用性系统,嵌入式系统的核心是嵌入式操作系统,嵌入式操作系统可以统称为应用在嵌入式系统的操作系统,它具有一般操作系统的功能,同时具有嵌入式软件的特点。本论文将采用DSP设计技术对嵌入式操作系统进行设计,主要方法是将目前常用的实时嵌入式操作系统移植到具有嵌入式操作系统内核的DSP处理器上,以期从中找到能够可供借鉴或指导的有效的实时嵌入式操作系统的设计方法,并和广大同行分享。
2 嵌入式处理器内核的分析
2.1 嵌入式操作系统选择
μC/OS-II是源代码公开的嵌入式实时内核,提供多任务调度与管理、时间管理、任务间同步与通信、内存管理及中断服务等功能。自1992年诞生以来,μC/OS-II己经被广泛地应用于各种嵌入式系统。
2.2 DSP嵌入式处理器内核分析
要开发基于DSP的嵌入式实时操作系统,选择合适的嵌入式DSP芯片至关重要。本文选用了S3C44B0X嵌入式处理器。本实验是在英培特公司推出的Embest EDUKIT-III型开发板上进行的。Embest EDUKIT-III型开发板是一款基于Samsung公司的S3C44BOX处理器(ARM7TDMI)的全功能ARM开发板。硬件系统包含了嵌入式系统开发应用所需的大部分设备,如串口、以太网口、USB口、音频输出、LCD及TSP触摸屏、5*4的小键盘、固态硬盘、大容量的Flash和SORAM等等。
S3C44B0X是16/32位的RISC(Reduced Instruction Set Computer)处理器。它为手持设备和一般类型应用提供了高性价比和高性能的微控制器解决方案。为了降低成本,S3C44BOX提供了丰富的内置部件,包括:8KB cache,内部SRAM,LCD控制器,带自动握手的2通道UART,4通道DMA,系统管理器,代用PWM功能的5通道定制器,FO端口,RTC,8通道10位ADC,IIC-BUS接口,IIS-BUS接口,同步SIO接口和PLL倍频器。S3C44B0X采用的是ARM7TDMI内核。
3 嵌入式实时操作系统的移植
3.1 移植的前提条件分析
要使μC/OS-II正常运行,处理器必须满足以下要求:
(1) 处理器的C编译器能产生可重入代码。
(2) 用C语言就可以打开和关闭中断。
(3) 处理器支持中断,并且能产生定时中断(通常在10至100Hz之间)。
(4) 处理器支持能够容纳一定量数据(可能是几千字节)的硬件堆栈。
(5) 处理器有将堆栈指针和其它CPU寄存器读出和存储到堆栈或内存中的指令。
3.2 μC/OS-II中需要修改的代码
由于μC/OS-II为开源软件,我们可以很轻松的获得其初始源代码。然后根据移植的需要进行修改和移植。
(1) OS_CPU.H中需要针对具体处理器的字长重新定义一系列数据类型。
μC/OS-II自己定义了一套数据类型,如INT16U表示16位无符号整型,对于ARM这样的32位内核,INT16U是unsigned short型,如果是16位的处理器,则是unsigned int型。
(2) OS_CPU.H中需要声明几个用于开关中断和任务切换的宏。
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL():这两个宏用来禁止和允许中断。OS_TASK_SW():这个宏是μC/OS-II从低优先级任务切换到高优先级任务时的调用。与别的实时内核一样,μC/OS-II也需要在来访问临界段代码之前关中断,完成后再开中断。实际上开/关中断的方式有三种。第一种是OS_CRITICAL_METHOD=1的情况,这种方法非常的简单,就是直接使用处理器指令CLI来关中断,STI来开中断。第二中方法是OS_CRITICAL_ METHOD=2的情况,这种方法时将元中断状态保存到堆栈中然后关中断,在开中断之前再处理器寄存器原来的内容进行恢复。第三种方法是OS_CRITICAL_METH OD=3的情况,这种方法是写一个函数将CPU的状态寄存器保存到局部变量中,OS_EXIT_CRITICAL()通过调用另一个函数,从这个局部变量中恢复寄存器,我们使用的这两个函数分别为OSCPUSave SR()和OSCPURestoreSR()。
(3) OS_CPU.H中需要设置一个常量来标识堆栈增长方向。
在μC/OS-II中,用OS_STK_GROWTH来设置堆栈的增长方向#define OS_STK_GROWT H l;//堆栈从高地址向低地址增长#define OS_STK_GROWTH 0;//堆栈从低地址向高地址增长在实验中,我们定义#define OS_STK_GROWTH 1,即堆栈从高地址向低地址增长,这与在80X86中一样。
(4) 定义OS_TASK_SW宏。
OS_TASK_SW宏是uC/OS-II从低优先级任务切换到高优先级任务时的调用,可以采用下面两种方式定义:如果处理器支持软中断,可以使用软中断将中断向量指向OSC txSw函数;或者直接调用OSC rxSw函数。
3.3 μC/OS-II移植结构
所谓移植,就是使一个实时内核能在某个微处理器或微控制器上运行。为了方便移植,大部分的uC/OS-II代码是用C语言写的,但仍需要用C和汇编语言一些与处理器相关的代码,这是因为uC/OS-II在读写处理器寄存器时只能通过汇编语言来实现。
具体移植结果及移植过程设计如下:
(1) INCLLJDE.H头文件的移植
INCLLJDE.H是一个主头文件。在这个主头文件中包含工程所需的其他文件的头文件,这就使工程项目中其他C文件无须分别考虑它实际上需要哪些头文件,它增强了代码的可移植性。使用INCLLJDE.H的缺点是,它可能包含一些与当前需要编译的C文件实际上不相干的头文件,这意味着每个文件的编译时间都可能增加。INCLLJDEH主头文件与具体移植没有关系,但它是必备文件,本系统在CCS2.0环境下,INCLLJDE.H文件的内容,注意其排列顺序。
(2) OS_CPU.h头文件的移植
为了更方便移植uC/OS-II嵌入式操作系统,内核代码使用了自己定义的数据类型,这就要求移植时必须定义微处理器的数据类型与uC/OS-II使用的数据类型相一致,保证移植后RTOS在微处理器系统平台上正常运行,这可以由OS_CPU.h头文件实现。
① 因为不同的微处理器有不同的字长,所以uC/OS-II的移植包括了一系列的类型定义以确保其可移植性。
uC/OS-II代码不直接使用C的short,int和fong等数据类型,而是在OS_CPU.h中首先使用typedef和#define定义的与处理器相关的常量、宏和类型定义。同时用户必须定义任务堆栈的数据类型,这个过程是通过为OS_STK声明正确的C语言数据类型来完成的。
② uC/OS-II主要有两种进入临界段的方式。第一种方式是进入临界段代码时关闭中断,临界段代码结束时开启中断。这种方式较好的保护了临界段代码的正常运行,但是如果进入临界段代码前中断是关着的,那么在结束临界段时中断开关状态就改变了。第二种方式是在进入临界段前先将中断开关状态压栈保护,然后关中断执行临界段代码,当要结束临界段代码时,将进入临界段代码之前的压栈处理的中断开关状态弹出堆栈,这就保证了临界段代码前后中断开关状态是不变的。但这种方法只应用于某些处理器因为压栈和出栈要用到汇编指令,而有些编译器对插入的汇编代码进行优化时不能令人满意。
参考文献:
[1] JeanJ.Labrosse.袁勤勇,黄绍金等译.嵌入式系统构件[M].北京:机械工业出版社,2003.
[2] 田国华.基于μC/OS-II的嵌入式RTOS软件平台构建及其应用研究[D].西北农林科技大学硕士论文,2006.
[3] 季虹,付少锋.实时嵌入式操作系统μC/OS-II内核的分析与改进[J].计算机工程,2007,33(16): 246-250.