uCosii移植51_STC12LE5A60S2



uCosii移植51_STC12LE5A60S2

前言

    这几天花了三天时间,把uCosii移植到了增强版51_STC12LES5A60S2上。很感谢在网上提供相关代码和移植方法的人,让我学到了很多知识,也少走了很多弯路。在这里我把我在移植中遇到的问题和方法记录下来,供大家学习和参考。

    uCosii是实时操作系统,移植性很好可以移植在多种cpu上。移植51作为入门学习很简单。但是普通51的存储空间有限,不能发挥实时操作系统优势,没有使用价值。所以选择增强版51_STC12LES5A60S2是个不错的选择。STC12LES5A60S22KRAM64KROM。而我移植的最小uCosii可以裁剪到5K远远小于64K的存储空间。可见系统可以流畅的运行,并且具有实时操作系统的实用价值。

    在看这篇文档前建议,先看看卢有亮的《嵌入式实时操作系统——uC/OS原理与实践》,学习一下uCosii。大概花一个星期就可以学会这个操作系统。只有了解了uCosii的工作原理,才能发挥它的最大潜力。(百度云盘:http://pan.baidu.com/s/1jGMj7qI

 

正文

  1. 新建一个文件夹,目录解构如下图,其中的STC12C5A.h51单片机的头文件可以直接在提供的文件夹下找到。

  2. keil在该文件夹下新建一个工程,如下图。 这里的单片机可以随便选一个。但是生成的STARTUP.A51可能不能用,可以用提供的STARTUP.A51代替。

  3. 修改Project->Option…下的相关配置,如下图

  4. 添加相关文件到工程中,如下图。需要注意的不要掉了STARTUP.A51os_cpu_a.asm

  5. 移植ucos-II 涉及三个文件OS_CPU.HOS_CPU_A.ASMOS_CPU_C.C,分别作如下修改:

OS_CPU.H:

定义临界段宏

#if      OS_CRITICAL_METHOD == 1

#define  OS_ENTER_CRITICAL()  EA=0   //关中断

#define  OS_EXIT_CRITICAL()   EA=1   //开中断

定义任务切换宏:

定义数据类型:

OS_CPU_C.C:

初始化任务堆栈:

复制代码

OS_STK*OSTaskStkInit (void (*task)(void *pd) reentrant, void *ppdata, OS_STK *ptos,INT16U opt) reentrant

{   

    OS_STK *stk;

 

    ppdata = ppdata;

    opt   = opt;                              //opt没被用到,保留此语句防止告警产生   

    stk   = ptos;                             //用户堆栈最低有效地址

    *stk++ = 15;                                //用户堆栈长度

    *stk++ = (INT16U)task & 0xFF;               //任务地址低8

    *stk++ = (INT16U)task >> 8;                 //任务地址高8   

    *stk++ = 0x0A;                              //ACC

    *stk++ = 0x0B;                              //B

    *stk++ = 0x00;                              //DPH

    *stk++ = 0x00;                              //DPL

    *stk++ = 0x00;                              //PSW

    *stk++ = 0x00;                              //R0

   

    //R3R2R1用于传递任务参数ppdata,其中R3代表存储器类型,R2为高字节偏移,R1为低字节位移。

    //通过分析KEIL汇编,了解到任务的void *ppdata参数恰好是用R3R2R1传递,不是通过虚拟堆栈。

    *stk++ = (INT16U)ppdata & 0xFF;             //R1

    *stk++ = (INT16U)ppdata >> 8;               //R2

    *stk++ = 0x01;                              //R3  因为我用的全是XDATA,所以存储器类型固定为1,见C51.PDF178页说明。

 

    *stk++ = 0x04;                              //R4

    *stk++ = 0x05;                              //R5

    *stk++ = 0x06;                              //R6

    *stk++ = 0x07;                              //R7

                                                //不用保存SP,任务切换时根据用户堆栈长度计算得出。   

    *stk++ = (INT16U) (ptos+MaxStkSize)>> 8;   //?C_XBP 仿真堆栈指针高8

    *stk++ = (INT16U) (ptos+MaxStkSize) &0xFF; //?C_XBP 仿真堆栈指针低8

       

    return ((void *)ptos);

}

复制代码

系统时钟初始化

复制代码

voidInitHardware(void) reentrant //该函数在main函数中在初始化后被调用

{  

    TMOD &= 0xF0;

    TMOD |= 0x01;   //定时器0:模式1(16位定时器),仅受TR0控制;定时器1:波特率发生器

    TH0 = 0xB8;   //定义Tick=50/(0.02/)

    TL0 = 0x00;   //OS_CPU_C.C中定时器中断响应也要设置,OS_CFG.HOS_TICKS_PER_SEC也有关系

    TR0 = 1;

复制代码

OS_CPU_A.ASM

OSStartHighRdy:在OSStart中被调用执行当前优先级最高的就绪任务

OSCtxSw:即OS_TASK_SW()宏,在OS_Sched()函数结束时被调用,完成任务切换;

OSIntCtxSwOSIntExit中被调用,完成中断退出后的任务切换

参考地址:http://www.cnblogs.com/Fredric-2013/archive/2013/02/19/2917805.html

  1. 把所以任务函数设置成reentrant,除了os_cpu_c.c文件下的void OSTickISRuser(void)void UserTickTimer(void)。这两个是时钟中断服务函数,不能设置成重入。

  2. 修改内核文件中头部的包含为

#ifndef __INCLUDES__

#include "source\includes.h"

#endif

并且删除ucos_ii下的#define OS_GLOBALS

防止产生链接时的错误*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS

 

注意os_core.c文件中修改为

#ifndef __INCLUDES__

#define OS_GLOBALS

#include "source\includes.h"

#endif

  1. main文件中编译整个工程。这时会出现错误

    *** ERROR L102: EXTERNAL ATTRIBUTE MISMATCH

    这是因为os_cpu_a.asm文件这的

    EXTRN IDATA (OSTCBCur)

    EXTRN IDATA (OSTCBHighRdy)

    EXTRN IDATA (OSRunning)

    EXTRN IDATA (OSPrioCur)

    EXTRN IDATA (OSPrioHighRdy)

    5个变量在ucos_ii文件中没有定义成idata类型,这5个变量涉及到系统的任务调度所以要定义在内部的ram中。如下图所示

   

  1. 修改os_cfg.h文件中的开关,关闭不用的功能。需要注意的是,可以打开钩子函数的开关,这样可以减少一些编译警告。

     

  2. 回到main函数中编译整个工程,这是会编译通过,但会产生警告

    *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS

    这是因为没有定义了函数没有掉用调用。通过添加条件编译语句,就可以消除这些警告。

    这样可以消除所以的警告和错误,下载到STC12LES5A60S2看到P1.0P1.3轮流闪烁的现象,那么恭喜你,可以享受跑实时操作系统的单片机。把那些繁琐的任务调度都交给操作系统去做。发挥单片机最大的潜能。

 

参考资料:

  1. 卢有亮的《嵌入式实时操作系统——uC/OS原理与实践》

  2. http://www.cnblogs.com/Fredric-2013/archive/2013/02/19/2917805.html

  3. http://www.3edu.net/lw/qrs/lw_46734.html

  4. http://www.eeskill.com/video/id/21184

  5. http://bbs.21ic.com/icview-125696-1-1.html

 

没有更多推荐了,返回首页