waking 发表于 2013-2-2 13:11:45

经典的调度器!!

freeboyxd 发表于 2013-2-21 20:27:10

实时性要求高的项目可能难以胜任了

Myauto123 发表于 2013-2-22 21:52:35

好东西,学习了。。。

liu110537 发表于 2013-2-26 12:23:11

下来研究研究

wxlcj 发表于 2013-2-27 09:21:46

楼主,新年过完了,可以继续讲课了。

Eagle_rxz 发表于 2013-3-4 22:59:18

任务调度,时间片轮询机制,不错,学习了

shuxmpx123 发表于 2013-3-5 16:00:38

本帖最后由 shuxmpx123 于 2013-3-5 16:07 编辑

呵呵楼主牛人啊,我正准备用protothread 的,看的一头雾水,正好看到你这个帖子,准备试用一下,不知楼主这个调度器跟protothread 相比如何,各有什么长短优缺啊··{:lol:}

shuxmpx123 发表于 2013-3-6 11:28:00

请问 为什么我用STM8 的COSMIC编译器编译提示#error cpstm8 src\main.c:135(7) missing prototype   
RunTaskA(task1,1);//任务1具有比任务2高的运行权限                  
       RunTaskA(task2,2);//任务2具有低的运行权限
提示这2个函数无原型
用keil编译就没问题?                  

shuxmpx123 发表于 2013-3-6 16:45:15

找到报错的原因了,

unsigned char task0() 改成
unsigned char task0(void)就可以了。。。。


shuxmpx123 发表于 2013-3-6 17:29:07

本帖最后由 shuxmpx123 于 2013-3-6 17:30 编辑

谁能告诉我
unsigned chartask2(void){
_SS
while(1){
   WaitX(100);
   D3_BLINK();   
}
_EE
}

unsigned chartask2(void){
   D3_BLINK();   
   return 100;
}
这样写有什么好处, 这个我没太看懂,貌似 task2里面的函数都只运行了一次? 不是像系统那样一种死循环运行?

zj_871112 发表于 2013-3-6 20:56:25

很好啊~~正是需要

younge 发表于 2013-3-6 22:09:47

lihaolongli 发表于 2012-11-27 13:28 static/image/common/back.gif
前边的宏定义看的不大明白


我也是看不懂宏定义,找了点资料。看后好多了

shuxmpx123 发表于 2013-3-7 09:37:07

我觉得这个调度器不怎么样,
1、 任务多的时候UpdateTimers();这里面的步骤也不少;
2、 RunTaskA(task1,1); 。。。。。 RunTaskA(taskn,1); 在主函数的while(1)里面,每个任务也还是要依次检测看时间有没有到;
3、_SS_EEWaitX貌似没有必要,直接把任务函数放进去运行就可以了,如果是我没看懂这个地方的妙处,请大家指正;

