搜索
bottom↓
楼主: rainyss

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

  [复制链接]

出0入0汤圆

发表于 2008-9-10 18:39:57 | 显示全部楼层
看了这才发现之前好多问题没有注意到!

出0入0汤圆

发表于 2008-9-10 23:52:03 | 显示全部楼层
有深度

出0入0汤圆

发表于 2008-9-17 17:27:32 | 显示全部楼层
值得学习!

出0入0汤圆

发表于 2008-9-17 17:55:55 | 显示全部楼层
学习了,

出0入0汤圆

发表于 2008-9-17 18:38:06 | 显示全部楼层
记号一个

出0入0汤圆

发表于 2008-9-18 01:36:54 | 显示全部楼层
引用顶楼



————————————————————————-————————

//任务装入函数

void task_load(unsigned int fn, unsigned char tid){

        task_sp[tid] = task_stack[tid] + 1;

        task_stack[tid][0] = (unsigned int)fn & 0xff;

        task_stack[tid][1] = (unsigned int)fn>> 8;

}

---------------------------------



 在这几句中,第二行右边所得到的是一个地址数据,但这个地址是task_stack这个二维数组的第tid行的第一列的元素的地址。这个地址加载到task_sp[tid]中有什么用呢?是我理解错了?得到第tid行第一列的数据是不是应为*(task_sp[tid]+1)

如果没有理解错,那楼主的这个小系统就有点问题了。。。

这个地址似乎不是一个有用的数据。



请楼主为菜鸟解答。。。在线等。

本贴被 microyao 编辑过,最后修改时间:2008-09-18,01:42:38.

出0入0汤圆

 楼主| 发表于 2008-9-18 06:41:32 | 显示全部楼层
如果有问题还能工作得起来?这可是堆栈,错一丁点都不行的.





本贴被 rainyss 编辑过,最后修改时间:2008-09-18,06:43:18.

出0入0汤圆

 楼主| 发表于 2008-9-18 06:49:27 | 显示全部楼层
//任务装入函数 

void task_load(unsigned int fn, unsigned char tid){ 

        task_sp[tid] = task_stack[tid] + 1; //装入栈指针,该值在切换任务时会加载到SP中



        task_stack[tid][0] = (unsigned int)fn & 0xff; //向私栈中装入任务地址低8位

        task_stack[tid][1] = (unsigned int)fn>> 8; //任务地址高8位

} 



任务切换过程:



call task_switch函数

将SP值保存到task_sp[tid]中

将tid切换到下一个任务

将task_sp[tid]中的值装入SP中

ret from task_switch

出0入0汤圆

发表于 2008-9-18 08:33:01 | 显示全部楼层


出来一个多月了,现在才发现

出0入0汤圆

发表于 2008-9-18 08:52:38 | 显示全部楼层
看来我得实验一下。怎么老感到与我脑中的标准C有冲突。。。

出0入0汤圆

 楼主| 发表于 2008-9-18 09:03:12 | 显示全部楼层
这几句里头没有用到非标准C的句型.

出0入0汤圆

发表于 2008-9-18 09:05:07 | 显示全部楼层
实验证明。我是错的。。。



并己经明白了。谢谢楼主。好长时间没用汇编,要好好复习一下了。。。

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

出0入0汤圆

发表于 2008-9-18 10:35:21 | 显示全部楼层
留名,要细看

出0入0汤圆

发表于 2008-9-19 18:15:57 | 显示全部楼层
好长的资料。 顶了慢慢看

出0入0汤圆

发表于 2008-9-19 21:29:35 | 显示全部楼层
MARKING

出0入0汤圆

发表于 2008-9-21 11:58:47 | 显示全部楼层
好帖!收藏!

本贴被 jjj206 编辑过,最后修改时间:2008-09-21,12:00:11.

出0入0汤圆

发表于 2008-9-25 19:17:36 | 显示全部楼层
向楼主学习!

出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入0汤圆

 楼主| 发表于 2008-9-26 23:49:04 | 显示全部楼层
初值不同.减到零不再减,同时任务恢复正常调度

出0入0汤圆

发表于 2008-10-5 20:37:25 | 显示全部楼层
支持,楼主辛苦了

出0入0汤圆

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

出0入0汤圆

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

出0入0汤圆

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

出0入0汤圆

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

出0入0汤圆

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

出0入0汤圆

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

出0入0汤圆

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

出0入0汤圆

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

不能不说酷~

