嵌入式操作系统UC/OSII bc45编译ucos-II的过程

2011-05-14 20:07丁旖武颖丁柄文
卷宗 2011年10期
关键词:堆栈寄存器中断

丁旖 武颖 丁柄文

摘要:嵌入式系统的应用和发展是计算机技术自桌面系统和网络技术之后,IT产业和IT技术又一 个新的重大进展。而对于规模比较小的系统,UC/OSII 则以实时行强,内核公开,系统稳定,易于学习和开发等特点受到广大技术人员和嵌入式爱好者的青睐。本文以UC/OSII为例介绍嵌入式uC/OS-II实时操作系统在嵌入式平台上的移植程序及方法。

关键词:嵌入式;UC/OSII;实时操作系统;开发流程;移植μC/OS-Ⅱ

1 引言

在日常生活等各个领域.当前流行的嵌入式操作系统有linux,wince, UC/OSII 等等。我国正在成为世界电子制造业的重要基地之一,对嵌入式系统技术及相关技术人才存在巨大需求。

2 uC/OS-II的移植程序

将μC/OS-Ⅱ移植到不同的处理器上。所谓移植,就是使一个实时内核能在某个微处理器或微控制器上运行。

要使μC/OS-Ⅱ正常运行,处理器必须满足以下要求:

1. 处理器的C编译器能产生可重入代码。

用C语言就可以打开和关闭中断。

处理器支持中断,并且能产生定时中断(通常在10至100Hz之间)。

处理器支持能够容纳一定量数据(可能是几千字节)的硬件堆栈。

处理器有将堆栈指针和其它CPU寄存器读出和存储到堆栈或内存中指令。

像Motorola 6805系列的处理器不能满足上面的第4条和第5条要求,所以μC/OS-Ⅱ不能在这类处理器上运行。

移植工作包括以下几个内容:

用#define设置一个常量的值(OS_CPU.H)

声明10个数据类型(OS_CPU.H)

用#define声明三个宏(OS_CPU.H)

用C语言编写六个简单的函数(OS_CPU_C.C)

编写四个汇编语言函数(OS_CPU_A.ASM)

一旦代码移植结束,下一步工作就是测试。

3 UCOS在51单片机的移植

任务函数中带有形参和局部变量时若使用reentrant关键字会引起重入,从C51.PDF 129-131页的内容知:为了函数重入,形参和局部变量必须保存在堆栈里,由于51硬件堆栈太小,KEIL将根据内存模式在相应内存空间仿真堆栈(生长方向由上向下,与硬件栈相反)。对于大模式编译,函数返回地址保存在硬件堆栈里,形参和局部变量放在仿真堆栈中,栈指针为?C_XBP,XBPSTACK=1时,起始值在startup.a51中初始化为FFFFH+1。

为了支持重入,重新设计了堆栈结构。增加了保存仿真堆栈指针?C_XBP和堆栈内容的数据结构。相应改变的文件有:OS_CPU_A.ASM、OS_CPU_C.C、OS_CPU.H、YY.C。建议使用统一的固定大小的堆栈空间,尽管uCOSII原作者把不同任务使用不同空间看成是优点,但为了在51上有效实现任务重入,还是不使用这个优点。

用户堆栈空间的大小是可以精确计算出来的。用户堆栈空间=硬件堆栈空间+仿真堆栈空间。硬件栈占用内部RAM,内部RAM执行效率高,如果堆栈空间过大,会影响KEIL编译的程序性能。如果堆栈空间小,在中断嵌套和程序调用时会造成系统崩溃。综合考虑,可把硬件堆栈空间大小定成了64字节,用户根据实际情况可以自行设定。仿真堆栈大小取决于形参和局部变量的类型及数量,可以精确算出。因为所有用户栈使用相同空间大小,所以取占用空间最大的任务函数的空间大小为仿真堆栈空间大小。这样用户堆栈空间大小就唯一确定了。可将用户堆栈空间大小用宏定义在OS_CFG.H文件中,宏名为MaxStkSize。

51的SP只有8位,无法在64K空间中自由移动,只好采用拷贝全部硬件堆栈内容的笨办法。51本来就弱,这么一来缺点更明显了。其实,引入OS必然要付出代价,一般OS要占用CPU10%-20%的负荷能力,需权衡利弊决定。切换频率决定了CPU的耗费,频率越高耗费越大,大到一定程度就该换更强的CPU了。我选了50Hz的切换频率,不高也不低,用户可以根据需要自行定夺。

4μC/OS-II在嵌入式开发平台上进行移植的一般方法和技巧

在选定了系统平台和开发工具之后,进行μC/OS-II的移植工作,一般需要遵循以下的几个步骤:

深入了解所采用的系统核心

分析所采用的C语言开发工具的特点

编写移植代码

进行移植的测试

针对项目的开发平台,封装服务函数 (类似80x86版本的PC.C和PC.H)

系统核心

无论项目所采用的系统核心是MCU、DSP、MPU,进行μC/OS-II的移植时,所需要关注的细节都是相近的。

首先,是芯片的中断处理机制,如何开启、屏蔽中断,可否保存前一次中断状态等。还有,芯片是否有软中断或是陷阱指令,又是如何触发的。

此外,还需关注系统对于存储器的使用机制,诸如内存的地址空间,堆栈的增长方向,有无批量压栈的指令等。

植代码

在深入了解了系统核心与开发工具的基础上,真正编写移植代码的工作就相对比较简单了。

