登录站点

用户名

密码

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;         /* 无符号位整型变量*/

typedef signed char INT8S;           /* 有符号位整型变量 */

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 个评论)

涂鸦板