严重支持~

出0入0汤圆

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

出0入0汤圆

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

出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入168汤圆

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

出0入0汤圆

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

出0入0汤圆

发表于 2008-10-20 00:13:59 | 显示全部楼层
学习中............................

出0入0汤圆

 楼主| 发表于 2008-10-20 12:16:47 | 显示全部楼层
建了个群,4759163,专门用来讨论超轻量OS.

刚建好,目前里面没啥讨论,想加入的话,确认你是否有耐心等着人多起来吧.

出0入0汤圆

发表于 2008-10-22 23:57:12 | 显示全部楼层
迷糊,好象无从下手

出0入0汤圆

发表于 2008-10-30 10:22:31 | 显示全部楼层
学习了

出0入0汤圆

发表于 2008-10-30 11:03:45 | 显示全部楼层
学习中.mark

出0入0汤圆

发表于 2008-10-30 12:54:19 | 显示全部楼层
顶起

出0入0汤圆

发表于 2008-10-30 16:10:33 | 显示全部楼层
看了以上的,,有点晕了,,



感觉有点像那种分别复用的,



不知道高手们能不能解释下以上介绍的与分时复用的有什么区别?



劳烦了,,谢谢

学习了~~

出0入0汤圆

 楼主| 发表于 2008-10-30 21:56:53 | 显示全部楼层
就是分时复用啊.多任务OS,就是制定一种分时复用的规则

本贴被 rainyss 编辑过,最后修改时间:2008-10-30,22:25:56.

出0入0汤圆

发表于 2008-10-31 09:43:03 | 显示全部楼层
顶一个

出0入0汤圆

发表于 2008-10-31 11:23:21 | 显示全部楼层
mark!

出0入0汤圆

发表于 2008-10-31 13:36:00 | 显示全部楼层
楼主好像笔误少了这句:

unsigned char idata task_sp[MAX_TASKS];//任务的栈指针

出0入0汤圆

发表于 2008-10-31 16:01:43 | 显示全部楼层
打上数码标记

出0入0汤圆

发表于 2008-11-4 08:50:25 | 显示全部楼层
回【143楼】 rainyss



谢谢了,,那这样就更好看懂了!



顶起  

出0入0汤圆

 楼主| 发表于 2008-11-4 11:56:10 | 显示全部楼层
【146楼】 xt0320 

积分:6

派别:

等级:------

来自:

 楼主好像笔误少了这句: 

unsigned char idata task_sp[MAX_TASKS];//任务的栈指针  







你看得可真够仔细的.厉害.估计大部分人都没有注意到.

出0入0汤圆

发表于 2008-11-4 12:21:12 | 显示全部楼层
收藏了啊

出0入0汤圆

发表于 2008-11-4 12:22:35 | 显示全部楼层
真的不错,有空仔细看看,mark

出0入0汤圆

发表于 2008-11-7 02:20:26 | 显示全部楼层
好贴,简单通俗易懂,是学习的好材料
头像被屏蔽

出0入0汤圆

发表于 2008-11-7 03:12:54 | 显示全部楼层
【146楼】 xt0320 

积分:6

派别:

等级:------

来自:

 楼主好像笔误少了这句: 

unsigned char idata task_sp[MAX_TASKS];//任务的栈指针  





佩服啊!

出0入0汤圆

 楼主| 发表于 2008-11-9 00:31:28 | 显示全部楼层
【152楼】 gamethink 

积分:1023

派别:

等级:------

来自:

 void task_switch(){ 



        task_sp[task_id] = SP; 



        if(++task_id == MAX_TASKS) 

                task_id = 0; 



        SP = task_sp[task_id]; 

} 



怎么觉得task_sp[task_id] = SP;是完全没有作用的...调试了很多次也没发现具体作用  









你把它删了试试看.

出0入0汤圆

发表于 2008-11-9 01:07:08 | 显示全部楼层
这个RTOS的主要问题就是要限制子程序里的代码不要太长,以防止实时性不够

但一般LCD的显示程序比较长,有无好方法处理

出0入0汤圆

发表于 2008-11-9 15:32:09 | 显示全部楼层
不错,在操作系统下写程序,就是要先把操作系统的思路搞明白了。

出0入0汤圆

 楼主| 发表于 2008-11-9 22:55:08 | 显示全部楼层
【156楼】 robinyuan 



积分:130

派别:

等级:------

