搜索
bottom↓
楼主: rainyss

给51 DIY超轻量级多任务操作系统

  [复制链接]

出0入0汤圆

发表于 2008-12-9 13:37:07 | 显示全部楼层
谢谢楼主。



对 了解 操作系统 很有帮助。





本贴被 michaelc21 编辑过,最后修改时间:2008-12-09,18:07:45.

出0入0汤圆

 楼主| 发表于 2008-12-4 11:31:42 | 显示全部楼层
比较接近了.监听就意味着挂起.

操作系统里有"事件"和"锁"的概念.

当事件未发生时,监听进程读取共享锁被挂起.当底层程序(例如中断)发现指定的动作发生时,比如串口数据到达时,底层程序会将数据以事件(有时也叫消息或邮件)的形式唤醒监听进程.



在我写的例子中没有使用锁,而是用了挂起功能.消息是用唤醒功能完全的.当然,了解了原理则区别不大.

出0入0汤圆

发表于 2008-10-18 01:15:42 | 显示全部楼层
学习中。。。。。。。。。。

出0入0汤圆

发表于 2008-9-26 23:42:34 | 显示全部楼层
为每个任务定义一字节计数器: 

unsigned char idata task_sleep[MAX_TASKS];//任务睡眠定时器 



该计数器会在每次定时器中断时减1(除非它的值为0,或为0xff) 

void clock_timer(void) interrupt 1 using 1 

{ 



... 

        //任务延迟处理 

        i = MAX_TASKS; 

        p = task_sleep;  

        do{ 

                if(*p != 0 && *p != -1)//不为0,也不为0xff,则将任务延时值减1.为0xff表示任务已挂起,不由定时器唤醒 

                        (*p)--; 

                p++; 

        }while(--i); 

} 



相关宏: 

task_sleep(timer) 延时timer个定时器中断周期.取值0~254



楼主能否对计数器延时分析下吗,我怎么感觉你所写的计数器延时程序,为每个任务的延时是一样的,并且同时进行,每个中断周期同时轮次减1,这样延时准确吗

出0入168汤圆

发表于 2008-10-13 16:48:48 | 显示全部楼层
谢谢,学习了。

出0入0汤圆

发表于 2008-10-13 16:45:54 | 显示全部楼层
原来协作式“操作系统”没人说?曾今这个论坛似乎有人对“协作式”很不屑的。。。

其实8位单片机由于受ram限制,很合适协作式,根本不合适用 抢占式。

而用了“操作系统”的好处当然是思路清晰明了,编程方便。



既然这样,我发个自己在用的一个 协作式..... 标准C写的。不管51或AVR都能用的





/* ======================  I N C L U D E   F I L E  ========================= */

#include  "EZSYS_KERNEL.h"



/* ======================  M A C R O   D E F I N E  ========================= */

#if ((SYSTEM_TASK_NUM == 0) || (SYSTEM_TASK_NUM> 256))         // 这个是系统任务数判断,在h文件中宏定义一下就OK了

  #error "SYSTEM_TASK_NUM error!!!"

#endif



/* ======================  G L O B A L E   V A R I A B L E  ================= */



/* ======================  S T A T I C   G L O B A L E   V A R I A B L E  === */

static struct _ezsys_task_struct                          // 任务数*4 就是该 协作式....要掉的ram

{

  void (*taskPtr)(void);                                                        // 函数指针

  U16  delayTimer;                                                              // 延时服务用

}

ezSys[ SYSTEM_TASK_NUM ];



/* ======================  S T A T I C   F U N C T I O N  =================== */







/* -----------------------------------------------------------------------------

 * Function Name    : SIGNAL(SYSTEM_TIMER_VECTOR)

 * Description      : 系统定时周期中断函数

 *

 * Input  Parameter : No Parameter.

 * Output Parameter : No Parameter.

 * Global Parameter : No Parameter.

 * -------------------------------------------------------------------------- */

SIGNAL(SYSTEM_TIMER_VECTOR)            // 系统定时周期,主要用来计数delayTimer的,顺便给了个定时服务函数

