在前几讲中,介绍了μC/OS-II的概念、工作机制,还介绍了μC/OS-II在Intel 80X86CPU上的移植,相信读者通信学习,已经对移植的过程和步骤有了一定的了解。由于RAM容量的限制,移植就存在一定的困难;但对于有些8位的MCU,将μC/OS-II移植到MOTOROLA MC68H908GP32(以下简称GP32)上。
一、在GP32上移植μC/OS-11的主要问题
GP32为韩国Gamepark株式会社自行开发的掌上游戏机,于2001年10月开始发售。主机使用3.5英寸TFT-LCD液晶,解决了STN-LCD画面暗的缺点(GBA存在这样的问题)同时也解决了画面残象的问题,玩动作游戏画面更流畅。主机参数
名称- GP32,LCD- 反射型TFT彩色液晶,画面尺寸- 3.5英寸,解象度- 320 x 240,表示能力- 65536色,CPU- 32bit RISC-CPU,ROM- 512Kbyte,SDRAM- 8MB,声音- 16Bit Stereo Sound MIDI 4声道PCM,通信- RF Network支援,使用电池- 2节AA电池,电池寿命- 12小时,外部连接端子- USB port,MEDIA- SMC(Smart Card Media)
在第(4)讲中,介绍过要移植μC/OS-11,目标处理必须满足以下要求:
(1)处理器的C编译器能产生可重入代码;
(2)用C语言就可以打开和关闭中断;
(3)处理器支持中断,并且能产生定时中断(通常在10~100Hz之间);
(4)处理器支持足够的RAM,保存全局变量和作为多任务环境下的任务堆栈。
(5)处理器有将堆栈指针和其他CPU寄存器读出和存储到堆栈或内存中的指令。
编译后的μC/OS-II的内核大约有6~10KB;如果只保留最核心的代码,则最小可压缩到2KB。RAM的占用与系统中的任务数有关,任务堆栈要占用大量的RAM空间,堆栈的大小取决于任务的局部变量、缓冲区大小及可能的中断嵌套的层数。而像MOTOROLA6805系列的8位MCU,由于RAM资源太小且堆栈指针是固定的,不能满足上面的第(4)条和第(5)条要求,所以μC/OS-II不能在这类处理器上运行。
μC/OS-II 是一种基于优先级的抢占式多任务实时操作系统,包含了实时内核、任务管理、时间管理、任务间通信同步(信号量,邮箱,消息 队列)和内存管理等功能。它可以使各个任务独立工作,互不干涉,很容易实现准时而且无误执行,使实时应用程序的设计和扩展变得容易,使应用程序的设计过程大为减化。
μC /OS-II是一个完整的、可移植、可固化、可裁剪的占先式实时多任务内核。μC/OS-II绝大部分的代码是用ANSI的C语言编写的,包含一小部分汇编代码,使之可供不同架构的微处理器使用。至今,从8位到64位,μC/OS-II已在超过40种不同架构上的微处理器上运行。μC/OS-II已经在世界范围内得到广泛应用,包括很多领域, 如手机、路由器、集线器、不间断电源、飞行器、医疗设备及工业控制上。实际上,μC/OS-II已经通过了非常严格的测试,并且得到了美国航空管 理局(FEDeral Aviation Administration)的认证,可以用在飞行器上。这说明μC/OS-II是稳定可靠的,可用于与人性命攸关的安全紧要(safety critICal)系统。除此以外,μC/OS-II 的鲜明特点就是源码公开,便于移植和维护。
GP32是68HC08家庭的成员,具有512字节的片内RAM,32K字节的片内Flash,8MHz总线时钟。内部寄存器包括1个8位累加器A,1个16位索引寄存器X,1个16位堆栈指针寄存器SP,1个16位程序指针寄存器PC及1个8位标志寄存器CCR。与6805系列MCU相比,68HC08系列MCU的堆栈指针为16位,可以自由寻址。这就满足了移植条件(5),且可以使用C编译器生成代码。
在GP32上移植μC/OS-II的主要困难还是RAM资源太少。为了移植成功,必须采取措施减少RAM的用量,包括限制系统中的任务数量、仔细修改μC/OS-II内核、去掉不使用的部分、限制任务的断嵌套层数、在任务中尽量减少使用局部变量等等。在采取了上述措施后,可将RAM用量减少到最低。在GP32上移植μC/OS-II更多的是一种演示,能更好地说明μC/OS-II内核的可裁剪性和灵活性。
在本讲中将介绍一个移植实例。为了减少RAM用量,在本例中只运行了2个用户任务。尽量减池一内核中不必要的模块(包括由箱、消息队列、内存管理等),去掉了任务挂起、唤醒和删除等扩展功能,但仍然支持任务的创建和管理,也保留了信号量模块来用来任务间的通讯。
二、工具和运行环境
要实现μC/OS-II向GP32的移植,需要一个面向MC68HC08的C编译器。笔者使用的是HIWARE公司的C编译器。移植过程同样适用于MC68HC08家庭的其他成员。
三、移植中所需修改的文件
首先是编写整个项目的公共头文件include.h,这个文件定义使用内核中的哪些模块。Include.h会被所有的C源程序引用。还要修改和CPU相关的三个文件,分别是头文件OS_CPU08.H、汇编代码文件OS_CPU08.ASM和C代码文件OS_CPU08.C。
1.include.h文件
include.h是主头文件,在所有后缀名为。C的文件的开始都包含include.h文件。文件中可以内核进行裁剪。在本例中定义如下:
#define OS_MAX_EVENTS 2 /*共用了2个信号量*/
#define OS_MAX_MEM_PART 0 /*不使用内存块功能*/
#define OS_LOWEST_PRIO 20 /*定义最低优先级20*/
#define OS_TASK_IDLE_STK_SIZE 60 /*定义空闲任务堆栈60字节*/
#define OS_TASK_STAT_EN 0 /*不使用统计任务*/
#define OS_MBOX_EN 0 /*不使用消息邮箱功能*/
#define OS_MEM_EN 0 /*不包括内存管理部分代码*/
#define OS_TASK_CHANGE_PRIO_EN 0 /*不包括任务优先级动态改变代码*/
#define OS_TASK_CREATE_EN1 /*包括任务创建函数代码*/
#define OS_TASK_CREATE_EXT_EN 0 /*不包括带扩展功能的任务创建函数*/
#define OS_TICKS_PER_SEC 10 /*定义每秒的时钟节拍数*/
对于不同类型的处理器,还需要改写include.h文件,增加自己的头文件,但必须加在文件末尾。在安装μC/OS-II的时候,附带了几个移植实例,例如,针对Intel 80X86的代码安装到IIL目录下。我们为GP32编写的移植实例可放在IIHC08下,这样,为GP32改写的include.h文件中应该加入下列语句:
#include "iiHC08_CPU08.ASM"
#include "iiHC08_CPU08.C"
#include "iiHC08_CPU08.H"
2.OS_CPU08.H文件
OS_CPU08.H文件中定义了硬件相关的基本信息:
/*数据类型*/
typedef unsigned short INT16U;
typedef signed short INT16S;
typedef unsigned long INT32U;
typedef signed long INT32S;
/*定义堆栈增长方向*/
#define OS_STK_GROWTH1 /*堆栈由高地址向低地址增长*/
/*定义堆栈单位*/
#define OS_STK INT8U
/*定义进入临界代码区开关中断宏*/
#define OS_ENTER_CRITICAL() asm sei
#define OS_EXIT_CRITICAL() asm cli
#define OS_TASK_SW() asm swi
(1)数据类型
数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作。 变量是用来存储值的所在处;它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。在声明变量时也可指定它的数据类型。所有变量都具有数据类型,以决定能够存储哪种数据。
由于不同的处理器有不同的字长,μC/OS-II的移植需要重新定义一系列的数据结构。具体字长还和使用的C编译器有关。在GP32中堆栈是按字节操作的,堆栈数据类型OS_STK声明为8位。μC/OS-II中所有任务的堆栈都必须用OS_STK声明。
数据类型的出现,是因为电脑内存有限。 把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。 例如大胖子必须睡双人床,就给他双人床,瘦的人单人床就够了。
(2)代码临界区
μC/OS-II在进入系统临界代码区之前要关闭中断,等到退出临界区后再打开,从而保护核心数据不被多任务环境下的其他任务或中断破坏。在GP32中,开关中断可以通过汇编指令CLI和SEI来实现。所以μC/OS-II中的宏OS_ENTER_CRITICAL()定义为指令SEI,OS_EXIT_CRITICAL()定义为指令CLI。
(3)堆栈增长方向
GP32的堆栈是由高地址向低地址方向增长的,所以常量OS_STK_GPOWTH必须设置为1。判断堆栈增长方向
说明:今天看到alLOCa.c中find_stack_direction函数,用来判断堆栈的增长方向,记录下来。
#define ADDRESS_FUNCTION(arg) &(arg)
/* Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* Direction unknown. */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
#else /* STACK_DIRECTION == 0; need run-time code. */
static int stack_dir; /* 1 or -1 once known. */
本文关键字:暂无联系方式嵌入式系统-技术,单片机-工控设备 - 嵌入式系统-技术