uC/OS-II在MC9S12XS128上的移植
热1已有 782 次阅读 2011-12-14 01:29硬件结构的分析
CPU12X寄存器组包括16位程序计数器PC、16位堆栈指针寄存器SP、16位累加器D或者8位累加器A和B、16位变址寄存器X和Y、16位条件码寄存器CCR,另外还包括全程寄存器、RAM页面管理寄存器、EEPROM页面管理寄存器.
S12XS的中断响应
S12XS单片机在响应中断时,其硬件会自动将核心寄存器堆推入堆栈,堆栈的地址由高地址向低地址增长
uC/OS-II在MC9S12XS128上的移植设计
uC/OS-II的移植一方面需要根据单片机硬件的独特结构 ,编写与该单片机硬件相关的相关代码,另一方面需要考虑实际应用,选择内核功能,裁剪内核的大小,提高系统的稳定性。
OS_CPU.H中与CPU相关的代码
在OS_CPU.H文件中定义与CPU相关的硬件信息,包括数据类型、堆栈数据类型、堆栈增长方向的定义以及任务调度函数OS_TASK_SW()和临界区代码处理方法的宏定义。
重新定义uC/OS-II 的移植包括的一系列数据类型定如下:
typedef unsigned char BOOLEAN; /* 布尔变量*/
typedef unsigned char INT8U; /* 无符号8 位整型变量*/
typedef signed char INT8S; /* 有符号8 位整型变量 */
typedef unsigned int INT16U; /* 无符号16 位整型变量*/
typedef signed int INT16S; /* 有符号16 位整型变量*/
……
CPU12X其堆栈是十六位宽度的,故定义堆栈数据类型如下:
#define OS_STK INT16U /* 堆栈是16 位宽度*/
MC9S12XS128单片机的堆栈地址是由高地址向低地址增长的,故有定如下:
#define OS_STK_GROWTH 1 /*堆栈指针由高向低地址增长*/
采用软中断模拟任务调度,则宏定义如下:
#define OS_TASK_SW() __asm swi
方法一脱离临界代码区时中断会强行打开,方法二堆栈偏移量会出现偏差。故选择方法三进行临界区代码中断处理。
即 #define OS_CRITICAL_METHOD 3 并定义
Typedef unsigned char OS_CPU_SR;
#define OS_ENTER_CRITICAL() __asm (tpa; sei; staa cpu_sr) #define OS_EXIT_CRITICAL() __asm (ldaa cpu_sr; tap)
OS_CPU.C中的相关代码
难点为如何改写任务堆栈初始化函数OSTaskStkInit(),完成任务栈的初始化,使得任务栈的结构看起来如同在任务执行过程中发生过一次中断,并将所有寄存器保存到堆栈一样。
根据中断发生时CPU12X各个寄存器的入栈顺序,函数代码如下:
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
{
INT16U *stk;
INT8U *wstk;
opt = opt;
stk = (INT16U *)ptos; //载入堆栈指针
*--stk = opt;
*--stk = (INT16U)(task); //PC低位入栈
*--stk =(INT16U)(((INT32U)task) >> 8); //PC高位入栈
*--stk = (INT16U)(0x1122); //Y寄存器入栈
*--stk = (INT16U)(0x3344); //X寄存器入栈
*--stk = (INT16U)0xBBAA; //A,B累加器入栈
*--stk = (INT16U)(0x0080); //CCR入栈
wstk = (INT8U *)stk;
*--wstk = *(INT8U *)0x10; //GPAGE入栈
*--wstk = *(INT8U *)0x17; //EPAGE入栈
*--wstk = *(INT8U *)0x16; //RPAGE入栈
*--wstk = (INT8U )task; //PPAGE入栈
return ((OS_STK *)wstk);
}
OS_CPU_A.asm中与硬件相关的代码
在此文件中要求用户编写四个汇编函数OSStartHighRdy(),OSCtxSw(), OSIntCtxSw(),OSTickISR(),这四个函数具有公共部分:寄存器入栈和寄存器出栈。可按照该CPU的栈结构进行相应改写。而OSIntCtxSw()函数用于从中断返回时进行任务切换,故不需进行寄存器入栈。
其参考OSTickISR()函数源程序如下:
OSTickISR:
;相关寄存器入栈
ldaa GPAGE
psha
ldaa EPAGE
psha
ldaa RPAGE
psha
ldaa PPAGE
psha
inc OSIntNesting ;进入中断
ldab OSIntNesting
cmpb #$01
bne OSTickISR1
ldy OSTCBCur ;将任务控制块堆栈指针指向该堆栈
sts 0,y
OSTickISR1:
bset CRGFLG_RTIF,#128 ;清除中断标志
call OSTimeTick
cli
call OSIntExit ;出中断
;相关寄存器出栈
pula
staa PPAGE
pula
staa RPAGE
pula
staa EPAGE
pula
staa GPAGE
rti
头文件INCLUDE.H和配置文件OS_CFG.H的完善
用户应在头文件中包含OS_CFG.H,OS_CPU.H,uCOS_II.H以及编译器相关库文件,同时需在OS_CFG.H中配置用户所需的各项应用,以精简内核,优化系统。
移植代码的测试
软件测试在软件的开发中占有极其重要的地位,对uC/OS-II移植后的代码测试步骤如下:
1、编译器编译通过
2、OSTaskStkInit()和OSStartHighRdy()的测试
运行/不运行测试法,先关闭目标系统上的发光二极管(LED),再由OS_TaskIdle()翻转LED状态。如果OSTaskStkInit()和OSStartHighRdy()函数正常,可见LED一直亮着,并可用示波器观测到50%占空比方波。
3、OSCtxSw()的测试
运行/不运行测试法,再对OSTaskStkInit()和OSStartHighRdy()的检测 后,创建一个测试任务,并在创建任务前关闭LED。在测试任务中并不打开系统时钟中断,且仅仅无休止的等待一段时间。此时OS_TaskIdle()仍旧翻转LED状态。如果OSCtxSw()正确,LED将点亮。示波器上可观察到占空比恒定的方波。
4、OSTickISR()和OSIntCtxSw()的测试
此时并不需要OS_TaskIdle()任务,并在创建测试任务前关闭LED,在测试任务中初始化并打开时钟节拍中断,并在任务中先延时一段时间,再翻转LED状态。若LED能在正确的延时时间间隔里闪烁,则OSIntCtxSw()和OSTickISR()函数正确。
发表评论 评论 (1 个评论)