{ 

  U08 i;



  ReloadSystemTimerCounter();                                                   // 重新载入定时器值



  for (i=0; i < SYSTEM_TASK_NUM; i++)

  {

    if (ezSys.delayTimer) ezSys.delayTimer--;

  }



  SystemTimerServe();                                                           // 系统定时周期服务函数

}



/* -----------------------------------------------------------------------------

 * Function Name    : main()

 * Description      : 主函数

 *

 * Input  Parameter : No Parameter.

 * Output Parameter : No Parameter.

 * Global Parameter : Easy System 的全局变量。

 * -------------------------------------------------------------------------- */

void main(void)

{

  U08 i;



  CLI();

  for (i=0; i < SYSTEM_TASK_NUM; i++)

  {

    ezSys.taskPtr = 0;

    ezSys.delayTimer = 0;

  }

  SystemInitServe();                                                            // 初始化服务函数

  WatchDogEnable();                                                             // 使能看门狗



  while(1)                                                                      // 系统调度

  {

    for (i=0; i < SYSTEM_TASK_NUM; i++)      // 有人说这就是个超循环,前后台的任务,怎么能称为操作系统?

                                             // 答对了,这就是个超循环调度。是不是操作系统我无所谓,不就个名称么,

                                             // 用着方便合适就好了,在嵌入式世界,只有最合适的,没有最好的!!!!

    {

      CLI();

      if ((ezSys.taskPtr !=0 ) && (ezSys.delayTimer == 0))  // 这一版本没有增加优先级,不符合执行条件的直接下一任务

      {

        SEI();

        ezSys.taskPtr();                                                     // 延时时间到,运行任务

      }

      SEI();

    }

  }

}



/* -----------------------------------------------------------------------------

 * Function Name    : TaskAdd()

 * Description      : 添加一个系统任务

 *

 * Input  Parameter : funPtr    -- 要创建的函数。

 *                    delayTime -- 任务延时运行的时间。

 * Output Parameter : No Parameter.

 * Global Parameter : Easy System的全局变量。

 * -------------------------------------------------------------------------- */

void TaskAdd(void (*funPtr)(void), U16 delayTime)

{

  U08 i;



  for (i=0; i < SYSTEM_TASK_NUM; i++)                                           // 检查任务是否已存在

  {

    if (ezSys.taskPtr == funPtr)

    {

      Assert("TaskExist");

      return;

    }

  }



  for (i=0; i < SYSTEM_TASK_NUM; i++)                                           // 添加任务

  {

    if (ezSys.taskPtr == 0)

    {

      CLI();

      ezSys.taskPtr = funPtr;

      ezSys.delayTimer = delayTime;

      SEI();

      return;

    }

  }



  Assert("TaskFull");

}



/* -----------------------------------------------------------------------------

 * Function Name    : TaskDel()

 * Description      : 删除一个系统任务.

 *

 * Input  Parameter : funPtr -- 要删除的函数。

 * Output Parameter : No Parameter.

 * Global Parameter : Easy System的全局变量。

 * -------------------------------------------------------------------------- */

void TaskDel(void (*funPtr)(void))

{

  U08 i;



  for (i=0; i < SYSTEM_TASK_NUM; i++)

  {

    if (ezSys.taskPtr == funPtr)

    {

      CLI();

      ezSys.taskPtr = 0;

      ezSys.delayTimer = 0;

      SEI();

      return;

    }

  }

}



/* -----------------------------------------------------------------------------

 * Function Name    : TaskDelay()

 * Description      : 延时运行一个任务.

 *

 * Input  Parameter : funPtr    -- 要延时运行的函数。

 *                    delayTime -- 任务延时运行的时间。

 * Output Parameter : No Parameter.

 * Global Parameter : Easy System的全局变量。

 * -------------------------------------------------------------------------- */

void TaskDelay(void (*funPtr)(void), U16 delayTime)

