微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > μC/OS-Ⅱ在ATmega128上的移植Step by Step

μC/OS-Ⅱ在ATmega128上的移植Step by Step

时间:10-08 来源:互联网 点击:

二是进入临界代码段(critical code section)的方法。μC/OS-II提供了三种进入临界代码段的方法,第一种方法是直接对中断允许位置1或清零,即进入临界代码段时,把中断允许位清零,退出临界代码段时,把中断允许位置1;第二种方法是进入临界代码段时,先将中断状态保存到堆栈中,然后关闭中断。与之对应的是,退出临界代码段时,从堆栈中恢复前面保存的中断状态。第三种方法是,由于某些编译提供了扩展功能,用户可以得到当前处理器状态字的值,并将其保存在C函的局部变量之中。这个变量可用于恢复状态寄存器SREG的值。由于ICCAVR不提供此项扩展功能,所以本文暂不考虑用第 三种方法进入临界代码段。第一种方法存在着一个小小的问题:如果在关闭中断后调用μC/OS-II的功能函数,当函数返 回后,中断可能会被打开。我们希望如果在调用μC/OS-II的功能函数前,中断是关着的,那么在函数返回后,中断仍然是关着的。方法1显然不满足要求。本文使用μC/OS-II的第二种方法——先将中断状态保存到堆栈中,然后关闭中断。

三是任务切换函数OS_TASK_SW( )是个宏,具体的实现是在OSCtxSw( )(OS_CPU_A.S)中程序清单L 2.2.2 OS_CPU.H.

#ifdef OS_CPU_GLOBALS

#define OS_CPU_EXT

#else

#define OS_CPU_EXT extern

#endif

/*

**************************************************************************

* 数据类型

* (与编译器相关的内容)

*************************************************************************

*/

typedef unsigned char BOOLEAN;

typedef unsigned char INT8U; // 无符号8位数

typedef signed char INT8S; // 带符号8位数

typedef unsigned int INT16U; // 无符号16位数

typedef signed int INT16S; // 带符号16位数

typedef unsigned long INT32U; // 无符号32位数

typedef signed long INT32S; // 带符号32位数

typedef float FP32; // 单精度浮点数

typedef unsigned char OS_STK; // 堆栈入口宽度为8位

typedef unsigned char OS_CPU_SR; // 定义状态寄存器为8位

/*

*************************************************************************

*

*方法 #1: 用简单指令开关中断。

* 注意,用方法1关闭中断,从调用函数返回后中断会重新打开!

* 方法 #2: 关中断前保存中断被关闭的状态.

*

*************************************************************************

*/

#define OS_CRITICAL_METHOD 2

#if OS_CRITICAL_METHOD == 1

#define OS_ENTER_CRITICAL() _CLI() // 关闭中断

#define OS_EXIT_CRITICAL() _SEI() // 打开中断

#endif

#if OS_CRITICAL_METHOD == 2

#define OS_ENTER_CRITICAL() asm(st -y,r16\n in r16,0x3F\n cli\n push r16\n

ld r16,y+); // 关闭中断

#define OS_EXIT_CRITICAL() asm(st -y,r16\n pop r16\n out 0x3F,r16\n ld

r16,y+); // 打开中断

#endif

#define OS_STK_GROWTH 1 // 堆栈向下生长

#define OS_TASK_SW() OSCtxSw()

2.2.3 OS_CPU_C.C文件

μC/OS-II的移植需要用户编写OS_CPU_C.C中的十个函数:

OSTaskStkInit();

OSInitHookBegin ();

OSInitHookEnd ();

OSTaskCreateHook();

OSTaskDelHook();

OSTaskSwHook();

OSTaskStatHook();

OSTimeTickHook();

OSTCBInitHook ();

OSTaskIdleHook ();

实际需要修改的只有OSTaskStkInit()函数,其它九个函数都是由用户定义的。如果用户需要使用这九个函数,可将文件OS_CFG.H中的#define constant

OS_CPU_HOOKS_EN设为1,设为0表示不使用这些函数。本文自定义的任务堆栈结构下图所示。函数OSTaskStkInit()是由OSTaskCreate()或OSTaskCreateExt()调用,用来初始化任务堆栈的。经初始化后的任务堆栈应该跟发生过一次中断后任务的堆栈结构一样。由前叙述可知,ATmega128在发生中断后,自动保存了程序计数器PC。为了

保存全部现场,还需要保存状态寄存器SREG,R0~R31这32个通用寄存器及SP的值。

需要注意的是:μC/OS-Ⅱ规定,在建立任务时,只能传递一个参数给任务,而且这个参数是一个指针;ICCAVR编译器规定,传递给函数的第一个参数是放在R16、R17中的,所以在R16、R17的位置中放置的是向任务传递的参数。R28、R29的 值不需要入栈,是因为R28、R29所组成的Y指针被用作软件堆栈的指针返回给调用函数。

根据上述自定义任务堆栈的结构,编写OSTaskStkInit()。其程序清单如2.2.3所示。

程序清单L 2.2.3 OS_CPU_C.C

#define OS_CPU_GLOBALS

#include G:\Porting\ICCAVR\porting12_8\EX1_m

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top