1 开发工具和运行环境 实现μC/OS-II的移植,要求所用的C编译器支持混合编程。KEIL C51可为众多的8051派生器件编程。我们选用的是KEIL7.02集成开发环境,仿真板基于C8051F015芯片。 2 移植中所需修改的文件 和CPU相关的文件主要有三个,分别是汇编文件OS_CPU_A.ASM、C语言文件 OS_CPU_C.C和头文件OS_CPU.H。 2.1 OS_CPU.H文件 OS_CPU.H文件中定义了数据类型及与硬件相关的基本信息。其中改动部分如下: 在C8051F中,堆栈都是按字节操作的,故数据类型OS_STK声明为8位。方向从低地址向高地址方向递增,所以OS_STK_GROWTH设置为0。μC/OS-II在进入系统临界代码区之前要关中断,等到退出临界区后再打开,以保护核心数据不被多任务环境下的其它任务或中断破坏。开、关中断可通过设置SFR中的中断屏蔽位实现。在关中断时,先将IE的内容保存在全局变量IE_ SHADOW中,然后关中断;退出临界区时,还原IE_SHADOW的值。OS_TASK_SW()用来实现任务切换。就绪任务的堆栈初始化应该模拟一次中断发生后的样子,堆栈中应该按入栈次序设置好各个寄存器。OS_TASK_SW()函数模拟一次中断过程,在中断返回的时候进行任务切换。由于C8051F015没有软中断,故直接定义宏OS_TASK_SW()为函数OSCtxSw()。 2.2 OS_CPU_A.ASM文件 编译器将每个文件作为一个模块,编译模块以主名命名,称为编译模块名,用NAME 来声明。因此,应在文件头部声明NAME OS_CPU_A。 函数有程序部分和局部变量部分,它们分别放在独立的段中。在大模式下,段名声明的固定格式为 ?PR?函数名?模块名 SEGMENT CODE。因此需要将OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()和OSTickISR()用上面的格式一一声明。如?PR?OSStartHighRdy?OS_CPU_A SEGMENT CODE,本模块实现的函数需要用PUBLIC声明,如PUBLIC OSStartHighRdy等。 C51将所有定义说明的数据标识符转换为大写字符,对函数则根据有无寄存器参数传送和函数是否可重入进行换名,如:void OSIntEnter(void) reentrant函数的名字OSIntEnter换成_?OSIntEnter。这些规则可从编译后的LST文件中看出。程序中声明引用的五个全局变量为OSTCBCur、OSTCBHighRdy、OSRunning、OSPrioCur、OSPrioHighRdy,声明格式是EXTRN IDATA (OSTCBCur)等。调用四个外部子程序OSTaskSwHook()、OSIntEnter()、OSIntExit()、OSTimeTick(),固定格式为:EXTRN CODE (_?OSTaskSwHook)等。 由于C8051F的堆栈指针只有8位,只能指向内部数据区的256个字节,因此,当前运行的任务的堆栈在IDATA区,堆栈大小为40H(64字节),堆栈起点由KEIL决定。通过标号可以获得KEIL分配的SP起点,代码如下: 2.3 OS_CPU_C.C文件 移植μC/OS-II 需要在OS_CPU_C.C中定义六个函数,而实际上需要定义的只有OSTaskStkInit()一个函数。该函数用来初始化任务的堆栈。初始状态的堆栈只须初始化?C_XBP (仿真堆栈指针)、任务地址及堆栈的长度。由于只有INC DPTR指令,故返回栈的最低地址,且最低地址处存放栈的长度,方便用汇编语言实现任务的切换。堆的大小可根据任务的实际情况自行确定,由参数ppdata所指的值确定。 3 可重入函数 因为51系列堆栈空间的限制, KEIL编译器没有像大系统那样使用调用堆栈。一般C语言调用过程中,会把过程的参数和使用的局部变量入栈。为了提高效率,编译器没有提供这种堆栈,而是提供一种压缩栈,每个过程被给定一个空间用于存放局部变量。过程中的每个变量都放在这个空间的固定位置,当递归调用这个过程时,会导致变量被覆盖。编译器允许将函数定义成可重入函数,由reentrant关键字指定,可重入函数可被单独保存。因为这些堆栈是模拟的,可重入函数一般都比较大,运行起来也比较慢。模拟栈不允许传递bit类型的变量,也不能定义局部位标量。移植中最好是将可能被多个任务使用的函数定义成可重入函数。 |