{

  U08 i;



  for (i=0; i < SYSTEM_TASK_NUM; i++)

  {

    if (ezSys.taskPtr == funPtr)

    {

      CLI();

      ezSys.delayTimer = delayTime;

      SEI();

      return;

    }

  }

}







/* ======================  T H E   E N D  =================================== */

出0入0汤圆

发表于 2008-10-13 16:31:03 | 显示全部楼层
关注

出0入0汤圆

发表于 2008-10-13 14:59:06 | 显示全部楼层
确实是好贴啊,现在正在学rtx51,看完之后收获良多啊,有没有专门研究51嵌入式系统的群啊,要是有的话,加我,250733345,要是没有的话,我可以建一个,希望大家顶一下

出0入0汤圆

发表于 2008-10-13 14:31:04 | 显示全部楼层
怎么好的东西

不能不说酷~

严重支持~

出0入0汤圆

发表于 2008-10-13 12:22:51 | 显示全部楼层
顶 慢慢看 好东西

出0入0汤圆

发表于 2008-10-13 09:17:24 | 显示全部楼层
好贴,mark

出0入0汤圆

发表于 2008-10-13 08:46:18 | 显示全部楼层
好贴,学习了

出0入0汤圆

发表于 2008-10-12 22:34:54 | 显示全部楼层
不错,好东西!

出0入0汤圆

发表于 2008-10-12 11:02:40 | 显示全部楼层
不错!

出0入0汤圆

发表于 2008-10-11 17:47:14 | 显示全部楼层
记号

出0入0汤圆

发表于 2008-10-11 16:36:30 | 显示全部楼层
看来我现在才刚接触单片机看这个,有些头晕!

出0入0汤圆

发表于 2009-3-24 09:06:22 | 显示全部楼层
楼上的 不能以往的循环延时,这样肯定会错过扑捉的机会
要把任务让出去,给其他任务的执行,通过执行其他的任务的时间差来达到延时的效果,

出0入0汤圆

发表于 2009-3-25 21:06:29 | 显示全部楼层
楼主好久没出现了

出0入0汤圆

发表于 2009-3-26 17:30:38 | 显示全部楼层
能不能用时间片的形式切换任务?

出0入0汤圆

 楼主| 发表于 2009-3-27 02:54:12 | 显示全部楼层
【215楼】 lrxgr
积分:34
派别:
等级:------
来自:
有个很低级的问题,如果执行第一任务里有一个延时,那么延时还没到达是,切换到第二个任务是,这时第一个任务的延时到达,cpu是不是就错过了一次捕捉延时的机会??

   



这个问题并不低级.这里头有个很重要的概念,就是总任务周期时间:

当任一任务暂时放弃CPU后,在最坏的情况下CPU要多久才能回到该任务.

最简单的计算方法是将每一个任务的最大执行时间加起来,设法让该时间不超过任意一个任务所允许的最大延迟.当然,这种方法太浪费了,但可以保证绝对有效.经验多了以后再去推算动态情况下如何保证每个任务都不会错过执行时机.

出0入0汤圆

发表于 2009-3-28 00:08:23 | 显示全部楼层
不顶不行啊

出0入0汤圆

发表于 2009-3-28 13:12:23 | 显示全部楼层
这块砖太有分量了,真是一砖激起千层浪

出0入0汤圆

发表于 2009-3-28 15:31:02 | 显示全部楼层

出0入0汤圆

发表于 2009-3-28 16:24:58 | 显示全部楼层
CPU的控制权需要一个任务执行完后再交给下一个任务,这样的操作系统我觉得跟顺序执行没什么区别。

出0入0汤圆

发表于 2009-3-29 10:21:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-4-6 15:11:36 | 显示全部楼层
我的感觉是如果顺序执行的速度够快,不影响实时操作的相应,还是采用顺序执行的方式好些,不过各有优缺点。最适合的才是最好的。楼主给出的是一种思路和代码的实现方式,采用何种架构是你自己的问题。

出0入0汤圆

 楼主| 发表于 2009-4-8 03:11:40 | 显示全部楼层
楼上精辟.不要用画圈把自已困住才是正道.

出0入0汤圆

