我爱嵌入式系统

当前位置:首页 > 软件天地 > 业内资讯 > 详细内容
建立一个属于自己的AVR的RTOS(1)
发布时间:2009/10/28  阅读次数:1072  字体大小: 【】 【】【
                                              序
        自从03年以来,对单片机的RTOS的学习和应用的热潮可谓一浪高过一浪.03年,在离开校园前的,非典的那几个月,在华师的后门那里买了本邵贝贝的《UCOSII》,通读了几次,没有实验器材,也不了了之。
        在21IC上,大家都可以看到杨屹写的关于UCOSII在51上的移植,于是掀起了51上的RTOS的热潮。
        再后来,陈明计先生推出的small  rots,展示了一个用在51上的微内核,足以在52上进行任务调度。
        前段时间,在ouravr上面开有专门关于AVR的Rtos的专栏,并且不少的兄弟把自己的作品拿出来,着实开了不少眼界。这时,我重新回顾了使用单片机的经历,觉得很有必要,从根本上对单片机的RTOS的知识进行整理,于是,我开始了编写一个用在AVR单片机的RTOS。
      
        当时,我所有的知识和资源有:  
        Proteus6.7                可以用来模拟仿真avr系列的单片机
        WinAVR  v2.0.5.48    基于GCC  AVR的编译环境,好处在于可以在C语言中插入asm的语句
        mega8    1K的ram有8K的rom,是开发8位的RTOS的一个理想的器件,并且我对它也比较熟悉。
        
        写UCOS的Jean  J.Labrosse在他的书上有这样一句话,“渐渐地,我自然会想到,写个实时内核直有那么难吗?不就是不断地保存,恢复CPU的那些寄存器嘛。”  

        好了,当这一切准备好后,我们就可以开始我们的Rtos  for  mega8的实验之旅了。
      
        本文列出的例子,全部完整可用。只需要一个文件就可以编译了。我相信,只要适当可用,最简单的就是最好的,这样可以排除一些不必要的干扰,让大家专注到每一个过程的学习。
    

第一篇:函数的运行  

                                                                  第一篇:函数的运行

        在一般的单片机系统中,是以前后台的方式(大循环+中断)来处理数据和作出反应的。
        例子如下:
      
        makefile的设定:运行WinAvr中的Mfile,设定如下
        MCU  Type:  mega8
        Optimization  level:  s
        Debug  format  :AVR-COFF
        C/C++  source  file:  选译要编译的C文件

#include  <avr/io.h>
void  fun1(void)
{
    unsigned  char  i=0;
    while(1)
    {
        PORTB=i++;
        PORTC=0x01<<(i%8);
    }
}

int  main(void)
{
    fun1();
}

        首先,提出一个问题:如果要调用一个函数,真是只能以上面的方式进行吗?
        相信学习过C语言的各位会回答,No!我们还有一种方式,就是“用函数指针变量调用函数”,如果大家都和我一样,当初的教科书是谭浩强先生的《C程序设计》的话,请找回书的第9.5节。
        
        例子:用函数指针变量调用函数


#include  <avr/io.h>
void  fun1(void)
{
    unsigned  char  i=0;
    while(1)
    {
        PORTB=i++;
        PORTC=0x01<<(i%8);
    }
}
void  (*pfun)();    //指向函数的指针

int  main(void)
{

    pfun=fun1;        //
    (*pfun)();        //运行指针所指向的函数
}
        
          第二种,是“把指向函数的指针变量作函数参数”
          
#include  <avr/io.h>
void  fun1(void)
{
    unsigned  char  i=0;
    while(1)
    {
        PORTB=i++;
        PORTC=0x01<<(i%8);
    }
}

void  RunFun(void  (*pfun)())    //获得了要传递的函数的地址
{
    (*pfun)();                                  //在RunFun中,运行指针所指向的函数
}

int  main(void)
{
      RunFun(fun1);                        //将函数的指针作为变量传递
        
}

        看到上面的两种方式,很多人可能会说,“这的确不错”,但是这样与我们想要的RTOS,有什么关系呢?各位请细心向下看。

        以下是GCC对上面的代码的编译的情况:
        
        对main()中的RunFun(fun1);  的编译如下
    ldi  r24,lo8(pm(fun1))
    ldi  r25,hi8(pm(fun1))
    rcall  RunFun
        
对void  RunFun(void  (*pfun)())的编译如下
                                /*void  RunFun(void  (*pfun)())*/
                              /*(*pfun)();*/
.LM6:
    movw  r30,r24
    icall
    ret

        在调用void  RunFun(void  (*pfun)())的时候,的确可以把fun1的地址通过r24和r25传递给RunFun()。但是,RTOS如何才能有效地利用函数的地址呢?
我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

51RTOS.com 版权所有  

Copyright 20006-2009 我爱嵌入式 ( 51RTOS.com ) All rights reserved 沪ICP备09080633号