来自:

 这个RTOS的主要问题就是要限制子程序里的代码不要太长,以防止实时性不够 

但一般LCD的显示程序比较长,有无好方法处理  







找几个点插入若干task_switch()就行了.

出0入4汤圆

发表于 2008-11-10 15:26:22 | 显示全部楼层
收藏先,,

出0入0汤圆

发表于 2008-11-10 17:51:04 | 显示全部楼层
到这里 就看到了这个好贴子  学习了

出0入0汤圆

发表于 2008-11-10 19:13:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-11-11 22:01:19 | 显示全部楼层
好贴,多谢分享

出0入0汤圆

发表于 2008-11-23 00:04:20 | 显示全部楼层
学习,多谢!

出0入0汤圆

发表于 2008-11-23 01:35:14 | 显示全部楼层
8位机就不用搞操作系统了,

不过要有操作系统的思想。

出0入0汤圆

发表于 2008-11-29 11:33:36 | 显示全部楼层
好贴,学习中~~~~

出0入0汤圆

发表于 2008-11-29 11:54:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-11-29 11:54:43 | 显示全部楼层
很好的学习资料

出0入0汤圆

发表于 2008-12-1 21:15:20 | 显示全部楼层
mark!

出0入0汤圆

发表于 2008-12-1 23:17:58 | 显示全部楼层
好!好,好!!非常好!!!

出0入0汤圆

 楼主| 发表于 2008-12-2 00:38:27 | 显示全部楼层
【171楼】 gamethink 



积分:1057

派别:

等级:------

来自:广州

 LZ,其实一直不太明白"监听进程"的具体意思和作用. 

按我理解,是不是看看另外一个任务是否有被挂起???  

   





得看上下文.有两种可能:

一种是用于监控其它进程的进程,但这种可能性小,"监听"二字用得不规范,应该叫"监控".

"监听进程"通常指的是等待外部触发条件发生的进程.比如等待网络包到达,等待串口数据到达,等待引脚电平翻转.



"监听"二字必定"服务"及"事件"挂勾.每种监听都对应着相应的事务处理.当事件发生时,监听被激活,转入或开启新进程进入事件处理的服务流程,处理完成后回到等待状态.等待过程中监听进程就像一个老式电话局里等待客户请求接线的接线生,所以叫"监听".

本贴被 rainyss 编辑过,最后修改时间:2008-12-02,00:43:47.

出0入0汤圆

发表于 2008-12-2 08:00:51 | 显示全部楼层
太好了!谢谢!

学习中~~~~

出0入0汤圆

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

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

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



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

出0入0汤圆

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



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





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

出0入0汤圆

发表于 2008-12-9 13:49:58 | 显示全部楼层
顶一个

出0入0汤圆

发表于 2008-12-10 16:10:52 | 显示全部楼层
to gamethink:



当task1内调用一个子程序sub1,而sub1内又调用了task_switch时

下面这句就不能删除了:

task_sp[task_id] = SP; 





此时,sub1分享task1的task_id

我写了个小程序已经验证过了



#include <reg52.h>  



#define MAX_TASKS 2       //任务槽个数.必须和实际任务数一至  

#define MAX_TASK_DEP 12   //最大栈深.最低不得少于2个,保守值为12.  

unsigned char task_id;    //当前活动任务号

unsigned char task_sp[MAX_TASKS];  

unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//任务堆栈.  





//任务切换函数(任务调度器)  

void task_switch(){  

        task_sp[task_id] = SP;  



        if(++task_id == MAX_TASKS)  

                task_id = 0;  



        SP = task_sp[task_id];  

}  



//任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任务,则原任务丢失,但系统本身不会发生错误.  

void task_load(unsigned int fn, unsigned char tid){  

        task_sp[tid] = task_stack[tid] + 1;  

        task_stack[tid][0] = (unsigned int)fn & 0xff;  

        task_stack[tid][1] = (unsigned int)fn>> 8;  

}  



//从指定的任务开始运行任务调度.调用该宏后,将永不返回.  

#define os_start(tid) {task_id = tid,SP = task_sp[tid];return;}  







//////////////////////////////////////////////////////////////////////////

void sub1()

{

        unsigned char a,b;

        a++;

        task_switch();

        b++;

}



//////////////////////////////////////////////////////////////////////////



/*============================以下为测试代码============================*/  