发表于 2009-4-10 17:48:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-4-10 18:53:15 | 显示全部楼层
其实要一个单片机做很多任务的话不应该有100uS以上的延时的。最好是没有延时,除非是发送串行为调速率延时5uS以内。
像遥控红外的发射和接收速率很低就不能用延时等待的方式,那样造成有些响应慢,除非你加很多专用的硬件资源。

出0入0汤圆

发表于 2009-4-10 23:47:19 | 显示全部楼层
支持

出0入0汤圆

发表于 2009-4-14 16:53:57 | 显示全部楼层
MARK,MARK!!!

出0入0汤圆

发表于 2009-4-15 10:57:45 | 显示全部楼层
好贴,MARK 一下呵呵

出0入0汤圆

发表于 2009-4-17 16:09:12 | 显示全部楼层
顶 有汇编的吗? 是不是要了C 才考虑系统这个问题呢

出0入0汤圆

发表于 2009-4-17 17:21:23 | 显示全部楼层
好贴,顶呀!

出0入0汤圆

发表于 2009-4-19 22:05:01 | 显示全部楼层
/*

简单的多任务操作系统

其实只有个任务调度切换,把说它是OS有点牵强,但它对于一些简单的开发应用来说,简单也许就是最好的.尽情的扩展它吧.别忘了把你的成果分享给大家.

这是一个最简单的OS,一切以运行效率为重,经测试,切换一次任务仅20个机器周期,也就是在标准51(工作于12M晶振)上20uS.
而为速度作出的牺牲是,为了给每个任务都分配一个私有堆栈,而占用了较多的内存.作为补偿,多任务更容易安排程序逻辑,从而可以节省一些用于控制的变量.
任务槽越多,占用内存越多,但任务也越好安排,以实际需求合理安排任务数目.一般来说,4个已足够.况且可以拿一个槽出来作为活动槽,换入换入一些临时任务.

task_load(函数名,任务槽号)
装载任务

os_start(任务槽号)
启动任务表.参数必须指向一个装载了的任务,否则系统会崩溃.

task_switch()
切换到其它任务



.编写任务函数注意事项:
KEIL C编译器是假定用户使用单任务环境,所以在变量的使用上都未对多任务进行处理,编写任务时应注意变量覆盖和代码重入问题.

1.覆盖:编译器为了节省内存,会给两个没用调用关系的函数分配同一内存地址作为变量空间.这在单任务下是很合理的,但对于多任务来说,两个进程会互相干扰对方.
解决的方法是:凡作用域内会跨越task_switch()的变量,都使用static前辍,保证其地址空间分配时的唯一性.

2.重入:重入并不是多任务下独有的问题,在单任务时,函数递归同样会导致重入,即,一个函数的不同实例(或者叫作"复本")之间的变量覆盖问题.
解决的方法是:使用reentrant函数后辍(例如:void function1() reentrant{...}).当然,根本的办法还是避免重入,因为重入会带来巨大的目标代码量,并极大降低运行效率.

3.额外提醒一句,在本例中,任务函数必须为一个死循环.退出函数会导致系统崩溃.




.任务函数如果是用汇编写成或内嵌汇编,切换任务时应该注意什么问题?

由于KEIL C编译器在处理函数调用时的约定规则为"子函数有可能修改任务寄存器",因此编译器在调用前已释放所有寄存器,子函数无需考虑保护任何寄存器.
这对于写惯汇编的人来说有点不习惯: 汇编习惯于在子程序中保护寄存器.
请注意一条原则:凡是需要跨越task_switch()的寄存器,全部需要保护(例如入栈).根本解决办法还是,不要让寄存器跨越任务切换函数task_switch()
事实上这里要补充一下,正如前所说,由于编译器存在变量地址覆盖优化,因此凡是非静态变量都不得跨越task_switch().


任务函数的书写:
void 函数名(void){//任务函数必须定义为无参数型
while(1){//任务函数不得返回,必须为死循环
        //....这里写任务处理代码
         
        task_switch();//每执行一段时间任务,就释放CPU一下,让别的任务有机会运行.
}
}


任务装载:
task_load(函数名,任务槽号)

装载函数的动作可发生在任意时候,但通常是在main()中.要注意的是,在本例中由于没考虑任务换出,
所以在执行os_start()前必须将所有任务槽装满.之后可以随意更换任务槽中的任务.



启动任务调度器:
os_start(任务槽号)

调用该宏后,将从参数指定的任务槽开始执行任务调度.本例为每切换一次任务需额外开销20个机器周期,用于迁移堆栈.
*/
#include"iom8v.h"
#include"fun.h"
//#include"def.h"
//#include"var.h"
char led;
char d8[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char seg[5];
char b[10];

#define MAX_TASKS 2
#define MAX_TASK_DEP 35
/*============================以下为任务管理器代码============================*/
//任务槽个数.在本例中并未考虑任务换入换出,所以实际运行的任务有多少个,就定义多少个任务槽,不可多定义或少定义
//任务的栈指针
#define MAX_TASKS 2
#define MAX_TASK_DEP 35
unsigned int task_sp[MAX_TASKS];
        //最大栈深.最低不得少于2个,保守值为12.                                                                        

                                                //预估方法:以2为基数,每增加一层函数调用,加2字节.如果其间可能发生中断,则还要再加上中断需要的栈深.
                                                //减小栈深的方法:1.尽量少嵌套子程序 2.调子程序前关中断.
unsigned char task_stack[MAX_TASKS][MAX_TASK_DEP];//任务堆栈.

unsigned char task_id;//当前活动任务号
//任务切换函数(任务调度器)
void task_switch(){
        asm("push r0");
        asm("push r1");
        asm("push r2");
        asm("push r3");
        asm("push r4");
        asm("push r5");
        asm("push r6");
        asm("push r7");
        asm("push r8");
        asm("push r9");
        asm("push r10");
        asm("push r11");
        asm("push r12");
        asm("push r13");
        asm("push r14");
        asm("push r15");
        asm("push r16");
        asm("push r17");
        asm("push r18");
        asm("push r19");
        asm("push r20");
        asm("push r21");
        asm("push r22");
        asm("push r23");
        asm("push r24");
        asm("push r25");
        asm("push r26");
        asm("push r27");
        asm("push r28");
        asm("push r29");
        asm("push r30");
        asm("push r31");
        asm("in r16,0x3f");
        asm("push r16");
        task_sp[task_id] = SP;
        task_id++;
        if(task_id == MAX_TASKS)task_id = 0;
        SP = task_sp[task_id];
        asm("pop r16");
        asm("out 0x3f,r16");
        asm("pop r31");
        asm("pop r30");
        asm("pop r29");
        asm("pop r28");
        asm("pop r27");
        asm("pop r26");
        asm("pop r25");
        asm("pop r24");
        asm("pop r23");
        asm("pop r22");
        asm("pop r21");
        asm("pop r20");
        asm("pop r19");
        asm("pop r18");
        asm("pop r17");
        asm("pop r16");
        asm("pop r15");
        asm("pop r14");
        asm("pop r13");
        asm("pop r12");
        asm("pop r11");
        asm("pop r10");
        asm("pop r9");
        asm("pop r8");
        asm("pop r7");
        asm("pop r6");
        asm("pop r5");
        asm("pop r4");
        asm("pop r3");
        asm("pop r2");
        asm("pop r1");
        asm("pop r0");
        asm("ret");
        //return;
}
void delay(long c)
{
          long i;
          for(i=0;i<c;i++)
         {
          asm("nop");
          asm("nop");
          asm("nop");
          asm("nop");
          asm("nop");
          asm("nop");
          asm("nop");           
         }
}
//任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任务,则原任务丢失,但系统本身不会发生错误.
void task_load(void(*task)(),unsigned char tid)
{
         
        task_sp[tid] = (unsigned int)(task_stack[tid]-1);
        task_stack[tid][MAX_TASK_DEP -1] = (unsigned char)(((unsigned int)task)&0xFF);
        task_stack[tid][MAX_TASK_DEP -2] = (unsigned char)(((unsigned int)task)>>8);
}

//从指定的任务开始运行任务调度.调用该宏后,将永不返回.
//#define os_start(tid) {task_id = tid,SP = task_sp[tid];return;}
void os_start(unsigned char tid)
{
          task_id = tid;
         SP = task_sp[tid]+MAX_TASK_DEP - 2;
         return;
}
/*============================以下为测试代码============================*/
void task1(void)
{
          for(;;)
         {
                  PORTC=0x10;
                delay(20000);
                task_switch();
         }
}


void task2(void)
{
          for(;;)
         {
                  PORTC=0x20;
                delay(30000);
                task_switch();
         }
}



void main(){
        //在这个示例里并没有考虑任务的换入换出,所以任务槽必须全部用完,否则系统会崩溃.
        //这里装载了三个任务,因此在定义MAX_TASKS时也必须定义为3
         DDRD=0Xff;
            DDRC=0x07;

        task_load(task1, 0);//将task1函数装入0号槽
        task_load(task2, 1);//将task2函数装入1号槽


        os_start(0);//启动任务调度,并从0号槽开始运行.参数改为1,则首先运行1号槽.
                                //调用该宏后,程序流将永不再返回main(),也就是说,该语句行之后的所有语句都不被执行到.
}
编译器是ICC ,MCU是mega8;这个系统有点问题,就是 在使用task_load(task1, 0)将task1函数装入0号槽时,task1 的值并不是任务1的入口地址,经调试(unsigned int)task1的值是40(0x28);各位大侠,帮帮忙,看看问题出在哪了?小弟不胜感激!!!!!!!!!!!!

出0入0汤圆

 楼主| 发表于 2009-4-22 01:00:10 | 显示全部楼层
AVR上已经有很多现成的轻量系统,没必要自已做.
你把我专为51写的系统拿到AVR上用是不行的,不是改一点代码就可以的,而是连设计理念都不能在AVR上成立.
当然,你的尝试是对的,不过写一个操作系统需要对该CPU和编译器都十分了解,你需要先练练功底,可以找一两个小OS来研究一下.坛里有一篇阿莫转载的AVR OS DIY的文章,但我找不着了.

出0入0汤圆

发表于 2009-4-24 08:46:17 | 显示全部楼层
顶个。 。。呵呵。。!!!

出0入0汤圆

 楼主| 发表于 2009-4-24 23:41:49 | 显示全部楼层
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=574348&bbs_page_no=1&search_mode=4&search_text=rainyss&bbs_id=9999

找着了.234楼想做AVR的OS,可以去那里看.

出0入0汤圆

发表于 2009-4-25 17:41:27 | 显示全部楼层
顶,占位学习

出0入0汤圆

发表于 2009-4-25 18:26:48 | 显示全部楼层
好贴

出0入0汤圆

发表于 2009-4-26 23:24:17 | 显示全部楼层
不怎么看得懂!你说用延时时就调用任务转换器?
那我不用延时程序,用其他程序作为延时不就行了吗?

出0入0汤圆

 楼主| 发表于 2009-4-28 00:20:26 | 显示全部楼层
那样的话所有的任务都慢下来了.

出0入0汤圆

发表于 2009-5-10 19:37:07 | 显示全部楼层
收藏备用。谢谢

出0入0汤圆

发表于 2009-5-10 21:33:22 | 显示全部楼层
好贴留名

出0入0汤圆

发表于 2009-5-11 11:01:53 | 显示全部楼层
留名,以备后用

出0入0汤圆

发表于 2009-5-11 11:10:58 | 显示全部楼层
好贴啊
慢慢学习

出0入0汤圆

发表于 2009-5-11 17:33:37 | 显示全部楼层
我没标记过?

出0入0汤圆

发表于 2009-5-11 21:21:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-5-18 08:55:01 | 显示全部楼层
好贴,顶!

出0入0汤圆

发表于 2009-5-20 16:52:18 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-5-20 20:21:47 | 显示全部楼层
m

出0入0汤圆

发表于 2009-5-21 17:26:32 | 显示全部楼层
好贴

出0入0汤圆

发表于 2009-5-22 10:45:36 | 显示全部楼层
太强悍了  标记慢慢看

出0入0汤圆

发表于 2009-5-24 03:03:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-5-24 10:22:53 | 显示全部楼层
巨强,收了学习!!

出0入0汤圆

发表于 2009-5-27 09:17:26 | 显示全部楼层
收藏了

出0入0汤圆

发表于 2009-5-27 10:44:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-5-27 15:22:25 | 显示全部楼层
认真看下

出0入0汤圆

发表于 2009-5-27 16:25:22 | 显示全部楼层
顶到飞高。。

出110入26汤圆

发表于 2009-5-28 08:46:08 | 显示全部楼层
怎样收藏

出0入0汤圆

发表于 2009-5-30 21:14:53 | 显示全部楼层
强大,非常好,对我以后做的操作系统很有帮助

出0入0汤圆

发表于 2009-5-30 21:29:50 | 显示全部楼层
感谢楼主,留个标记日后必回!

出0入0汤圆

发表于 2009-6-2 00:15:33 | 显示全部楼层
谢谢,学习中!!

出0入0汤圆

发表于 2009-6-2 10:44:08 | 显示全部楼层
又把它顶出来,只是现在我添加讨论,不知道作者能不能回应。

LZ的思路我大体看明白,单对任务切换这一块,阐述一些我的看法。

你所讲的任务切换迅速,是建立在一个基础上的:为每个任务保存一个独立的堆栈空间。
这个类同于ucos,  ucos对每个任务指定独立大小的堆栈空间。
而51的堆栈处理空间只有内部的RAM区,
这样,ucos移植到51,任务切换的最大的瓶颈就是将每个任务的堆栈从片内搬到片外,又从片外搬到片内。

你的所有任务堆栈都分配在片内RAM上。而且每个堆栈空间独立。
如果任务多了,比如16个任务(RTX51 Tiny支持的最大数量),你的堆栈消耗,在51上是不能满足的。

每个任务的堆栈空间都有两部分,一部分是用掉的,程序调用的压栈,变量的压栈,都是有效数据。
一部分是空白部分,用于新的程序压栈,新的变量压栈。提供为以后的应用。

Tiny的所有任务的堆栈空白部分是共享的。用掉部分是独立的。所以它的内部ram消耗程度是很小的。
由此带来的在任务切换时候的数据搬运,占用了一些系统时间。但这个时间是值得的。

所以,LZ推荐你的思路时候,提出的与Tiny的对比并不是很合适。

出0入0汤圆

发表于 2009-6-2 11:36:27 | 显示全部楼层
很难超越RTX TINY。

出0入0汤圆

发表于 2009-6-5 09:05:12 | 显示全部楼层
对于128byte的51,运行OS确实太勉强了。不光RAM少,连ROM也是个问题。在这种资源下,MCU都不可能做太多事情的。

    在我自己做的几个案子中,最低选择就是有256byte的RAM,就足以把自己的51微内核放进去,而且也具备额uCos的基本特点。
虽然51的堆栈处理空间只有内部RAM,但是可以处理到256byte。恰好就是多这128byte,就可以保存寄存器和任务状态。
   
    至于速度问题,现在的51都可以到1T的速度,用个24M的晶振难道还不够快吗?自己曾经这样同时驱动一个8位的数码管(而且还是
用595扫描驱动)和一个192*64的点阵液晶屏显示DS1302的时间(还用的外部内存映射的方式),任务的切换速度达到800Hz(为了动态扫描),MCU的空闲时间依然很富裕。
    自从用上了OS之后,就如以前看到一个网友这样说过。“当你使用过OS之后,就再也不想用以前的顺序执行方式了”

出0入0汤圆

发表于 2009-6-6 21:23:51 | 显示全部楼层
标记,慢慢消化

出0入0汤圆

发表于 2009-6-6 22:48:58 | 显示全部楼层
看完了,学了很多东西,谢谢LZ

出0入0汤圆

 楼主| 发表于 2009-6-7 23:38:33 | 显示全部楼层
to 【263楼】 wolf11_1234
积分:59
派别:
等级:------
来自:



以空间换时间.

出0入0汤圆

发表于 2009-6-8 14:54:40 | 显示全部楼层
基本功不行,看了两层楼,看的头晕。

出0入0汤圆

发表于 2009-6-14 13:03:17 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-6-16 08:51:45 | 显示全部楼层
学学

出0入0汤圆

发表于 2009-6-17 08:49:15 | 显示全部楼层
学习,不过得先看看,还没弄明白.谢谢!

出0入0汤圆

发表于 2009-6-17 22:29:42 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-7-2 16:42:41 | 显示全部楼层
标个个个记

出0入0汤圆

发表于 2009-7-2 17:07:52 | 显示全部楼层
好文,谢谢分享!

出0入0汤圆

发表于 2009-7-4 21:09:29 | 显示全部楼层
强贴留名

出0入0汤圆

发表于 2009-7-11 15:39:37 | 显示全部楼层
学习ing。。。。。。。。。。。

出0入0汤圆

发表于 2009-7-12 12:25:54 | 显示全部楼层
都一年了,这个贴都不沉~~牛!!

出0入0汤圆

发表于 2009-7-12 17:55:15 | 显示全部楼层
太强了

出0入0汤圆

发表于 2009-7-12 18:20:28 | 显示全部楼层
学习学习再学习

出0入0汤圆

发表于 2009-7-21 17:51:13 | 显示全部楼层
寄存器为什么不入堆栈呀?
不会丢失数据吗?

出0入0汤圆

发表于 2009-7-27 00:19:34 | 显示全部楼层
MARK下明天继续看

出0入0汤圆

发表于 2009-7-27 00:30:37 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-7-27 09:08:26 | 显示全部楼层
maRK好贴!!

出0入0汤圆

 楼主| 发表于 2009-7-28 00:15:29 | 显示全部楼层
【281楼】 he306
积分:1
派别:
等级:------
来自:
寄存器为什么不入堆栈呀?
不会丢失数据吗?  


这就是技巧了。放弃寄存器入栈可以极大地提高任何切换的速度以及节省大量的堆栈空间,代价是使用局部变量时不作用域内不得跨越任务。

出0入0汤圆

发表于 2009-8-6 08:48:55 | 显示全部楼层
太好了,晚上回去研究。

出0入0汤圆

发表于 2009-8-12 23:29:34 | 显示全部楼层
顶顶

出0入0汤圆

发表于 2009-8-15 09:58:37 | 显示全部楼层
这就是我所期望的好帖,正在研究51的操作系统。

出0入0汤圆

发表于 2009-8-17 16:35:30 | 显示全部楼层
顶一下!

出0入0汤圆

发表于 2009-8-19 16:55:19 | 显示全部楼层
厉害!

出0入0汤圆

发表于 2009-8-19 20:55:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-8-19 21:31:51 | 显示全部楼层
看着有点晕,得慢慢消化才行!!

出0入0汤圆

发表于 2009-8-19 22:23:09 | 显示全部楼层
现在还看不懂,先记号下来。

出0入0汤圆

发表于 2009-8-19 23:07:14 | 显示全部楼层
MARK一下 高深的东西不敢触碰

出0入0汤圆

发表于 2009-8-23 17:08:50 | 显示全部楼层
标记一下,以后肯定用的上 ,谢谢!

出0入0汤圆

发表于 2009-8-23 22:47:42 | 显示全部楼层
看了 一些  没有完全看懂
   
  楼主的思想太厉害了
   保存了
  后面漫漫看

出0入0汤圆

发表于 2009-8-23 22:53:28 | 显示全部楼层
标记,呵呵

出0入0汤圆

发表于 2009-8-25 22:41:28 | 显示全部楼层

出0入0汤圆

发表于 2009-8-26 08:46:47 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 08:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表