μC/OS-II自身的代码绝大部分都是用ANSI C编写的,而且代码的层次结构十分干净,与平台相关的移植代码仅仅存在于OS_CPU_A.ASM、OS_CPU_C.C以及OS_CPU.H这三个文件当中。

在移植的时候,结合前面两个步骤中已经掌握的信息,基本上按照《嵌入式实时操作系统μC/OS-II》一书的相关章节的指导来做就可以了。

但是,由于系统核心、开发工具的千差万别,在实际项目中,一般都会有一些处理方法上的不同,需要特别注意。以C6711的移植为例:

※ 中断的开启和屏蔽的两个宏定义为:

#define OS_ENTER_CRITICAL() Disable_int()

#define OS_EXIT_CRITICAL() Enable_int()

Disable_int和Enable_int是用汇编语言编写的两个函数。在这里使用了控制状态寄存器(CSR)的一个特性——CSR中除了控制全局中断的GIE位之外,还有一个PGIE位,可用于保存之前的GIE状态。

因此在Disable_int中先将GIE的值写入PGIE,然后再将GIE写0,屏蔽中断。而在Enable_int中则从PGIE读出值,写入GIE,从而回复到之前的中断设置。

这样,就可以避免使用这两个宏而意外改变了系统的中断状态——此外,也没有使用堆栈或局部变量,比原作者推荐的方法要好。※ 任务的切换:

前文说过,C6711中没有软中断机制,所以任务的切换需要用汇编语言自行编写一个函数_OSCtxSw来实现,并且 #define OS_TASK_SW() OSCtxSw() 在C6711中需要入栈保护的寄存器包括A0-A15、B0-B15、CSR、IER、IRP和AMR,这些再加上当前的程序地址构成一个存储帧,需要入栈保存。

_OSCtxSw函数中,需要像发生了一次中断那样,将上述存储帧入栈,然后获取被激活任务的TCB指针,将其存储帧的内容弹出,从而完成任务切换。

需要特别注意的是,在这里OS_TASK_SW是作为函数调用的,所以如前文所述,调用时的当前程序地址是保存在B3寄存器中的,这也就是任务重新激活时的返回地址。

※ 中断的编写:

如前文所述,如果用“interrupt”关键字声明函数,CCS在编译时,会自动将该函数中使用到的寄存器入栈、出栈保护。但是,这会导致各种中断发生时,出入栈的内容各不相同。这对于μC/OS-II是会引起严重错误的。因为μC/OS-II要求中断发生时的入栈操作使用和发生任务切换时完全一样的存储帧结构。

因此,在移植时、基于μC/OS-II进行开发时,都不应当使用“interrupt”关键字,而应用如下结构编写中断函数:

void OSTickISR (void)

{

DSP_C6x_Save(); // 服务函数,入栈

OSIntEnter();

if (OSIntNesting == 1) // v2.51版本新增加

{

OSTCBCur->OSTCBStkPtr

=(OS_STK*) DSP_C6x_GetCurrentSP(); // 服务函数

} // 获取当前SP的值

// 允许中断嵌套 则在此处开中断

OSTimeTick();

OSIntExit();

DSP_C6x_Resume(); // 服务函数,出栈

}

DSP_C6x_Save 和DSP_C6x_Resume是两个服务函数,分别完成中断的出、入栈操作。它们与OS_TASK_SW函数的区别在于:中断发生时的当前程序地址是自 动保存在IRP寄存器的,应将其作为任务返回地址,而不再是B3。此外DSP_C6x_Resume是一个永远不会返回的函数,在将所有内容出栈后,它就直接跳转回到中断发生前的程序地址处,继续执行。

进行移植的测试

在编写完了所有的移植代码之后,就可以编写几个简单的任务程序进行测试了,大体上可以分三个步骤来进行,相关资料比较详尽,这里就不多作赘述 了。

封装服务函数

最后这个步骤,往往是容易被忽视的,但对于保持项目代码的简洁、易维护有很重要的意义。

μC/OS-II的原作者强烈建议将源代码分路径进行存储,

5. 结论

μC/OS-II具有免费、简单、可靠性高、实时性好等优点,但也有缺乏便利 开发环境等缺点,尤其不像商用嵌入式系统那样得到广泛使用和持续的研究更新。但开放性又使得开发人员可以自行裁减和添加所需的功能,在许多应用领 域发挥着独特的作用。当然,是否在单片机系统中嵌入μC/OS-II应视所开发的项目而定,对于一些简单的、低成本的项目来说,就没必要使用了。

参考文献

[1] JEAN J.LABROSSE,邵贝贝译.

[2] μC/OS-II ―源码公开的实时嵌入式操作系统. 中国电力出版社

[3] uC/OS-II-源码公开的实时嵌人式操作系统【M】,邵贝贝译.中国电力出版社.2001

[4] 忠梅等 ‘ARM 嵌入式处理器结构与应用基础.北京:北京虢譬航天大学出版社,2002

猜你喜欢
堆栈寄存器中断
Lite寄存器模型的设计与实现
嵌入式软件堆栈溢出的动态检测方案设计*
跟踪导练(二)(5)
千里移防,卫勤保障不中断
分簇结构向量寄存器分配策略研究*
基于堆栈自编码降维的武器装备体系效能预测
AT89C51与中断有关的寄存器功能表解
FPGA内嵌PowerPC的中断响应分析
高速数模转换器AD9779/AD9788的应用
一种用于分析MCS-51目标码堆栈深度的方法