下面的程序是我现在用的,感觉调度执行的步骤或许比楼主这个执行步骤更少:
          if (TIM4->SR1 & 0x01)
          {
                  TIM4->SR1 &= 0xFE;
                //TEST_K5_0_1();

                sys._500us++;
                if ((sys._500us&0x07) == 0)        // %8 == 0                4ms
                {
                        sys.task_4ms++;
                        if ((sys._500us&0x0F) == 0)        // %16 == 0                8ms
                        {
                                sys.task_8ms++;
                                if ((sys._500us&0x1F) == 0)        // %32 == 0                16ms
                                {
                                        sys.task_16ms++;
                                        if ((sys._500us&0x3F) == 0) // %64 == 0        // 32ms
                                        {
                                                sys.task_32ms++;
                                                sys._32ms++;
                                                if ((sys._32ms&0x03) == 0) // %4 == 0128ms
                                                {
                                                        sys.task_128ms++;       
                                                        if ((sys._32ms&0x07) == 0)        // %8 == 0256ms
                                                        {
                                                                sys.task_256ms++;
                                                                if (sys._32ms&0x0F)                // %16 == 0512ms
                                                                {
                                                                        sys.task_512ms |= 0xFF;
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }

while(1)
        {
                if (sys.task_8ms > 1)
                {
                        //while(1);
                }
                if (sys.task_4ms)
                {
                        sys.task_4ms = 0;

                }
                if (sys.task_8ms)       
                {
                        Key_Scan();                                //扫描按键

                        sys.task_8ms = 0;
                }
                if (sys.task_16ms)       
                {

                        sys.task_16ms = 0;
                }

}

pxq8410 发表于 2013-3-28 12:20:03

学习,任务调度

bondxie3 发表于 2013-4-7 16:40:23

一口气看完整个帖子,获益良多!希望这个调度器越来越好!

LearningASM 发表于 2013-4-8 08:24:34

由状态机到学习任务调度{:time:}

renwocai 发表于 2013-4-8 12:56:17

smset 发表于 2012-12-21 11:57 static/image/common/back.gif
综合这几天的讨论,先更新一版,仅供评测用:主要改动有: 1) 增加了RunTaskA宏,让前面的任务有优先执行 ...

我把这段程序手式展开看了几遍,还是有些疑问,请楼主及各位高手能解释下

1.信号量部分的宏定义了但后面都没有用到,可以直接注释掉吧?//#define SEM unsigned int
//初始化信号量
//#define InitSem(sem) sem=0;
//等待信号量
//#define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
//等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
//#define WaitSemX(sem,tickets)do { sem=tickets+1; WaitX(0); if(sem>1){ sem--;return 1;} } while(0);
//发送信号量
//#define SendSem(sem)do {sem=0;} while(0);2.任务函数的展开,如下unsigned chartask1()
{
    static unsigned char _lc;
    switch(_lc)
    {
    default:while(1)
      {
      do {_lc=__LINE__+((__LINE__%256)==0); return 100 ;}
         while(0);
   case __LINE__+((__LINE__%256)==0):;
         LED1=!LED1;
         };
    }; _lc=0; return 255;
}while(1) 的作用范围跨过了case __LINE__+((__LINE__%256)==0),但while(1)的执行条件是default,而default与case __LINE__+((__LINE__%256)==0)应该是并列的啊,这段代码应该是怎样执行的?或者说,default与case之间应该是完整的代码吧,怎么就少了一个大括号呢?

bondxie3 发表于 2013-4-9 11:35:10

renwocai 发表于 2013-4-8 12:56 static/image/common/back.gif
我把这段程序手式展开看了几遍,还是有些疑问,请楼主及各位高手能解释下

1.信号量部分的宏定义了但后 ...

要结合RunTask宏展开分析!

renwocai 发表于 2013-4-9 15:52:31

bondxie3 发表于 2013-4-9 11:35 static/image/common/back.gif
要结合RunTask宏展开分析!

谢谢回复,task1()不解决,RunTask就更没法看啦。

renwocai 发表于 2013-4-10 11:17:44

又看了几天,终于明白啦,原来while(1)的作用是执行完后一个case再强行拉回来记录一次行号。

现在还有一个问题,信号量是怎么使用的?能否给个简单的例程?

himm007 发表于 2013-4-10 15:33:00

smset 发表于 2013-1-6 18:30 static/image/common/back.gif
嗯,您说的很有道理。

可能本帖中有部分回帖认为: 小小调度器是 把时间片调度和protothread结合起来的 ...

“必须用的cpu(无法改换),仅仅只有512字节RAM, 8K字节ROM,而且我希望它干更多的事情。 ”

================================================================

闲逛的时候看到这么精彩的帖子,真实佩服各路高手。
不过我的看法是,
1,虽然小小调度器很精简,但它的代码只占整个系统的百分之一,再精简都会被其余的任务代码冗余掉。,
2,按照时间片的方式顺序调度各个任务,会打断任务的执行环境,编程时要实时考虑访问的内存是不是会被其它的任务修改,调度器很优美,但无疑会给开发者带来额外的困扰。
3,我还是倾向于使用状态机的方式,顺序处理各个任务,优先级高的任务多分配些状态,优先级低的少分配些。而且各个状态的执行函数都是在同一级,因此可以节省很多可贵的栈空间。

8K ROM,512Byte 也够用了。


fqc168 发表于 2013-4-10 17:48:09

我看了两天protothread,觉得还是使用状态机比较合适,明白了事,C语言就是追求简单易读,宏隐含太多东西!

smset 发表于 2013-4-10 18:09:09

himm007 发表于 2013-4-10 15:33 static/image/common/back.gif
“必须用的cpu(无法改换),仅仅只有512字节RAM, 8K字节ROM,而且我希望它干更多的事情。 ”

========= ...

1,虽然小小调度器很精简,但它的代码只占整个系统的百分之一,再精简都会被其余的任务代码冗余掉。,

小小调度器除了本身小巧外,最大的用处是通过这个调度框架,写出的代码反而比状态机还省CPU资源.所以前面说" 比裸奔还省资源 " ,就是这个意思.
2,按照时间片的方式顺序调度各个任务,会打断任务的执行环境,编程时要实时考虑访问的内存是不是会被其它的任务修改,调度器很优美,但无疑会给开发者带来额外的困扰。

你把小小调度器理解成抢占式多任务了, 但小小调度器不是抢占式多任务, 而是stackless的协作式调度, 不存在一个任务正在运行时,变量被其它的任务修改的可能性.也正是这样, 才会更加简化编程.
3,我还是倾向于使用状态机的方式,顺序处理各个任务,优先级高的任务多分配些状态,优先级低的少分配些。而且各个状态的执行函数都是在同一级,因此可以节省很多可贵的栈空间。

还是这个道理, 小小调度器是stackless的协作式调度器, 并不存在消耗更多的栈空间的问题.所以函数依然是同一级的.

smset 发表于 2013-4-10 18:12:37

当你习惯于状态机时,你可能感觉不出状态机的问题. 然而当你习惯于调度器以后,你才会感觉出状态机的问题.

同样的道理:

当你习惯开手动挡汽车的时候, 你并不觉得多大的不方便.

但是当你习惯开自动档汽车以后,你就再也不愿意开手动档汽车了.

jz701209李 发表于 2013-4-10 18:35:32

强帖留名。。。。。。

himm007 发表于 2013-4-11 14:14:49

帖子内容太多,你可以单独一个网页详细介绍这个么,个人网站或者新帖子什么的。
最好能把宏展开,这样好看懂些。

liyongl66 发表于 2013-4-12 16:27:29

很好的思路,多谢了!

meirenai 发表于 2013-4-14 23:53:07

标记。。。。.

皮爱了西 发表于 2013-4-15 15:02:34

收藏了先。

Hz01800475 发表于 2013-4-16 12:16:58

smset 发表于 2013-4-10 18:12 static/image/common/back.gif
当你习惯于状态机时,你可能感觉不出状态机的问题. 然而当你习惯于调度器以后,你才会感觉出状态机的问题.

...

   楼主,能不能放出一个综合性的工程。比如有串口,IIC,SPI,按键的模板。

qingaixww 发表于 2013-4-16 22:47:47

有意义,高人!

zd305 发表于 2013-4-26 21:15:54

在PIC mplab xxc8 上编译,WaitX(50);出错,出错信息:constant expression required

jangyouhua 发表于 2013-5-6 21:48:52

smset思路很好!我在他的基础上改了一下,用于IAR c++ 编泽
有些没有完工!对共享变量加入临界保护!写的不好,不要扔砖头哦!
#ifndef WEEAOS_H
#define WEEAOS_H

#include "weea_cpu.h"

#define MAXTASKS   3u

#ifdefWEEA_GLOBALS

volatile INT16U weea_timers = {0};

#else

extern INT16U weea_timer;

#endif


#defineWEEA_BEGIN()               static INT16U _lc; switch(_lc) { default:
#defineWEEA_END()                   } _lc = 0; return 0xffff;

#defineWaitX(ticks)               do{_lc = __LINE__;return ticks;}while(0); case __LINE__:

#defineRunTask(TaskName,TaskID)   do{if(weea_timers == 0) \
                                           {\
                                             INT16U _trvalue = TaskName(); \
                                             OS_ENTER_CRITICAL(); \
                                             weea_timers = _trvalue; \
                                             OS_EXIT_CRITICAL(); \
                                           }\
                                       }while(0);

#define RunTaskEx(TaskName,TaskID)      if(weea_timers == 0) \
                                        { \
                                           INT16U _trvalue = TaskName(); \
                                           OS_ENTER_CRITICAL(); \
                                           weea_timers = _trvalue; \
                                           OS_EXIT_CRITICAL(); \
                                           continue; \
                                       }

#define CallSub(SubTaskName)            do { WaitX(0); INT16U _curr_td = SubTaskName(); if(_curr_td != 0xffff) return _curr_td;} while(0);
#define UpdateTimers()                  { for(INT8U i=MAXTASKS; i>0 ;i--){if((weea_timers != 0) && (weea_timers != 0xffff)) weea_timers--;}} //一定要在中断中调用

//weeaOS returen reslut value define   
#define   PT_R_MUT   0    //等待MUT信号量
#define   PT_R_SEM   0    //等待MUT信号量
#define   PT_R_TMO   255//等待超时
#define   PT_R_OK      1    //等到一个对应结果,如等到一个MUT,或一个SEM,或其它

// MUT信号量支持
typedefboolTmut;
#definemut_create(A,B) \
             Tmut A = B
#define mut_create_extern(A) \
          extern Tmut A
#defineSendMut(A)       do{ (A) = true; }while(0);
#defineWaitMut(A)      do{ WaitX(0); if(!(A)) return 1; }while(0);
#defineWaitMutX(A,B,Err)\
         do{ WaitX(0);\
             static u16 __t=(B);\
             if(!(A)){if(__t!=0xffff){if(__t==0){(Err)=PT_R_TMO;goto _WEEA_##__LINE__;}--__t;}return 1;}(Err) = PT_R_OK;_WEEA_##__LINE__:\
         }while(0);

// SEM计数型信号量支持
typedefINT8UTsem;
#definesem_create(A,B) \
        Tsem A = B
#define sem_create_extern(A) \
        extern Tsem A




// 消息支持




#endif
      

jangyouhua 发表于 2013-5-6 22:03:07

稍修改了下,增加了注释:
#ifndef WEEAOS_H
#define WEEAOS_H

#include "weea_cpu.h"

#define MAXTASKS   3u

#ifdefWEEA_GLOBALS

volatile INT16U weea_timers = {0};

#else

extern INT16U weea_timer;

#endif


#defineWEEA_BEGIN()               static INT16U _lc; switch(_lc) { default:
#defineWEEA_END()                   } _lc = 0; return 0xffff;

#defineWaitX(ticks)               do{_lc = __LINE__;return ticks;}while(0); case __LINE__:

#defineRunTask(TaskName,TaskID)   do{if(weea_timers == 0) \
                                           {\
                                             INT16U _trvalue = TaskName(); \
                                             OS_ENTER_CRITICAL(); \
                                             weea_timers = _trvalue; \
                                             OS_EXIT_CRITICAL(); \
                                           }\
                                       }while(0);

#define RunTaskEx(TaskName,TaskID)      if(weea_timers == 0) \
                                        { \
                                           INT16U _trvalue = TaskName(); \
                                           OS_ENTER_CRITICAL(); \
                                           weea_timers = _trvalue; \
                                           OS_EXIT_CRITICAL(); \
                                           continue; \
                                       }

#define CallSub(SubTaskName)            do { WaitX(0); INT16U _curr_td = SubTaskName(); if(_curr_td != 0xffff) return _curr_td;} while(0);
#define UpdateTimers()                  { for(INT8U i=MAXTASKS; i>0 ;i--){if((weea_timers != 0) && (weea_timers != 0xffff)) weea_timers--;}} //一定要在中断中调用

//weeaOS returen reslut value define   
#define   PT_R_MUT   0    //等待MUT信号量
#define   PT_R_SEM   0    //等待MUT信号量
#define   PT_R_TMO   255//等待超时
#define   PT_R_OK      1    //等到一个对应结果,如等到一个MUT,或一个SEM,或其它

// MUT互斥型信号支持
typedefboolTmut;
#definemut_create(A,B) \
             Tmut A = B
#define mut_create_extern(A) \
          extern Tmut A
#defineSendMut(A)       do{ (A) = true; }while(0);
#defineWaitMut(A)      do{ WaitX(0); if(!(A)) return 1; }while(0);

// A: mut型信号量,bool型
// B: 超时值,IN16U型
// Err: 返回等待结果,要求Err在调用前为0(PT_R_MUT或PT_R_SEM).
//      PT_R_MUT或PT_R_SEM: 信号量正等待中
//      PT_R_OK: 等到一个信号
//      PT_R_TMO : 等到超时
#defineWaitMutX(A,B,Err)\
         do{ WaitX(0);\
             static u16 __t=(B);\
             if(!(A)){if(__t!=0xffff){if(__t==0){(Err)=PT_R_TMO;goto _WEEA_##__LINE__;}--__t;}return 1;}(Err) = PT_R_OK;_WEEA_##__LINE__:\
         }while(0);

// SEM计数型信号量支持
typedefINT8UTsem;
#definesem_create(A,B) \
        Tsem A = B
#define sem_create_extern(A) \
        extern Tsem A




// 消息支持




#endif
      

jangyouhua 发表于 2013-5-6 22:16:31

用了n多RTOS,protothread确实叫人惊叹!如果测试没问题,可以支持消息、邮箱,以及类似keil RTX中的event事件!

jangyouhua 发表于 2013-5-6 22:53:32

再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H

#include "weea_cpu.h"

#define MAXTASKS   3u

#ifdefWEEA_GLOBALS

volatile INT16U weea_timers = {0};

#else

extern INT16U weea_timer;

#endif


#defineWEEA_BEGIN()               static INT16U _lc; switch(_lc) { default:
#defineWEEA_END()                   } _lc = 0; return 0xffff;

#defineWaitX(ticks)               do{_lc = __LINE__;return ticks;}while(0); case __LINE__:

#defineRunTask(TaskName,TaskID)   do{if(weea_timers == 0) \
                                           {\
                                             INT16U _trvalue = TaskName(); \
                                             OS_ENTER_CRITICAL(); \
                                             weea_timers = _trvalue; \
                                             OS_EXIT_CRITICAL(); \
                                           }\
                                       }while(0);

#define RunTaskEx(TaskName,TaskID)      if(weea_timers == 0) \
                                        { \
                                           INT16U _trvalue = TaskName(); \
                                           OS_ENTER_CRITICAL(); \
                                           weea_timers = _trvalue; \
                                           OS_EXIT_CRITICAL(); \
                                           continue; \
                                       }

#define CallSub(SubTaskName)            do { WaitX(0); INT16U _curr_td = SubTaskName(); if(_curr_td != 0xffff) return _curr_td;} while(0);
#define UpdateTimers()                  { for(INT8U i=MAXTASKS; i>0 ;i--){if((weea_timers != 0) && (weea_timers != 0xffff)) weea_timers--;}} //一定要在中断中调用

//weeaOS return reslut value define   
#define   PT_R_MUT   0    //等待MUT信号量
#define   PT_R_SEM   0    //等待MUT信号量
#define   PT_R_TMO   255//等待超时
#define   PT_R_OK      1    //等到一个对应结果,如等到一个MUT,或一个SEM,或其它

// MUT互斥型信号支持
typedefboolTmut;
#definemut_create(A,B) \
             Tmut A = B
#define mut_create_extern(A) \
          extern Tmut A
#defineSendMut(A)       do{ (A) = true; }while(0);
#defineWaitMut(A)      do{ WaitX(0); if(!(A)) return 1; }while(0);

// A: mut型信号,bool型
// B: 超时值,IN16U型
// Err: 返回等待结果,要求Err在调用前为0(PT_R_MUT或PT_R_SEM).
//      PT_R_MUT或PT_R_SEM: 信号量正等待中
//      PT_R_OK: 等到一个信号
//      PT_R_TMO : 等到超时
#defineWaitMutX(A,B,Err)\
         do{ WaitX(0);\
             static u16 __t=(B);\
             if(!(A)){if(__t!=0xffff){if(__t==0){(Err)=PT_R_TMO;goto _WEEA_##__LINE__;}--__t;}return 1;}(Err) = PT_R_OK;OS_ENTER_CRITICAL();(A)=false;OS_EXIT_CRITICAL();_WEEA_##__LINE__:\
         }while(0);

// SEM计数型信号支持
typedefINT8UTsem;
#definesem_create(A,B) \
        Tsem A = B
#define sem_create_extern(A) \
        extern Tsem A

#define SendSem(A)         do( (A)++; )while(0);
#define WaitSem(A)         do{ WaitX(0); if((A) == 0){return 1;} (A)--; }while(0);
#define WaitSemX(A,B,Err) \
do{\
   WaitX(0);static u16 __tt=(B);if((A)==0){if(__tt!=0xffff){if(__tt==0){(Err)=PT_R_TMO;goto _WEEA_##__LINE__;}--__tt;}return 1;}(Err)=PT_R_OK;OS_ENTER_CRITICAL();--(A);OS_EXIT_CRITICAL();_WEEA_##__LINE__:\
}while(0);

// 消息、邮箱支持
typedefINT8UTmsg;
#definemsg_create(A,B) \
        Tmsg* A = B
#define msg_create_extern(A) \
        extern Tmsg* A
#define SendMsg(A)         
#define WaitMsg(A)         
#define WaitMsgX(A,B,Err) \



#endif

      

eddia2012 发表于 2013-5-11 17:50:10

{:smile:}这个已用了好几个案子的开发了,它对C编译器适应性很强!

smset 发表于 2013-5-14 17:03:22

jangyouhua 发表于 2013-5-6 22:53 static/image/common/back.gif
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H


修改得好,期待能进一步完善和优化。

foxpro2005 发表于 2013-5-15 00:23:02

本帖最后由 foxpro2005 于 2013-5-15 00:30 编辑

jangyouhua 发表于 2013-5-6 22:53 static/image/common/back.gif
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H


互斥信号------ 这一部分好像有点问题....
WaitMut(A)      do{ WaitX(0); if(!(A)) return 1; (A)=false; }while(0);

maimaige 发表于 2013-5-22 10:24:00

小 调度器 mark一下

Hz01800475 发表于 2013-5-24 14:39:43

eddia2012 发表于 2013-5-11 17:50 static/image/common/back.gif
这个已用了好几个案子的开发了,它对C编译器适应性很强!

{:smile:} 我现在在用你的代码,Task_event_wait(D_wait_ever);    #define D_wait_ever   ((u8)-1)这个宏是什么作用。

Hz01800475 发表于 2013-5-24 14:50:54

eddia2012 发表于 2013-5-11 17:50 static/image/common/back.gif
这个已用了好几个案子的开发了,它对C编译器适应性很强!

Task2_display() 这个函数没看懂,        if(task_Wait_flag)什么意思啊。
                        {
                                                   Task_subCall(subtask);
                        }

Hz01800475 发表于 2013-5-24 15:45:28

eddia2012 发表于 2012-12-16 22:34 static/image/common/back.gif
希望加入事件触发优化。

你的代码加了吧。

安心 发表于 2013-6-12 08:44:15

{:smile:}不错

BruceZeng 发表于 2013-6-25 16:48:19

protothread

AIHHLI 发表于 2013-6-26 10:35:24

研究了一会,搞懂了。
真的很巧妙,赞一个。
看不懂的童鞋可以从楼主位那段代码开始,关键是task2,手动将宏展开,你将看到一种switch的变态用法,然后原理一目了然。__LINE__是语句所在的行号。
实际上在函数遇到延时返回前做了两件事:设置延时时间,设置状态变量lc,使得第二次进入函数时得到正确的跳转。

lovemini 发表于 2013-7-10 16:40:32

jangyouhua 发表于 2013-5-6 22:53 static/image/common/back.gif
再贴一改进代码:
#ifndef WEEAOS_H
#define WEEAOS_H


能提供weea_cpu.h 的代码吗?

tom_flag 发表于 2013-7-31 20:55:52

支持。。谢谢分享哈..调度器博大精深哈~~

smset 发表于 2013-7-31 22:59:23



#include <stc89c51.h>
/****小小调度器开始**********************************************/
#define MAXTASKS 3
volatile unsigned char timers;
#define _SS static unsigned char _lc; switch(_lc){default:
#define _EE ;}; _lc=0; return 255;
#define WaitX(tickets)do {_lc=__LINE__; return tickets ;} while(0); case __LINE__:

#define RunTask(TaskName,TaskID) do { if (timers==0) timers=TaskName(); }while(0);
#define RunTaskA(TaskName,TaskID) { if (timers==0) {timers=TaskName(); continue;} }   //前面的任务优先保证执行

#define CallSub(SubTaskName) do {unsigned char currdt; _lc=__LINE__; return 0; case __LINE__:currdt=SubTaskName(); if(currdt!=255) return currdt;} while(0);
#define UpdateTimers() {unsigned char i; for(i=MAXTASKS;i>0 ;i--){if((timers!=0)&&(timers!=255)) timers--;}}

#define SEM unsigned int
//初始化信号量
#define InitSem(sem) sem=0;
//等待信号量
#define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
//等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
#define WaitSemX(sem,tickets)do { sem=tickets+1; WaitX(0); if(sem>1){ sem--;return 1;} } while(0);
//发送信号量
#define SendSem(sem)do {sem=0;} while(0);

/*****小小调度器结束*******************************************************/


sbit LED1 = P2^1;
sbit LED2 = P2^2;

sbit LED0 = P2^5;

unsigned char task0(){
_SS
while(1){
   WaitX(50);
   LED0=!LED0;   
}
_EE
}

unsigned chartask1(){
_SS
while(1){
   WaitX(100);
   LED1=!LED1;   
}
_EE
}

unsigned chartask2(){
_SS
while(1){
   WaitX(100);
   LED2=!LED2;   
}
_EE
}

void InitT0()
{
      TMOD = 0x21;
      IE |= 0x82;// 12t
      TL0=0Xff;
      TH0=0XDB;
      TR0 = 1;
}

void INTT0(void) interrupt 1 using 1
{
    TL0=0Xff;    //10ms 重装
    TH0=0XDB;//b7;   

    UpdateTimers();

    RunTask(task0,0);//任务0具有精确按时获得执行的权限,建议:task0每次执行消耗时间<0.5个 ticket
}




void main()
{
      InitT0();
      while(1){
         //RunTask(task0,0);
         RunTaskA(task1,1);//任务1具有比任务2高的运行权限                  
         RunTaskA(task2,2);//任务2具有低的运行权限                  
      }
}

liufabing 发表于 2013-8-1 17:20:57

Mark,学习

liufabing 发表于 2013-8-3 01:08:05

656楼的代码08行
#define _EE ;}; _lc=0; return 255;
后面的_lc=0; return 255;
程序不会运行这2句,不知道有什么作用?

rossih 发表于 2013-8-14 09:05:06

不是跟时间触发嵌入式系统那本书里的一样么?

smset 发表于 2013-8-14 09:57:08

rossih 发表于 2013-8-14 09:05 static/image/common/back.gif
不是跟时间触发嵌入式系统那本书里的一样么?

根本不一样,没有可比性。

holts2 发表于 2013-8-16 11:03:20

smset 发表于 2013-8-14 09:57 static/image/common/back.gif
根本不一样,没有可比性。

如果程序的行数超过255行,程序可以正常运行吗 ?

smset 发表于 2013-8-16 13:21:32

holts2 发表于 2013-8-16 11:03 static/image/common/back.gif
如果程序的行数超过255行,程序可以正常运行吗 ?

可以正常运行的。

holts2 发表于 2013-8-16 13:30:07

smset 发表于 2013-8-16 13:21 static/image/common/back.gif
可以正常运行的。

我在stm8s103使用库,用到, 编绎正常,但程序不能正常运行,不知从何查起


#include "ptask.h"
#include "stm8s.h"

#define LED_GPIO_PORT(GPIOA)
#define LED_GPIO_PINS(GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)
#define SW_4GPIO_PIN_1
#define SW_5GPIO_PIN_2
#define LED_RUN_OR_WAIT   GPIO_PIN_3

#define LED_GPIO_PORT2 (GPIOC)
#define LED_GPIO_PINS2 (GPIO_PIN_5 | GPIO_PIN_6)
#define LED_WAIT   GPIO_PIN_5
#define LED_RUN3   GPIO_PIN_6

#define LED_GPIO_PORT3 (GPIOD)
#define LED_GPIO_PINS3 (GPIO_PIN_6)
#define LED_RUN    GPIO_PIN_6

#define KEY_GPIO_PORT(GPIOD)
#define KEY_GPIO_PINS(GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 )
#define KEY_POWER   GPIO_PIN_1   
#define KEY_REDUCE   GPIO_PIN_2
#define KEY_PLUSGPIO_PIN_3

#define KEY_MODE_PINS (GPIO_PIN_4)
#define KEY_MODE    GPIO_PIN_4
#define KEY_TRIGGER_PINS (GPIO_PIN_5)
#define KEY_TRIGGERGPIO_PIN_5

#define KEY_GPIO_PORT2(GPIOC)
#define KEY_SW_PINS (GPIO_PIN_7)
#define KEY_SW    GPIO_PIN_7

#define MilliSec      1
#define Sec             1000

#define STEP            5   //约5%
#define MAX             70//100%
#define MIN             15//约21%

#define OFF             0
#define ON            1
#define RUN             2
#define WAIT            3

#define TIM4_PERIOD   124   //1ms定时


void GPIO_Configuration(void);
void TIM4_Config(void);
void TimingDelay_Decrement(void);
void PWM1_Init(void);
void SetTIM1_PWM_DutyCycle(uint16_t TIM1_Pulse);

unsigned char Blink(void);
unsigned char SwRead(void);

void KeyRead(void);
unsigned char Key_thread(void);
void LightReduce(void);
void LightPlus(void);
void PowerEvent(void);
void SwEvent(void);

void Write_Byte (unsigned int address,unsigned char Data);

unsigned char task0(void);
unsigned char task1(void);

/* Private functions -------------------------------------------*/
/* Global variables --------------------------------------------*/
volatile unsigned char timers={0};

unsigned char Trg;
unsigned char Cont;

unsigned charBlinkOfNumber = 0;

unsigned char DutyCycle;
unsigned char Mode;
unsigned char ChangeFlag = 1;

unsigned char SaveFlag;
unsigned int SaveDelay;

unsigned char RunF;
unsigned char WaitF;

unsigned char SwF;

/**
****************************************************************
* @brief Main function.
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
****************************************************************
*/
void main(void)
{
/* Configures clocksFmaster = 16MHz */
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
       
/* read light value */
DutyCycle = FLASH_ReadByte(FLASH_DATA_START_PHYSICAL_ADDRESS);
if (! ((DutyCycle >= MIN) && (DutyCycle <= MAX)))
        {        DutyCycle = (5 * MIN) ;        }
       
/* Configures GPIOs */
GPIO_Configuration();

        /* init pb */
SwF =   FLASH_ReadByte(FLASH_DATA_START_PHYSICAL_ADDRESS+1);
if (SwF)
          {
                  GPIO_WriteHigh(LED_GPIO_PORT, SW_4);
                        GPIO_WriteLow(LED_GPIO_PORT, SW_5);
                }
    else       
                {
                        GPIO_WriteLow(LED_GPIO_PORT, SW_4);
                  GPIO_WriteHigh(LED_GPIO_PORT, SW_5);
                }


        /* read switch mode */
        if ( GPIO_ReadInputPin(KEY_GPIO_PORT, KEY_MODE))
          {Mode = ON;}
        else
    {Mode = OFF;}

        /* Initialize PWM */
        PWM1_Init();

/* TIM4 configuration */
TIM4_Config();

/* enable interrupts */
enableInterrupts();

while(1)
        {
                /* 键盘处理 */
    RunTask(Key_thread,Task0_ID);
   
          /* 常闭键处理 */
                if (! GPIO_ReadInputPin(KEY_GPIO_PORT, KEY_TRIGGER))
                        {
                          if (Mode == RUN)   { Mode = WAIT; ChangeFlag = 1; }
                 }
                  else
                  {
                          if (Mode == WAIT)          {        Mode = RUN;        ChangeFlag = 1; }
                        }
                       
                /* 闪烁服务 */
                RunTask(Blink,Task1_ID);

                /* 模式服务 */
                if ((ChangeFlag == 1) && (BlinkOfNumber == 0))
          {
                        ChangeFlag = 0;
                  if (Mode == OFF)
                  {
                          GPIO_WriteLow(LED_GPIO_PORT3, LED_RUN);
                                RunF = 0;                WaitF = 0;
                                GPIO_WriteLow(LED_GPIO_PORT2, LED_WAIT);
                                GPIO_WriteLow(LED_GPIO_PORT2, LED_RUN3);
                          TIM1_CtrlPWMOutputs(DISABLE);
                  }
                  if (Mode == ON)         { Mode = RUN; }
                  if (Mode == RUN)
                  {
                          GPIO_WriteHigh(LED_GPIO_PORT3, LED_RUN);
                                RunF = 1;                WaitF = 0;
                                GPIO_WriteHigh(LED_GPIO_PORT2, LED_WAIT);
                                GPIO_WriteHigh(LED_GPIO_PORT2, LED_RUN3);
                          TIM1_CtrlPWMOutputs(ENABLE);
                  }
                  if (Mode == WAIT)
                  {
                          GPIO_WriteLow(LED_GPIO_PORT3, LED_RUN);
                                RunF = 0;                WaitF = 1;
                                GPIO_WriteLow(LED_GPIO_PORT2, LED_WAIT);
                                GPIO_WriteLow(LED_GPIO_PORT2, LED_RUN3);
                          TIM1_CtrlPWMOutputs(DISABLE);
                  }
                       
                        if (RunF || WaitF)
                   { GPIO_WriteHigh(LED_GPIO_PORT, LED_RUN_OR_WAIT); }
                        else
                   { GPIO_WriteLow(LED_GPIO_PORT, LED_RUN_OR_WAIT);}
                                  }
               
               
                RunTask(SwRead,Task2_ID);

                /* 存储服务 */
                if (SaveFlag == 1)
                {
                        if (SaveDelay == 0 )
                        {
                                Write_Byte(FLASH_DATA_START_PHYSICAL_ADDRESS,DutyCycle);
                                Write_Byte(FLASH_DATA_START_PHYSICAL_ADDRESS+1,SwF);
                                SaveFlag = 0;
                        }
                }
               
       // RunTask(task0,Task1_ID);
       // RunTask(task1,Task2_ID);
}
       
}

/**
******************************************************************
* @brief Toggle Sw switch
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
unsigned char SwRead(void)
{
        _BEGIN
    if (GPIO_ReadInputPin(KEY_GPIO_PORT2, KEY_SW))
                {
                      WaitX(20);
                if(GPIO_ReadInputPin(KEY_GPIO_PORT2, KEY_SW))       SwEvent();
               }
        _END
}


unsigned char task0(void)
{
        _BEGIN
        while(1)
        {
                WaitX(100);
                GPIO_WriteHigh(LED_GPIO_PORT,SW_4);
                WaitX(200);
                GPIO_WriteLow(LED_GPIO_PORT,SW_4);
        }
        _END
}

unsigned char task1(void)
{
        _BEGIN
        while(1)
        {
                WaitX(50);
                GPIO_WriteHigh(LED_GPIO_PORT,SW_5);
                WaitX(50);
                GPIO_WriteLow(LED_GPIO_PORT,SW_5);
        }
        _END
}

/**
******************************************************************
* @brief Delay before completing the action
* @param function action() to be performed once the delay past
* @param None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
unsigned char Key_thread(void)
{
_BEGIN
    KeyRead();
    if (Trg)
        {
        WaitX(20);
      KeyRead();
        if(Cont)
       {
       if ((Cont & KEY_PLUS) && (Mode == RUN)){ LightPlus(); }
         if ((Cont & KEY_REDUCE) && (Mode == RUN)){ LightReduce(); }
       if (Cont & KEY_POWER)   { PowerEvent(); }
       }
      }
_END
}       

/**
******************************************************************
* @brief Delay before completing the action
* @param function action() to be performed once the delay past
* @param None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
unsigned char Blink(void)
{
        _BEGIN
        if (BlinkOfNumber > 0)
        {
                WaitX(100);
                GPIO_WriteReverse(LED_GPIO_PORT, LED_WAIT);
                BlinkOfNumber--;
        }
        _END
}


/**
***************************************************************
* @brief Configures GPIOs
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
***************************************************************
*/
void GPIO_Configuration(void)
{
/* GPIOD reset */
        GPIO_DeInit(LED_GPIO_PORT);
        GPIO_DeInit(LED_GPIO_PORT2);
        GPIO_DeInit(KEY_GPIO_PORT);
       
        GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS,GPIO_MODE_OUT_PP_LOW_FAST);
        GPIO_Init(LED_GPIO_PORT2, (GPIO_Pin_TypeDef)LED_GPIO_PINS2,GPIO_MODE_OUT_PP_LOW_FAST);       
        GPIO_Init(LED_GPIO_PORT3, (GPIO_Pin_TypeDef)LED_GPIO_PINS3,GPIO_MODE_OUT_PP_LOW_FAST);       
       
        GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_GPIO_PINS,GPIO_MODE_IN_PU_NO_IT);
        GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_TRIGGER_PINS,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(KEY_GPIO_PORT, (GPIO_Pin_TypeDef)KEY_MODE_PINS,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(KEY_GPIO_PORT2, (GPIO_Pin_TypeDef)KEY_SW_PINS,GPIO_MODE_IN_PU_NO_IT);
       
}


/**
*****************************************************************
* @briefConfigure TIM4 to generate an update interrupt each 1ms
* @paramNone
* @retval None
 *****************************************************************
*/
void TIM4_Config(void)
{
/* TIM4 configuration:
   - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
   clock used is 16 MHz / 128 = 125 000 Hz
- With 125 000 Hz we can generate time base:
      max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
      min time base is 0.016 ms if TIM4_PERIOD = 1   --> (1 + 1) / 125000 = 0.016 ms
- In this example we need to generate a time base equal to 1 ms
   so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */

/* Time base configuration */
TIM4_TimeBaseInit(TIM4_PRESCALER_128, TIM4_PERIOD);
/* Clear TIM4 update flag */
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
/* Enable update interrupt */
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);

/* Enable TIM4 */
TIM4_Cmd(ENABLE);
}

/**
********************************************************
* @briefDecrements the TimingDelay variable.
* @paramNone
* @retval None
 ********************************************************
*/
void TimingDelay_Decrement(void)
{if (SaveDelay != 0x00) { SaveDelay--;} }

/**
*****************************************************************
* @brief Initialize all the PWM Parameters
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
*****************************************************************
*/
void PWM1_Init(void)
{
          /* PWM1 Mode configuration Channel2
           * Duty Cycle = *100=50% */
       
                TIM1_DeInit();
               
                /* Time Base configuration */
    /*
                   TIM1_Prescaler = 1280   分频16/1280 = 12.5 KHz
       TIM1_Period = 69   频率12.5K /(69+1) = 179Hz
       TIM1_CounterMode = TIM1_COUNTERMODE_UP
                       TIM1_RepetitionCounter = 0
    */
                TIM1_TimeBaseInit(1280, TIM1_COUNTERMODE_UP, 69, 0);
               
                /* Channel 2 Configuration in PWM mode */
    /*
       TIM1_OCMode = TIM1_OCMODE_PWM2
       TIM1_OutputState = TIM1_OUTPUTSTATE_ENABLE
       TIM1_OutputNState = TIM1_OUTPUTNSTATE_ENABLE
       TIM1_Pulse = DutyCycle
       TIM1_OCPolarity = TIM1_OCPOLARITY_LOW
       TIM1_OCNPolarity = TIM1_OCNPOLARITY_HIGH
       TIM1_OCIdleState = TIM1_OCIDLESTATE_SET
       TIM1_OCNIdleState = TIM1_OCIDLESTATE_RESET
    */
                TIM1_OC3Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_ENABLE, DutyCycle,
               TIM1_OCPOLARITY_LOW, TIM1_OCNPOLARITY_HIGH, TIM1_OCIDLESTATE_SET,
               TIM1_OCNIDLESTATE_RESET);
                                                       
    TIM1_OC4Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, DutyCycle, TIM1_OCPOLARITY_LOW,
               TIM1_OCIDLESTATE_SET);
                                                                       
                /* TIM1 counter enable */
    TIM1_Cmd(ENABLE);
               
                /* TIM1 Main Output Enable */
    TIM1_CtrlPWMOutputs(ENABLE);
}


/**
***************************************************************
* @brief Set DutyCycle value
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
***************************************************************
*/
void SetTIM1_PWM_DutyCycle(uint16_t TIM1_Pulse)
{
        /* Set the Pulse value */
        TIM1->CCR3H = (uint8_t)(TIM1_Pulse >> 8);
        TIM1->CCR3L = (uint8_t)(TIM1_Pulse);
        /* Set the Pulse value */
        TIM1->CCR4H = (uint8_t)(TIM1_Pulse >> 8);
        TIM1->CCR4L = (uint8_t)(TIM1_Pulse);
}


/**
******************************************************************
* @brief Toggle Power switch
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
void KeyRead( void )
{
        //uint8_t ReadData= (GPIO_ReadInputData(KEY_GPIO_PORT)^0xFF) & 0x0E ;
        unsigned char ReadData= (GPIO_ReadInputData(KEY_GPIO_PORT)^0xFF) & 0x0E ;
      Trg = ReadData & (ReadData ^ Cont);      
      Cont = ReadData;               
}


/**
******************************************************************
* @brief Toggle Power switch
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
void PowerEvent(void)
{
if ( Mode == OFF )             { Mode = ON;}
        else             { Mode = OFF; }
        ChangeFlag = 1;
}

/**
****************************************************************
* @brief Configures clocks
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
****************************************************************
*/
void LightPlus(void)
{
          if (DutyCycle == MAX)
          {
                  if (BlinkOfNumber == 0)          {BlinkOfNumber = 16;}
          }
          else
          {
                  DutyCycle = (DutyCycle + STEP);
                                SetTIM1_PWM_DutyCycle(DutyCycle);
                                SaveFlag = 1;
                                SaveDelay = (60 * Sec);
          }
}

/**
****************************************************************
* @brief Configures clocks
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
****************************************************************
*/
void LightReduce(void)
{
                  if (DutyCycle == MIN)
          {
                  if (BlinkOfNumber == 0 )   {BlinkOfNumber = 16;}
          }
          else
          {
                  DutyCycle = (DutyCycle - STEP);
                                SetTIM1_PWM_DutyCycle(DutyCycle);
                  SaveFlag = 1;
                                SaveDelay = (60 * Sec);
          }
}


/**
******************************************************************
* @brief Toggle Sw switch
* @par Parameters: None
* @retval void None
* @par Required preconditions: None
******************************************************************
*/
void SwEvent(void)
{
if ( Mode == ON )
             {
                       GPIO_WriteReverse(LED_GPIO_PORT, SW_4);
                       GPIO_WriteReverse(LED_GPIO_PORT, SW_5);
                       SwF = GPIO_ReadInputPin(LED_GPIO_PORT, SW_4);
                       SaveFlag = 1;
                       SaveDelay = (60 * Sec);
                       }

}

/**
******************************************************************
* @brief Write EEPROM by byte
* @param Start address
* @param Data
* @retval void None
******************************************************************
*/

void Write_Byte (unsigned int address,unsigned char Data)
{   
    FLASH->DUKR = 0xAE;
    FLASH->DUKR = 0x56;
    FLASH->CR2 = 0x00;
    FLASH->NCR2 = 0xFF;
    *((u8*)address) = Data;
    FLASH->IAPSR = (u8)(~0x08);
}




#ifdef USE_FULL_ASSERT
/**
* @briefReports the name of the source file and the source line number
*   where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
   ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* Infinite loop */
while (1)
{
}
}
#endif

smset 发表于 2013-8-16 15:55:42

holts2 发表于 2013-8-16 13:30 static/image/common/back.gif
我在stm8s103使用库,用到, 编绎正常,但程序不能正常运行,不知从何查起

定时器中断代码在哪里呢?

holts2 发表于 2013-8-16 21:09:36

smset 发表于 2013-8-16 15:55 static/image/common/back.gif
定时器中断代码在哪里呢?

在中断文件中

/**
* @brief Timer4 Update/Overflow Interrupt routine.
* @paramNone
* @retval None
*/
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
/* In order to detect unexpected events during development,
   it is recommended to set a breakpoint on the following instruction.
        */
        TimingDelay_Decrement();
      UpdateTimers();
/* Cleat Interrupt Pending bit */
TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
        }

smset 发表于 2013-8-17 14:15:55

Key_thread, 这个任务怎么没while(1)呢,这样只能启动时运行一次就结束了任务。


raosibin 发表于 2013-8-18 13:32:57

收藏,以待学习

bondxie3 发表于 2013-8-20 17:43:06

各位大侠,遇到需要挂起的任务怎么办呢?

smset 发表于 2013-8-20 18:49:44

bondxie3 发表于 2013-8-20 17:43 static/image/common/back.gif
各位大侠,遇到需要挂起的任务怎么办呢?

把它的定时器值设为255即可挂起,设为0即可恢复。

bondxie3 发表于 2013-8-21 09:18:02

谢谢smset楼主,一直在想有条件的启动或者挂起某个任务, 其实设置任务的定时器即可.

bondxie3 发表于 2013-8-21 16:57:58


u8 TaskB(void)
{
_SS
        WaitX(100);
        LED_ON();
        WaitX(100);
        LED_OFF();       
_EE       
}

u8 TaskA(void)
{
_SS
        while(1)
        {
                if(Flag)
                {
                        Flag=0;
                        CallSub(TaskB);
                }
                //...其他操作       
        }
_EE       
}

大侠,请问这种写法对吗,怎么总是进入TaskB呢?

bondxie3 发表于 2013-8-21 16:59:14


u8 TaskB(void)
{
_SS
        WaitX(100);
        LED_ON();
        WaitX(100);
        LED_OFF();       
_EE       
}

u8 TaskA(void)
{
_SS
        while(1)
        {
                if(Flag)
                {
                        Flag=0;
                        CallSub(TaskB);
                }
                //...其他操作       
        }
_EE       
}
[/ code]
再发

bondxie3 发表于 2013-8-21 17:00:02

大侠们说的发代码方法不行啊
u8 TaskB(void)
{
_SS
      WaitX(100);
      LED_ON();
      WaitX(100);
      LED_OFF();      
_EE      
}

u8 TaskA(void)
{
_SS
      while(1)
      {
                if(Flag)
                {
                        Flag=0;
                        CallSub(TaskB);
                }
                //...其他操作      
      }
_EE      
}

bondxie3 发表于 2013-8-21 17:01:38

呵呵,应该是这样啊.

代码
[/ code]
实际使用时去掉'/'后面的空格

bondxie3 发表于 2013-8-23 10:56:14

671楼的调用没有问题,是TaskB变量没有设置成static引起的.
我觉得只要不跨越Wait类的操作,变量可为临时变量.

smset 发表于 2013-8-23 11:56:32

是的,楼上说的没错。 不过尽量采用静态变量,就可以避免这类问题。

smset 发表于 2013-8-23 12:18:47

bondxie3 发表于 2013-8-23 10:56 static/image/common/back.gif
671楼的调用没有问题,是TaskB变量没有设置成static引起的.
我觉得只要不跨越Wait类的操作,变量可为临时变量 ...

建议用492楼的版本。 671楼的有潜在问题。

linbin250 发表于 2013-8-23 13:41:28

下次做东西的时候用用:)

holts2 发表于 2013-8-30 14:27:07

smset 发表于 2013-8-17 14:15 static/image/common/back.gif
Key_thread, 这个任务怎么没while(1)呢,这样只能启动时运行一次就结束了任务。




难怪编绎没报错,一切正常,就是不能用,原来是键盘

worldsing 发表于 2013-8-30 17:57:11

都快到700楼了,有没有详细测试过代码?
比如:
--------------------------------------------------------------------
unsigned chartask1(){
_SS
while(1){
   WaitX(500);
   while(TIMEOUT); //这是某个应用操作的超时等待;
   RevBit(LED1_PORT, LED1_PIN);
}
_EE
}

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

调度的时间变了。。。

smset 发表于 2013-8-30 18:31:42

WaitX(dtime) , dtime 必须小于255.

smset 发表于 2013-8-30 18:32:37

本帖最后由 smset 于 2013-8-30 18:37 编辑

--------------------------------------------------------------------
unsigned chartask1(){
_SS
while(1){
   WaitX(250);
   WaitX(250);
   while(TIMEOUT); //这是某个应用操作的超时等待;
   RevBit(LED1_PORT, LED1_PIN);
}
_EE
}
再试试看
------------------------------------------------------------------

另外,我很不建议你这里 while(TIMEOUT);

因为这个调度器不建议在任务里面死循环,不释放出去。如果所有任务都是协作式的,很可能这样做永远就在这里循环了。
--------------------------------------------------------------------
unsigned chartask1(){
_SS
while(1){
   WaitX(250);
   WaitX(250);
   while(TIMEOUT){
      WaitX(0);
   }
   RevBit(LED1_PORT, LED1_PIN);
}
_EE
}
------------------------------------------------------------------
你的逻辑,可以这样来做。

或者用信号量来实现,也是可以的。

bondxie3 发表于 2013-9-2 08:18:11

smset 发表于 2013-8-30 18:32 static/image/common/back.gif
--------------------------------------------------------------------
unsigned chartask1(){
_SS


while(TIMEOUT)
{
      WaitX(0);
}
这种方式有问题.使用如下方式才行
do
{
   WaitX(0);
}while( TIMEOUT );

可以把这种方式定义成一个宏:
#define WaitUntil(CondExpr,Cyc)                \
                do                                        \
                {                                        \
                        WaitX(Cyc);                \
                }while( !(CondExpr) )

guxingganyue 发表于 2013-9-15 17:55:16

我也来一层,有机会了再研究。

zishan 发表于 2013-9-16 08:47:07

个人觉得就是一个软timer,由于没有上下文切换导致"任务"不能while(),实时性很不强,实用性有待加强.

wswh2o 发表于 2013-10-12 11:38:33

vc6.0好像不支持case __LINE__这种用法~~,提示“case expression not constant”

smset 发表于 2013-10-12 12:39:59

wswh2o 发表于 2013-10-12 11:38 static/image/common/back.gif
vc6.0好像不支持case __LINE__这种用法~~,提示“case expression not constant”

支持的哦,你检查下是不是哪里设置有问题。

我以前就用过vc下编译protothread,可以参考这里:
http://www.amobbs.com/forum.php?mod=viewthread&tid=4077658&highlight=protothread

liujie14565 发表于 2013-10-15 23:13:54

smset 发表于 2013-10-12 12:39 static/image/common/back.gif
支持的哦,你检查下是不是哪里设置有问题。

我以前就用过vc下编译protothread,可以参考这里:


楼主 有3个问题请教下:
1. 有3个任务,Task0 1ms 执行一次Task13ms 执行一次Task310ms 执行一次    会重叠    怎么处理好一点,


2.有4个任务,都是10ms执行周期    例如 Task0执行一次后    10ms 后在执行Task0   10ms 执行一轮怎么处理好一点,

Elec_Ramble 发表于 2013-10-15 23:36:29

学习了…
来自:amoBBS 阿莫电子论坛 Windows Phone 7 客户端

mcuprogram 发表于 2013-10-17 21:34:29

smset 发表于 2012-12-21 11:57 static/image/common/back.gif
综合这几天的讨论,先更新一版,仅供评测用:主要改动有: 1) 增加了RunTaskA宏,让前面的任务有优先执行 ...

mark      

jsntzxh 发表于 2013-10-18 11:27:41

顶……………………

zl_123 发表于 2013-10-23 21:39:13

mark                                 

wujh 发表于 2013-10-24 00:00:08

翻了几页还是不懂,先mark

mvpgpz 发表于 2013-10-24 09:08:07

太好了 哈哈 收藏!

mathison 发表于 2013-10-25 12:10:18

本帖最后由 mathison 于 2013-10-25 12:11 编辑

谢谢 smset 大师 的分享
我正在尝试 将大师的调度器 改写一个已经量产的 电推剪的项目中
使用的 义隆 EM78P259 的ic

用了8年的汇编 尝试一下 C开发的痛苦和乐趣
如果改写后的代码能达到客户的要求会和大家分享代码
目前在补C语言关于c语言的书 smset大师有推荐吗 ?

smset 发表于 2013-10-25 13:10:38

mathison 发表于 2013-10-25 12:10 static/image/common/back.gif
谢谢 smset 大师 的分享
我正在尝试 将大师的调度器 改写一个已经量产的 电推剪的项目中
使用的 义隆 EM7 ...

大师不敢当,我本是屌丝一枚。
我以前学习C语言,看的是谭浩强的书。

smset 发表于 2013-10-25 13:24:35

liujie14565 发表于 2013-10-15 23:13 static/image/common/back.gif
楼主 有3个问题请教下:
1. 有3个任务,Task0 1ms 执行一次Task13ms 执行一次Task310ms 执行一次 ...

根据你的描述,总体上你还是在以定时器加状态机的思路在描述需求。

当然,也能用小小调度器任务机制来实现。只是不是真正多任务的思想。

如果你的任务是毫秒级的,那你应该把定时器中断周期减少到1毫秒,或者1毫秒以内。

比如:
第1点提到的3个任务,这个你就设计3个任务是可以的,或者简单点就设计一个任务,在这个任务里面实现三个任务的动作。

uchar TaskA(){
   static uchar count;
_SS
   count=0;
   while(1){
      WaitX(1);//等待1毫秒,定时器中断时间为1毫秒      
      count++;
   }
   if ((count%1)==0)task1proc();//任务1,1毫秒执行1次;
   if ((count%3)==0)task2proc(); //任务2,3毫秒执行1次;
   if ((count%10)==0) task3proc();//任务3,10毫秒执行1次;
_EE
}


如果4个任务之间有先后等待关系,你也可以用一个把这4个的任务执行动作做成4个函数,
然后用一个任务函数来实现。

baal 发表于 2013-10-25 14:27:18

时间片,系统,MARK

worldsing 发表于 2013-10-25 21:36:43

smset 发表于 2013-8-30 18:32 static/image/common/back.gif
--------------------------------------------------------------------
unsigned chartask1(){
_SS


嗯,这是可以也得到解决

但是这代码展开后应该是一个很长的函数调用关系

而不是真正意义的任务上调度器,当然也能完成

多任务,调度器应该做到任务有独立的空间,不限制

任务的操作。任务与任务独立,任务调度器隔离。

mathison 发表于 2013-10-26 16:41:37

本帖最后由 mathison 于 2013-10-26 16:44 编辑

再次感谢 smset
附上我在 义隆单片机上的移植
芯片用的是 EM78P259N
编译环境 使用 eUIDE

比较BC的C编译器
居然不支持在中断中使用 数组
我想是因为 EM78P259N 中断没有自动保存 PSR (R4)寄存器的缘故

所以我汇编改写了 UpdateTimers()

同理因为数组的原因 RunTask(task0,0);也不能放在中断中调用, PS:工程中并没有给出 RunTask(task0,0);的汇编实现,有兴趣的朋友可以自行修改

//UpdateTimers();
        {
        unsigned char i;
        for(i=0;i<MAXTASKS ;i++)
        {
                _asm
                        {
                                MOV        A,@%timers
                                MOV        RSR,A
                                MOV        A,%i
                                ADD        RSR,A
                                MOV        A,@255
                                SUB        A,R0
                                JBC        0x03,0x00
                                JMP        asm_end
                                MOV        A,@1
                                SUB        A,R0
                                JBS        0x03,0x00
                                JMP        asm_end
                                MOV        R0,A       
                        asm_end:       
                        }
               
        }
        }

mathison 发表于 2013-10-26 16:53:07

本人C开发新手
义隆的C编译器用起来真痛苦
有用C做义隆单片机开发的朋友吗 请问你们用什么编译器

追寻cheney 发表于 2013-10-26 19:14:50

下载学习,感谢楼主!!{:lol:}

jetli 发表于 2013-10-26 19:44:08

不明觉厉! 啊{:victory:}{:lol:}

zzz123456 发表于 2013-10-27 01:15:18

116 209 257 330 397 492 540 楼,楼主建议用492版。记号。

smset 发表于 2013-10-27 11:15:03

mathison 发表于 2013-10-26 16:41 static/image/common/back.gif
再次感谢 smset
附上我在 义隆单片机上的移植
芯片用的是 EM78P259N


不用谢,很支持你的做法!

因为小小调度器本来就是为小资源单片机而生的。

义隆单片机是很流行的小资源单片机,把小小调度器移植到这类单片机上去,并供他人借鉴参考,也是很有意义的。

liuqian 发表于 2013-10-28 10:59:54

从1楼一只看到最后,眼镜都麻了。我也是用时间那本书里面的框架,自己稍微改了改,发现LZ这个更实用。准备作个交通灯的项目,移植过去试试看,用freescale的8位机

tang0571 发表于 2013-10-28 11:15:57

好久不写程序了,还是要顶一下!
页: 1 2 3 4 5 6 [7] 8 9 10 11 12 13
查看完整版本: 再出个调度器,极小资源单片机值得一用