void task1(){  

        static unsigned char x,y,z;  

        while(1){  

                x++;  

                task_switch();//编译后在这里打上断点  

                y++; 

             sub1(); 

                task_switch();//编译后在这里打上断点  

                z++;  

                task_switch();//编译后在这里打上断点  

        }  

}  



void task2(){  

        static unsigned char l,m,n;  

        while(1){  

                l+=2;  

                task_switch();//编译后在这里打上断点  

                m+=2;  

                task_switch();//编译后在这里打上断点  

                n+=2;  

                task_switch();//编译后在这里打上断点  

        }  

}  



void main(){  

        //这里装载了两个任务,因此在定义MAX_TASKS时也必须定义为2  

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

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

        os_start(0);  

}  



本贴被 kejian2000 编辑过,最后修改时间:2008-12-10,16:11:54.

出10入95汤圆

发表于 2008-12-10 22:56:26 | 显示全部楼层
留着!

出0入0汤圆

发表于 2008-12-11 09:57:35 | 显示全部楼层
顶一下,没想过51搞系统

出0入0汤圆

发表于 2008-12-17 09:13:52 | 显示全部楼层
做个记号

出0入0汤圆

发表于 2008-12-18 19:52:29 | 显示全部楼层
不顶不行

出0入0汤圆

发表于 2008-12-18 23:24:20 | 显示全部楼层
确实强悍。

出0入0汤圆

 楼主| 发表于 2008-12-19 05:40:53 | 显示全部楼层
【186楼】 gamethink 



积分:1093

派别:

等级:------

来自:广州

 to kejian2000  

谢谢你的回答,我试过确实不能够删除 



to LZ 

我从"3.消息机制"开始就看得很迷惑了...其实是不是还有其它文章没放的?而且和源代码的差别也很大  

   









消息机制是一种软件机制,用于进程间通信的.就是说,你要理解消息,就要先真正理解什么叫进程,为什么要进行进程间通信,进程间通信通的是什么东西.接下来要理解进程挂起和唤醒.这些背景知识不先理解,则无法理解消息的含义.

限于篇幅我并没有解释这些东西,因为帖子的主要目的是"如果搭一个精简的操作系统"而非"操作系统原理教学",写太啰嗦反而搞得谁都看不下去.

本贴被 rainyss 编辑过,最后修改时间:2008-12-19,05:45:48.

出0入0汤圆

发表于 2008-12-24 16:21:38 | 显示全部楼层
   高人!佩服

出330入0汤圆

发表于 2008-12-24 16:39:19 | 显示全部楼层
这个帖子应该带 两个 酷 字,因为比一般的 酷 贴 要精致的多。

出0入0汤圆

发表于 2008-12-25 15:05:36 | 显示全部楼层
看过留名,回来就实现一下多任务系统!

出330入0汤圆

发表于 2008-12-25 15:32:05 | 显示全部楼层
能够把这种思想在PIC单片机上实现吗?PIC单片机的堆栈不可访问啊。

本贴被 zcllom 编辑过,最后修改时间:2008-12-25,16:07:20.

出0入0汤圆

 楼主| 发表于 2008-12-27 02:43:39 | 显示全部楼层
to192楼



那些背景知识要系统全面的讲会很复杂,不全面讲又会引出更多的疑问,反而搞得晕头转向.个人认为这些知识还是先找本操作系统原理的书看看比较好.



操作系统里绝大部分概念都是鸡与蛋的关系,必须使用反复通读慢慢了解全盘渐近的方法,才能真正吸收,靠背,靠教,作用都不大

出0入0汤圆

发表于 2008-12-27 16:00:15 | 显示全部楼层
置顶!!

向楼主(rainyss)学习了。!

偶滴QQ:278081591

出0入0汤圆

 楼主| 发表于 2009-1-2 17:59:35 | 显示全部楼层
<<操作系统原理>>是一定要看的,不用精读,以大至看懂概念为标准通读一遍,不懂的先记下来,在读完第一遍后重读,如此迭低若干次.



接下来去google里搜"实时多任务",将两方面的知识结合起来.



做完这两部分后去找陈明计和电脑圈圈,这两人的OS模型一个倾向于"正规化作战"一个喜欢搞"游击战".吸收他们的个性到你的知识体系中去.记住,知识本身位居其二,个性才是知识的本源.



说起来简单做起来并不易,要持之以恒长期努力,且永远不要认为自已已经懂了.

出0入0汤圆

发表于 2009-1-2 19:06:36 | 显示全部楼层
学习!

出0入0汤圆

