嵌入式实时操作系统μC/OS―II在LPC2131上的移植

时间:2022-09-16 01:28:15

嵌入式实时操作系统μC/OS―II在LPC2131上的移植

摘 要: μC/OS―II是一个移植方便、可固化、占先的多任务实时内核,它适用于多种微处理器和数字处理芯片。本文论述了μC/OS―II在ARM处理器LPC2131上移植的详细过程。

关键词: μC/OS―II LPC2131 内核移植

1.系统简介

1.1LPC2131简介

LPC2131包含一个支持仿真的ARM7TDMI-S CPU、与片内存储控制器接口的ARM7局部总线、与中断控制器接口的AMBA高性能总线AHB和连接片内外设功能的VLSI外设总线VPB。AHB和VPB通过桥相连。LPC2131的外设功能(中断控制器除外)都连接到VPB总线。片内外设与器件引脚的连接由引脚连接模块控制。该模块必须由软件控制,以符合外设功能与引脚在特定应用中的需求。

1.2 μC/OS―II简介

μC/OS-II是源码公开的实时嵌入式内核,其性能完全可以与商业产品竞争。此外,μC/OS―II的鲜明特点就是源码公开,便于移植和维护。

μC/OS-II的移植条件:

* 处理器的C编译器可以产生可重入代码;

* 可以使用C调用进入和退出Critical Code(临界区代码);

* 处理器必须支持硬件中断,并且需要一个定时中断源;

* 处理器需要有能够在CPU寄存器与内存和堆栈交换数据的指令。

移植μC/OS―II的主要工作就是处理器和编译器的相关代码。

2.μC/OS―II移植过程

2.1 设置与处理器相关的OS_CPU.H文件

OS_CPU.H文件包括了用#define语句定义的、与处理器相关的常数、宏以和类型。对OS_CPU.H的修改主要有以下几个步骤。

2.1.1 定义与编译器相关的数据类型

μC/OS―II的移植包括了一系列的数据类型定义,以确保其可移植性。相关的数据定义类型如下:

typedef unsigned charBOOLEAN;/* 布尔变量 */

typedef unsigned charINT8U;/* 无符号8位整型变量 */

typedef signed charINT8S; /* 有符号8位整型变量 */

typedef unsigned short INT16U;/* 无符号16位整型变量 */

typedef signed short INT16S;/* 有符号16位整型变量 */

typedef unsigned int INT32U;/* 无符号32位整型变量 */

typedef signed int INT32S;/* 有符号32位整型变量 */

typedef float FP32; /* 单精度浮点数(32位长度)*/

typedef double FP64; /* 双精度浮点数(64位长度)*/

2.1.2 宏定义――临界代码的处理方式

μC/OS-II定义了两个宏,用来关/开中断:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL().它们总是成对使用的,并且分别加在临界段代码的前面和后面,它们可以使用3种不同的方式实现,在这里我们使用的是第二种方式。

第二种方法是:执行OS_ENTER_CRITICAL()时,先将中断状态保存到堆栈中,然后关中断;而当执行OS_EXIT_CRITICAL()时,再从堆栈中恢复原来的中断开/关状态。其实现程序代码如下:

#define OS_CRITICAL_METHOD 2/* 选择开、关中断的方式*/

__swi(0x00) void OS_TASK_SW(void); /*任务级任务切换函数 */

__swi(0x01) void _OSStartHighRdy(void); /*运行优先级最高的任务*/

__swi(0x02) void OS_ENTER_CRITICAL(void);/关中断*/

__swi(0x03) void OS_EXIT_CRITICAL(void); /* 开中断 */

__swi(0x40) void *GetOSFunctionAddr(int Index); /* 获取系统服务函数入口*/

__swi(0x41) void *GetUsrFunctionAddr(int Index);/* 获取自定义服务函数入口*/

__swi(0x42) void OSISRBegin(void); /* 中断开始处理*/

__swi(0x43) intOSISRNeedSwap(void);/*判断中断是否需要切换*/

__swi(0x80) void ChangeToSYSMode(void);/* 任务切换到系统模式*/

__swi(0x81) void ChangeToUSRMode(void);/*任务切换到用户模式*/

__swi(0x82) void TaskIsARM(INT8U prio);/*任务代码是ARM代码*/

__swi(0x83) void TaskIsTHUMB(INT8U prio); /* 任务代码是THUMB*/

2.1.3 设定堆栈增长方向

堆栈由高地址向低地址增长,这个也是和编译器有关的,当进行函数调用时,入口参数和返回地址一般都会保存在当前任务的堆栈中,编译器的编译选项和由此生成的堆栈指令就会决定堆栈的增长方向。

2.2 设置与操作系统相关的OS_CPU_C.C文件

μC/OS―II的移植范例要求编写OSTaskStkInit()等10个简单的C函数。 惟一必要的函数是OSTaskStkInit(),其他9个函数必须申明,但并不一定要包含任何代码。

OSTaskCreat()和OSTaskCreateExt()通过调用OSTaskStkInit(),初始化任务的栈结构;因此,堆栈看起来就像中断刚发生过一样,所有寄存器都保存在堆栈中。

当前任务堆栈初始化完成后,OSTaskStkInit() 返回新的堆栈指针stk,在OSTaskCreate()执行时将会调用其初始化过程,然后通过OSTCBInit()函数调用将返回的SP指针保存到该任务的TCB块中。

OSTaskStkInit()的示意性程序代码如下所示:

OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)

{

opt = opt;

stk = ptos;

获取堆栈指针;

使用满递减堆栈;

使用R0传递第一个参数;

开中断;

关中断计数器OsEnterSum;

Return(stk)

}

2.3 OS_CPU_A.ASM中汇编函数的设置

在该文件中,主要需要编写以下三个汇编函数。

2.3.1 OSStartHighRdy()

OSStart()函数通过调用OSStartHighRdy()来使就绪任务中优先级最高的任务开始运行,

OSStart()多任务启动以后,该函数负责从最高优先级任务的TCB控制块中获得该任务的堆栈指针SP,通过SP依次将CPU现场恢复,这时系统就将控制权交割用户创建该任务进程。

2.3.2 OSCtxSw()

任务级的切换是通过执行软中断指令,或者依据处理器的不同,执行TRAP(陷阱)指令来实现的。中断服务子程序、陷阱或异常处理的向量地址必须指向OSCtxSw()。

如果当前任务调用μC/OS―II提供的功能函数,并使得更高优先级任务进入了就绪态,μC/OS―II就会借助向量地址找到OSCtxSw()。

2.3.3 OSIntCtxSw()

OSIntExit()通过调用OSIntCtxSw(),在ISR执行任务切换的功能。因为OSIntCtxSw()是在ISR中被调用的,所以所有的处理器寄存器都被正确地保存到了被中断任务的堆栈之中。

本文简述了使用嵌入式实时操作系统μC/OS―II的优势并简介了它的基本特性,进而分析了其与LPC2131处理器相关的移植条件,详细介绍了在移植过程中对操作系统内核文件所做的修改工作,实现了一个嵌入式系统的软件平台的设计。

本文为全文原貌 未安装PDF浏览器用户请先下载安装 原版全文

上一篇:对中职《数控编程》课教学的几点探索 下一篇:《C语言程序设计》课程教学研究