μC/OS-Ⅱ在ATmega128上的移植Step by Step
由于μC/OS-Ⅱ的任务切换实际上是模拟一次中断,因此需要知道CPU的中断响应机制。中断发生时,ATmega128按以下
步骤顺序执行:
A. 全局中断允许位I清零。
B. 将指向下一条指令的PC值压入堆栈,同时堆栈指针SP减2。
C. 选择最高优先级的中断向量装入PC,程序从此地址继续执行中断处理。
D. 当执行中断处理时,中断源的中断允许控制位清零。
中断结束后,执行RETI指令,此时
A. 全局中断允许位I置“1”。
B. PC从堆栈推出,程序从被中断的地方继续执行。
特别要注意的是:AVR单片机在响应中断及从中断返回时,并不会对状态寄存器SREG和通用寄存器自动进行保存和恢复操作,因此,对状态寄存器SREG和通用寄存器的中断保护工作必须由用户来完成。
1.4 ATmega128的定时器中断
ATmega128有三个定时器:T0,T1,T2;它们三者都有计数溢出中断功能,而且T1和T2还有匹配比较中断,即定时器计数到设定的值时,产生中断并自动清零。若系统采用这种中断方式,其好处是在中断服务程序ISR中不需要重新装载定时器的值。但本文出于通用性的考虑,仍采用定时器计数溢出中断方式
2 μC/OS-Ⅱ的移植
2.1移植条件
要实现μC/OS-Ⅱ的移植,所用的处理器和编译器必须满足一定的条件:
(1) 所用的C编译器能产生可重入代码。
可重入代码是指可以被一个以上的任务调用,而不必担心其数据会被破坏的代码。可重入代码任何时候都可以被中断,一段时间以后又可以重新运行,而相应的数据不会丢失,不可重入代码则不行。本文所使用ImageCraft公司的ICCAVR V6.29编译器能产生可重入代码。
(2) 用C语言就可以打开和关闭中断。
本文所使用的ICCAVR V6.29编译器支持在C语言中内嵌汇编语句且提供专门开关中断的宏:CLI()和SEI()。这样,使得在C语言中开关中断非常方便。
(3) 处理器支持中断,并且能产生定时中断(通常在10至100Hz之间)本文使用的ATmega128,有3个定时器,能产生μC/OS-Ⅱ所需的定时中断。
(4) 处理器支持能够容纳一定数量数据的硬件堆栈。本文使用的ATmega128有4K RAM,硬件堆栈可以开辟在这4K RAM中。
(5) 处理器有将堆栈指针和其它CPU寄存器从内存中读出和存储到堆栈或内存中的指令。一般的单片机都满足这个要求(如PUSH、POP指令),且ATmega128还具有直接访问I/O寄存器的指令(IN、OUT等),它比8051系列的单片机更容易实现上述要求。
2.2移植的实现
μC/OS-Ⅱ的移植工作包括以下几个内容:
用typedef声明与编译器相关的10个数据类型(OS_CPU.H)
用#define设置一个常量的值(OS_CPU.H)
#define声明三个宏(OS_CPU.H)
用C语言编写六个简单的函数(OS_CPU_C.C)
编写四个汇编语言函数(OS_CPU_A.S)
根据这几项内容,本文逐步来完成。
2.2.1 INCLUDES.H文件
是主头文件,在所有后缀名为.C的文件的开始都包含INCLUDES.H文件。使用INCLUDES.H的好处是所有的.C文件都只包含一个头文件,简洁,可读性强。缺点是.C文件可能会包含一些它并不需要的头文件,增加编译时间。我们是以增加编译时间为代价来换取程序的可移植性的。用户可以改写INCLUDES.H文件,增加自己的头文件,但必须加在文件末尾。
程序清单L2.2.1 INCLUDES.H.
#include // ATmega128的寄存器头文件
#include // ICCAVR的宏
#include
#include
#include
#include //一些C语言的标准库
/*
***************************************************************************
* μC/OS-Ⅱ 头文件
***************************************************************************
*/
#include G:\Porting\ICCAVR\porting12_8\ATmega128\os_cpu.h
#include G:\Porting\ICCAVR\Porting12_8\EX1_mega128\os_cfg.h
#include G:\Porting\ICCAVR\Porting12_8\SOURCE\ucos_ii.h
要注意,μC/OS-Ⅱ 的3个头文件的先后顺序是:os_cpu.h,os_cfg.h最后是ucos_ii.h。
2.2.2 OS_CPU.H文件
OS_CPU.H包括了用#define定义的与处理器相关的常量、宏和类型定义。其中需要注意以下三点:
一是堆栈的生长方向。正如前面所述,ATmega128的堆栈生长方向是向下生长,即从高地址到低地址,因此,OS_STK_GROWTH要被定义为1。
二是进入临界代码段(critical code section)的方法。μC/OS-II提供了三种进入临界代码段的方法,第一种方法是直接对中断允许位置1或清零,即进入临界代码段时,把中断允许位清零,退出临界代码段时,把中断允许位置1;第二种方法是进入临界代码段时,先将中断状态保存到堆栈中,然后关闭中断。与之对应的是,退出临界代码段时,从堆栈中恢复前面保存的中
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