发表于 2009-1-2 19:40:34 | 显示全部楼层
shi kuai hao zhuan a

出0入0汤圆

发表于 2009-1-4 10:18:36 | 显示全部楼层
厉害!

出0入0汤圆

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

出0入0汤圆

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

出0入0汤圆

发表于 2009-1-4 14:06:36 | 显示全部楼层
众位都很牛!呵呵!

出0入0汤圆

发表于 2009-1-9 19:41:05 | 显示全部楼层
不平凡啊

出0入0汤圆

发表于 2009-1-12 23:45:17 | 显示全部楼层
牛年更牛啊

出0入0汤圆

发表于 2009-1-20 15:32:41 | 显示全部楼层
我顶!!!

出0入0汤圆

发表于 2009-1-23 22:20:24 | 显示全部楼层
学习!

出0入0汤圆

发表于 2009-1-24 14:29:34 | 显示全部楼层
楼主好.



我把你的 mtask 项目移植到一块测试目标板上跑. 是驱动一块12864的LCD的. 开始一会就跑飞了. 



原本测试的代码是没问题的:





#include "glcd.h"

#include "8051.img"

#include "welcome.img"



#define DELAY 10000



void main(void)

{

idata unsigned int i;

unsigned char array[100] = {"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()[]{}|\\<>?/|\0"};

unsigned short c;



  GLCD_LcdInit();



  while(1)

  {

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

    {

      GLCD_ClearScreen();

      GLCD_Locate(0, 0);

      LcdPutchar(array, &Font_System3x6);

      LcdDelay(DELAY);



      GLCD_ClearScreen();

      GLCD_DisplayPicture(image2);

      LcdDelay(DELAY);



      GLCD_ClearScreen();

      GLCD_DisplayPicture(image3);

      LcdDelay(DELAY);



      /* software delay time */

      c = 3000;

      while (c--);

    }

  }  

}





把三段显示的代码套进任务内就出现问题了:



void task1(void)

{

static unsigned char i;



  i = 0;



  while(1)

  {

    stra = strb;



    if(++i == sizeof(stra))

      i = 0;



    GLCD_ClearScreen();

    GLCD_Locate(0, 0);

    LcdPutchar(array, &Font_System3x6);

    LcdDelay(DELAY);



    task_switch();

  }

}



void task2(void)

{

static unsigned char i;

  i = 0;



  while(1)

  {

    stra = strb;



    if(++i == sizeof(stra))

      i = 0;



    GLCD_ClearScreen();

    GLCD_DisplayPicture(image2);

    LcdDelay(DELAY);



    task_switch();

  }

}



void task3(void)

{

unsigned char i;



  while(1)

  {

    i = sizeof(stra);



    GLCD_ClearScreen();

    GLCD_DisplayPicture(image3);

    LcdDelay(DELAY);



    do

    {

      stra[i-1] = strb[i-1];

    } while(--i);



    task_switch();

  }

}



void main(void)

{

  GLCD_LcdInit();



  task_load(task1, 0);

  task_load(task2, 1);

  task_load(task3, 2);



  os_start(0);

}



显示的函数都在 task_switch() 前完成, 应不会有覆盖的问题吧?

出0入0汤圆

 楼主| 发表于 2009-1-24 15:19:41 | 显示全部楼层
不存在你担心的覆盖问题,跑飞跟函数没有关系.跑飞极有可能是你内存使用过量引起的



void main(void) 

{ 

idata unsigned int i;  //题外话,这个变量没必要定义为idata,idata太占CPU资源,好象也没有必要用uint吧?uchar够用了

unsigned char array[100] = {"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()[]{}|\\<>?/|\0"};     //  这个数组应定义为unsigned char code array[] 

unsigned short c; 



最后,你的LcdDelay(DELAY)函数是不应该使用的,多任务操作中不应使用空循环,除非延时时间足够短,因为延时期间CPU是被白白消耗的.我另一个例子里有task_sleep()的实现方法,不占CPU资源,延时最小单位为1 tick,你可以参考一下.

本贴被 rainyss 编辑过,最后修改时间:2009-01-24,15:24:30.

出0入0汤圆

发表于 2009-2-1 11:02:10 | 显示全部楼层
不错,留个记号

出0入0汤圆

发表于 2009-2-1 11:10:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-2-1 21:51:47 | 显示全部楼层
牛人阿!!!

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

本版积分规则

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

GMT+8, 2024-3-28 17:30

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

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