原创 ICCAVR下移植于ATMEGA32的UCOSII

2009-9-24 13:54 3130 7 7 分类: MCU/ 嵌入式

  费了九牛二虎之力终于把UCOSII移植到M32上了,似乎没有想怪中那么兴奋,只是感觉轻松了许多,因为原本打算是在三个星期前搞定的,想想根本原因是没有把握好调试程序时的一些细节,为了一些不可能的东西在钻牛角尖....


   计算机网络的老师给我们讲过大部人都是"蜗牛"!?,只有少部分人是"老鹰"......"老鹰"可以一下冲上高空,而"蜗牛"只有慢慢地爬,也可以到达山顶.不过我觉得只要蜗牛掌握了正确的方法或许也有机会变成---老鹰!(也许其他的蜗牛们也是这么想的~~)


   废话少说了.其实正确的写法是uC/OS-II,u就是micro的意思,为了方便均用UCOSII代替,要移植UCOSII必须要知道编译器的堆栈情况.ICCAVR的堆栈指针是向下增长的,堆栈指针指向SRAM的最高地址.其堆栈还分为软堆栈硬堆栈.软堆栈是用于寄存器入栈的,而硬堆栈用于的函数地址进出栈的,函数调用或进出中断函数时会用到.软堆栈实际是分布在硬堆栈的下面.软堆栈用Y寄存器作为指针,硬堆栈用SP为作指针.(不知看懂了没.表达似乎不太好...)其实ICCAVR也附带有移植于M103的UCOSII,不过M103跟M32是有区别的.


   知道了软硬堆栈就好办了,我的程序是从<嵌入式实时操作系统uC/OS-II(第二版)>的实例1直接改过来的,其实例的中8086的SP指针直接用M32的Y寄存器代替,将M32的硬堆栈指针SP保存到软堆栈中,下面是我的一段堆栈初始化的程序:


OS_STK  *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{  
    INT16U tmp;
    INT8U *stk;
    INT8U *hard_stk;  //硬件堆栈指针
    INT16U stk_tmp;  //硬堆栈变量
   opt = opt;  //防止编译器警告
   pdata="pdata";
   stk_tmp=(INT16U)ptos;  //得到硬堆栈的地址
   hard_stk=(INT8U *)ptos;//指向硬堆栈
   stk    = (INT8U *)ptos-40;//指向软堆栈,40为硬堆栈的大小,ICCAVR的help文档上说过,如果函数不是嵌套很大一般用16就够了,这里我用help文档上说的最大的. 
    //函数地址入栈
  tmp = *(INT16U const *)task;//得到函数地址,这里参考了ICCAVR里面自带的M103的UCOSII源文件.
  *hard_stk-- = (INT8U)(tmp); //函数地址入栈
  *hard_stk-- = (INT8U)(tmp>> 8);
  stk_tmp=(INT16U)hard_stk;  //得到硬堆栈的地址
    //Rx入栈
    *stk-- = 0;              
    *stk-- = 1;             
    *stk-- = 2;              
    *stk-- = 3;              
    *stk-- = 4;             
    *stk-- = 5;              
    *stk-- = 6;              
    *stk-- = 7;              
    *stk-- = 8;             
    *stk-- = 9;               
    *stk-- = 10;              
    *stk-- = 11;              
    *stk-- = 12;              
    *stk-- = 13;               
    *stk-- = 14;               
    *stk-- = 15;             
    *stk-- = 16;
    *stk-- = 17;
    *stk-- = 18;              
    *stk-- = 19;                                                                                                                       //为了在OS_CPU_A.S文件上方便一点,R20~R23我设置为编译器不使用,这样似乎有点浪费,读者完可以自己改过来.            
    *stk-- = 24;           
    *stk-- = 25;             
    *stk-- = 26;              
    *stk-- = 27;             
    *stk-- = 30;            
    *stk-- = 31;              
    /*SREG入栈*/
   *stk-- =0x80;                  //PUSH SREG
    /*SP入栈*/
    *stk-- = (INT8U)(stk_tmp);      //sp
    *stk = (INT8U)((stk_tmp)>> 8);  //sp
    return ((OS_STK *)stk);
}


  在OS_CPU.H修改相应的定义:


typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;                    /* Unsigned  8 bit quantity                           */
typedef signed   char  INT8S;                    /* Signed    8 bit quantity                           */
typedef unsigned int   INT16U;                   /* Unsigned 16 bit quantity                           */
typedef signed   int   INT16S;                   /* Signed   16 bit quantity                           */
typedef unsigned long  INT32U;                   /* Unsigned 32 bit quantity                           */
typedef signed   long  INT32S;                   /* Signed   32 bit quantity                           */
typedef float          FP32;                     /* Single precision floating point                    */
typedef double         FP64;                     /* Double precision floating point                    */


typedef unsigned char  OS_STK;        /*堆栈入口为8位  Each stack entry is 8-bit wide             */


#define  OS_CRITICAL_METHOD    1                                                                   #define  OS_ENTER_CRITICAL()   asm("cli") /*关中断*/
#define  OS_EXIT_CRITICAL()    asm("sei")   /*开中断*/


#define  OS_TASK_SW()        OSCtxSw();/*暂时直接用函数代替*/


  


     OS_CPU_A.ASM文件直接改成M32相应的汇编,可参考ATMEGA32的技术文档,当然一些伪指令技术文档里面是没有的,可查找相关的书籍.这里也写出来:              


                                  对寄存器作定义:


                                    TCNT0 = $32;
                                     SREG=$3F;
                                     SPH=$3E;
                                     SPL=$3D;


                                  定义宏:


                      .macro XXX  //XXX宏的名字
                          ;写指令
                      .endmacro  //宏结束
  


  M32我用了定时器0,感觉这个8位的定时器一般会少用.直接用Tools菜单下的,Application Builder来生成定时器的在4M晶振下产生100HZ的初始值,误差为0.2% .


   以下是我在Project option下的设置:


           c0c4fc61-c125-426e-b0bb-9e9914e971ff.jpg


    下面是文件摆放:


           57655538-ae07-4702-8476-70056a02dc95.jpg


     附件是我在ICCAVR下移植的M32的源程序,有兴趣的可以下来看看,关掉了绝大部分的功能......只是建立了两个简单任务,不过要对应上面的两个图设置好,带proteus 7.4 SP3仿真.(点rar图标下载)


                                    https://static.assets-stash.eet-china.com/album/old-resources/2009/9/24/a6cdc4b3-ec64-41b9-a5cf-70d014abdf26.rar 


    下面是PROTEUS仿真图,数码管每两秒加1,LED每一秒变换一次状态.


    点击看大图




PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条