μC/OS-Ⅱ在ATmega128上的移植Step by Step(2)
- UID
- 1023166
- 性别
- 男
- 来自
- 燕山大学
|
μC/OS-Ⅱ在ATmega128上的移植Step by Step(2)
三是任务切换函数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_mega128\includes.h" //包含头文件
/*
*************************************************************************
* 九个接口函数(暂未使用)
*************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSInitHookBegin (void)
{
}
#endif
... ...
/*
*************************************************************************
* OSTaskStkInit()
*************************************************************************
*/
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos,
INT16U opt)
{
INT8U *psoft_stk;
INT8U *phard_stk; //为操作AVR单片机软、硬件堆栈而建立的临时指针
INT16U tmp;
opt = opt; //'opt'未使用,此处可防止编译器的警告
psoft_stk = (INT8U *)ptos; // 载入堆栈指针
phard_stk = (INT8U *)ptos
- OS_TASK_SOFT_STK_SIZE // 任务栈栈空间的大小
L1
+ OS_TASK_HARD_STK_SIZE; // 系统返回的堆栈(硬件堆栈) L2
tmp = *(INT16U const *)task;
*phard_stk-- = (INT8U)tmp;
*phard_stk-- = (INT8U)(tmp >> 8); //把任务入口地址放入硬件堆栈
//******************通用寄存器入栈**************************/
*psoft_stk-- = (INT8U)0x00; // R0 = 0x00 L3
*psoft_stk-- = (INT8U)0x01; // R1 = 0x01
*psoft_stk-- = (INT8U)0x02; // R2 = 0x02
*psoft_stk-- = (INT8U)0x03; // R3 = 0x03
*psoft_stk-- = (INT8U)0x04; // R4 = 0x04
*psoft_stk-- = (INT8U)0x05; // R5 = 0x05
*psoft_stk-- = (INT8U)0x06; // R6 = 0x06
*psoft_stk-- = (INT8U)0x07; // R7 = 0x07
*psoft_stk-- = (INT8U)0x08; // R8 = 0x08
*psoft_stk-- = (INT8U)0x09; // R9 = 0x09
*psoft_stk-- = (INT8U)0x10; // R10 = 0x10
*psoft_stk-- = (INT8U)0x11; // R11 = 0x11
*psoft_stk-- = (INT8U)0x12; // R12 = 0x12
*psoft_stk-- = (INT8U)0x13; // R13 = 0x13
*phard_stk-- = (INT8U)tmp;
*phard_stk-- = (INT8U)(tmp >> 8); //把任务入口地址放入硬件堆栈
//***********R16、R17的位置中放置向任务传递的参数*****************/
tmp = (INT16U)p_arg;
*psoft_stk-- = (INT8U)tmp;
*psoft_stk-- = (INT8U)(tmp >> 8);
*psoft_stk-- = (INT8U)0x18; // R18 = 0x18
*psoft_stk-- = (INT8U)0x19; // R19 = 0x19
*psoft_stk-- = (INT8U)0x20; // R20 = 0x20
*psoft_stk-- = (INT8U)0x21; // R21 = 0x21
*psoft_stk-- = (INT8U)0x22; // R22 =
0x22
*psoft_stk-- = (INT8U)0x23; // R23 = 0x23
*psoft_stk-- = (INT8U)0x24; // R24 =
0x24
*psoft_stk-- = (INT8U)0x25; // R25 = 0x25
*psoft_stk-- = (INT8U)0x26; // R26 = 0x26
*psoft_stk-- = (INT8U)0x27; // R27 = 0x27
/***R28、R29用作软件堆栈的指针储存在任务控制块OS_TCB的OSTCBStkPtr中***/
*psoft_stk-- = (INT8U)0x30; // R30 = 0x30
*psoft_stk-- = (INT8U)0x31; // R31 = 0x31L2
*psoft_stk-- = (INT8U)0x80; // SREG = 0x80,开全局中
断
tmp = (INT16U)phard_stk;
*psoft_stk-- = (INT8U)(tmp >> 8); // SPH
*psoft_stk = (INT8U) tmp; // SPL
return ((void *)psoft_stk);
}
接下去的工作便是测试移植的代码,具体的测试工作,请参考邵贝贝译的《嵌入式实时操作系统μC/OS-II(第2版)》。
|
|
|
|
|
|