首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

利用Protothread实现实时多任务系统(2)

利用Protothread实现实时多任务系统(2)

3 利用Protothread构造实时多任务系统
  与操作系统下的多任务不同,操作系统下的每个任务可在任意时刻被打断并阻塞,Protothread仅能在程序员指定位置阻塞。用Protothread实现实时多任务,正是利用了Protothread在指定位置阻塞的特点,让出执行权限给更高优先级的任务先运行。
  下面举例说明如何利用Protothread构造实时多任务系统。
  系统要求:
  TaskA实时任务,30 ms内响应,运行时间<20 ms;
  TaskB实时任务,200 ms内响应,运行时间<40 ms;
  TaskC非实时任务,响应时间无要求,运行时间>30 ms。
  设计思路:
  将TaskB和TaskC分成若干步,每步运行时间不超过10 ms(这个时间可视系统需求而定,例如TaskA若为40 ms内响应,则每步可扩至20 ms)。任务以3个Protothread的方式运行。首先执行TaskA,在TaskA执行完成1次后,释放执行权限,让TaskB和TaskC执行。TaskB或TaskC在每执行1步之前检查运行时间,一旦发现30 ms内不够执行1步时,阻塞运行,让出执行权限给TaskA。同样,TaskB和TaskC的调度关系也类似,先运行TaskB,完成时释放执行权限,让TaskC执行;TaskC在每执行1步之前检查运行时间,若发现200 ms内不够执行1步时,阻塞运行,让出执行权限重新交给TaskB。
  源程序(Task0TimeCounter、Task1TimeCounter为计数器,每毫秒加1):
  #include "ptsem.h"
  #define TASKA_MAX_RUN_TIME20
  #define TASKA_CYCLE_TIME30
  #define TASKB_CYCLE_TIME200
  #define TASK_STEP_TIME10
  #define TASK0_VALID_TIME TASKA_CYCLE_TIMETASK_STEP_TIME
  #define TASK1_VALID_TIME TASKB_CYCLE_TIMETASK_STEP_TIMETASKA_MAX_RUN_TIME *2
  /*按照PT_WAIT_UNTIL 的宏定义扩展一个新宏:当程序进入阻塞时发送一信号,告知高优先级任务获得执行权限*/
  #define LC_STEP_SET(s,n) s = __LINE__ + n; case __LINE__ + n:
  #define PT_SEM_WAIT_UNTIL(pt, s, condition, n)\
    do {
      LC_STEP_SET((pt)﹥lc,n);
      if(!(condition)) {if((s)﹥count==0)
        PT_SEM_SIGNAL(pt,s);
        return PT_WAITING;
      }
    } while(0)
  struct pt TaskAPt;
  struct pt TaskBPt;
  struct pt TaskCPt;
  struct pt_sem SemRunTaskA;
  struct pt_sem SemRunTaskB;
  /*若30 ms内已经不够时间执行1步,则让出TaskA的执行权限*/
  #define TASKB_STEP(pt) \
    PR_SEM_WAIT_UNTIL(pt, & SemRunTaskA,TaskOTimeCounter<=TASKO_VALID_TIME,0)
  /*若200 ms内已经不够时间执行1步,则让出TaskB的执行权限*/
  /*若30 ms内已经不够时间执行1步,则让出TaskA的执行权限*/
  #define TASKC_STEP(pt) \
    PT_SEM_WAIT_UNTIL(pt, &SemRunTaskB,Task1TimeCounter<=TASK1_VALID_TIME,0);\
    PT_SEM_WAIT_UNTIL(pt, &SemRunTaskA,Task0TimeCounter<=TASK0_VALID_TIME,1)
  int ProtothreadTaskA(struct pt *pt) {
    PT_BEGIN(pt);
    PT_SEM_WAIT(pt, &SemRunTaskA);/*等待其他任务让出执行权限*/
    ResetTask0TimeCounter;/*对时间计数器置0*/
    TaskA();/*TaskA任务*/
    PT_END(pt);
  }
  int ProtothreadTaskB(struct pt *pt) {
    PT_BEGIN(pt);
    PT_SEM_WAIT(pt, &SemRunTaskB);/*等待TaskC让出执行权限*/
    ResetTask1TimeCounter;/*对时间计数器置0*/
    TASKB_STEP(pt);/*如果不够1步执行,则阻塞,让出执行权限*/
    TaskB_1();/*TaskB任务的第1步*/
    TASKB_STEP(pt);
    TaskB_2();/*TaskB任务的第2步*/
    TASKB_STEP(pt);
    TaskB_3();/*…*/
    PT_END(pt);
  }
  int ProtothreadTaskC(struct pt *pt) {
    PT_BEGIN(pt);
    TASKC_STEP(pt);/*如果不够1步执行,则阻塞,让出执行权限*/
    TaskC_1();/*TaskB任务的第1步*/
    TASKC_STEP(pt);
    TaskC_2();/*TaskB任务的第2步*/
    TASKC_STEP(pt);
    TaskC_3();/*…*/
    TASKC_STEP(pt);
    TaskC_4();
    PT_END(pt);
  }
  void main(void) {/*系统初始化*/
    PT_INIT(&TaskAPt);
    PT_INIT(&TaskBPt);
    PT_INIT(&TaskCPt);
    PT_SEM_INIT(&SemRunTaskA,1);
    PT_SEM_INIT(&SemRunTaskB,1);/*运行任务*/
    while(1) {
      ProtothreadTaskA(&TaskAPt);
      ProtothreadTaskB(&TaskBPt);
      ProtothreadTaskC(&TaskCPt);
    }
  }
  模拟运行结果如表1所列。运行结果显示,3个任务的运行情况完全满足系统的设计要求。从资源需求来看,完成此例的系统设计,共需要12个字节的RAM空间。笔者进一步对Protothread定义文件做了少许修改和优化,最终仅耗费6个字节。
结语
  本文旨在解决资源紧张型应用的、多任务环境下的实时性问题。 通过借助Protothread的阻塞运行机制, 成功实现了低开销的实时多任务系统。
继承事业,薪火相传
返回列表