uCOS-II2.86 移植的一点心得

来源:互联网 发布:淘宝上卖家中心在哪里 编辑:程序博客网 时间:2024/05/22 13:28

      uCOS-II是一种十分优秀实时操作系统,其在NASA的认证通过直接说明了其优秀及稳健的性能,同时由于其完全open,所以受到广大开源爱好者的喜爱。uCOS-II简单明了,同时绝大部分代码都采用ANSI C编写(除了与CPU相关代码外),所以学习起来十分容易,是嵌入式学习乃至操作系统学习最好的入门OS之一。

      我主要想讲一下自己最近移植uCOS-II的心得,因为最近也在学习操作系统,所以这段日子对于uCOS-II的学习的确也让我对于操作系统有了一个实际深刻的认识。

      uCOS-II移植其实十分简单。对于一个处理器,需要做的工作只有:修改三个文件――os_cpu_c.c、os_cpu.h、os_cpu_a.asm(ASM文件根据编译器不同而又有一些不同)。

用另一种方式说,需要做的工作就是修改五个函数:

1、os_cpu_c.c:OSTaskStkInit;

2、os_cpu_a.asm:OSStartHighRdy、OSCtxSw、OSIntCtxSw、OSTickISR;

OSTaskStkInit函数是针对CPU压栈的函数,需要模仿出CPU初始化后的寄存器状况。也使需要修改的唯一一个C语言函数。其他的都是汇编函数。

      如果我们可以从uCOS-II官方网站上找到相同CPU或是相似的同一家族的CPU移植代码,那么我们的移植工作将会简单得多。因为至少我们可以只用了解这个处理器的内部结构,而不用细致的了解其汇编指令等很多繁琐而没有意义的事情(有的处理器你可能一辈子不再用它,了解得太细致只是在浪费时间)。
譬如,此次我要做的是将uCOS-II移植到瑞萨M16C/62A上,而官方网站上只有其62P的移植代码,于是乎我就将二者的datasheet在CPU的寄存器、中断部分仔细比对,发现二者区别很小。最大的区别恐怕就在CPU内部寄存器中的INTBL和PC寄存器二者顺序相反吧,这只要在相关部分注意就可以了,所以很容易就搞定了CPU相关代码部分。

总结一下移植中浪费我时间的几个小错误吧,这完全是个人粗心导致的失误:

1、在os_cpu.h文件中需要用宏定义将OS_TASK_SW指向OSCtxSw函数,而我开始像以前一样直接将OSCtxSw函数与0号软终端链接起来,结果发现函数调用不成功。后来直接用宏定义将OS_TASK_SW define为OSCtxSw函数,初步调试通过,即验证OSCtxSw函数正确,但是到后来调用任务的时候却发现任务切换不正常,不得不重新将函数与中断结合起来,当然就不能还是0号中断了,而是改为一个比较保险的软终端,这个问题纠结了很长时间。

2、在看书的时候不仔细直接导致我犯了一个大错误。起初以为task只要是能够达到功能的死循环即可。所以每个task函数都是while(1)或者for(;;;),但是我没有注意到一点就是每个task里面都应该有OSTimeDly()函数,否则将导致任务之间不能跳转。所以最初的实验现象是永远只有一个任务在运行,但是任务不能切换……

3、未注意到版本之间的区别。我们知道在新版本的uCOS-II中,添加了一个文件os_tmr.c,主要是在timer上面做了很大的调整,但是我没有注意到这一点,仍旧按照老版本的方法调试,导致函数调用让我完全不知所措。最后注意到os的源代码的不同,仔细阅读源代码之后知道了其用法,其实如果不需要timer太强大的功能,只要在os_cfg.h文件中将OS_TMR_EN设置为0即可。这在习惯老版本调试方法的同学而言是很好的方法。

 

UCOS-II的移植需要提供2,3个文件分别介绍如下:
一:OS_CPU.H
1 与编译器有关的数据类型
   只是按照不同的编译器编写对应的数据类型的typedef
   对应于ARM7的数据类型的编写如下
typedef unsigned char  BOOLEAN;              /* 布尔变量                                 */
typedef unsigned char  INT8U;                   /* 无符号8位整型变量                        */
typedef signed   char  INT8S;                     /* 有符号8位整型变量                        */
typedef unsigned short INT16U;                 /* 无符号16位整型变量                       */
typedef signed   short INT16S;                   /* 有符号16位整型变量                       */
typedef unsigned int   INT32U;                   /* 无符号32位整型变量                       */
typedef signed   int   INT32S;                     /* 有符号32位整型变量                       */
typedef float          FP32;                           /* 单精度浮点数(32位长度)                 */
typedef double         FP64;                         /* 双精度浮点数(64位长度)                 */
 
   在上面定义的各种数据类型中按照ARM7的堆栈宽度选择INT32U
typedef INT32U         OS_STK;                   /* 堆栈是32位宽度                           */
 
   接下来一部分是为了兼容低版本UCOS的数据类型所编写的代码,在UCOS-II中暂不考虑
 
2 与处理器相关的代码
    先定义中断的实现方式,预先设定的中断方式有三种,在ARM7中设置为方式2
#define     OS_CRITICAL_METHOD     2            /* 选择开、关中断的方式 */
 
    接下来的一段是我暂时还没有完全搞懂的一部分,只知道是设定了12个软件中断的函数,当调用这些函数之前都会执行对应中断号的事情。。具体的看到后面应该能完全搞懂软件中断的实现方式,该段代码在后面的文件中会有具体的解释,这里暂时不看
    定义堆栈的生长方式,ARM7内核支持两种生长方式,但是ADS的C语言编译器只支持从上往下的生长方式,因此:
#define OS_STK_GROWTH    1                      /*  堆栈是从上往下长的,0-从下往上的生长方式         */
 
    最后几行分别定义了用户模式01和系统模式1f以及IRQ中断禁止的指令80三个立即数,方便调用。