结合时间触发+消息+protothread思想+支持优先级的非抢占调度器

2019-12-13 18:20发布

本帖最后由 summarize 于 2013-5-19 14:47 编辑

废话少说,先上stm8s103 IAR库工程代码压缩包。
Schedule-IAR-STM8S103.rar (416.35 KB, 下载次数: 538) 2013-5-19 14:15 上传 点击文件名下载附件

工程是在stm8s103f3单片机上调度通过,已经用消息实现了 UART1_TX模块的共享,即UART1_RX接收到的数据+0x11后再通过UART_TX模块发送回去,同时ADC1 通道3的转换结果也通过UART1_TX模块发送出去.见下图

1.ADC1转换结果每1秒上传一次到PC。测试式给ADC1通道3供的是5V电,所以结果是0x03ff.即1023.

共享时接收到的数据.png (61.3 KB, 下载次数: 0) 下载附件 2013-5-19 14:16 上传

3.支持非抢占式优先级调度,优先级顺序就是创建任务时的顺序,由高到底。其实现思想是,每一个任务运行结束后,都重新回到第一个创建的任务处按顺序查找某个任务是否满足运行条件,所以先创建的任务会先被“发现”其满足运行条件并运行之,核心代码如下

a.任务控制块数据结构
  1. struct SchTcb
  2. {
  3. #if SCH_CFG_Q_EN > 0u
  4.   void          *pData;       //消息指针
  5.   SCH_UINT8 Size;         //消息大小
  6. #endif

  7.   SCH_DLY_TYPE        TimeCounter;  //定时计数器,时基为 "SCH_SYS_TICKS_MS"
  8.   void          (*pTask)();   //任务指针
  9.   struct SchTcb *pNextTCB;    //下一个任务控制块指针
  10. };
复制代码b.调度核心
  1. void SCHTaskSchedStart(void)
  2. {
  3. SCHED_SART:
  4.        
  5.   pCurTCB = pFirstTCB;                        //指向第一个创建的任务,之后按创建时的顺序执行下去

  6.   while (1)                                 
  7.   {
  8.     SCHTimeTick();                            //如果任务Tick满足条件,则将其置于可执行状态

  9.     if (SCH_TASK_RUN == pCurTCB->TimeCounter) //任务处于可执行状态
  10.     {
  11.       pCurTCB->TimeCounter = SCH_TASK_PEND;   //设置为挂起状态,保证任务只执行一次

  12.       pCurTCB->pTask();                       //执行当前任务控制块指向的任务

  13.       goto SCHED_SART;                        //每执行完一个任务,都重新查找一次可执行最高优先级任务
  14.     }

  15.     pCurTCB = pCurTCB->pNextTCB;              //指向下一个任务控制块,查找下个任务是否可执行
  16.   }
  17. }
复制代码“schedule.c”和"schedule.h"已经设置为只读属性,无特殊情况不建议修改,"sch_cfg.h"则为开放给用户的接口,可定义数据类型、调度器节拍和配置是否使用消息。

本人水平有限,欢迎大家测试、指正不足。

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
101条回答
kinsno
1楼-- · 2019-12-26 05:47
summarize 发表于 2013-12-21 18:30
你的理解基本正确,看下任务控制块结构体:

struct SchTcb

话说你的GOTO版本呢?

switch你说是可以在在非任务函数(包函BEGIN的那个函数)的其它任意函数内调用,如下:
void A(void)
{
        switch()
        {

        }
}

void B(void)
{
        A();
        switch()
        {

        }
}

void C(void)
{
        B();
        switch()
        {

        }
}

最后来一个包含BEGIN的任务,如下:

void Task(void)
{
        BEGIN();
        while(1)
        {
                A();
                B();
                C();
                Delay()或wait()
        }
        END();

}

但是我总是觉得这里面如果万一出现一点差错,就是毁灭性的打击啊!虽然号称是在非任务函数内可以使用!

在上贴中有提到过,你说会出一个版本是GOTO,何时亮剑?哈哈!敬待!


summarize
2楼-- · 2019-12-26 10:37
kinsno 发表于 2014-1-2 17:00
话说你的GOTO版本呢?

switch你说是可以在在非任务函数(包函BEGIN的那个函数)的其它任意函数内调用, ...



技术人员不应该说万一来假设吧,这个是没有万一的:不能使用"switch"是因为"SCHTaskBegin();"已经使用过一次"switch",编译通不过.展开后就清楚了,而在非任务函数中没有使用过"switch",所以能使用.

protothread的GOTO版本,我也是在本坛中看到其它帖子中有提到过.我也没有去仔细了解啊,不好意思了.

最近百事缠身啊.......
kinsno
3楼-- · 2019-12-26 14:43
 精彩回答 2  元偷偷看……
summarize
4楼-- · 2019-12-26 16:08
kinsno 发表于 2014-1-23 09:49
技术人员不说万一,我只是习惯性的一种怀疑自己,每一次打样,每一次产品,我都心惊胆颤,尤如初学者,哈哈,自 ...


1.理解你的心情,最核心的东西是参考了"Protothread"的,而"Protothread"是UIP的核心调度方式,本坛有不少相关帖子.

2.谢谢关心,是家人回家,我不回,帮忙看店,现在想在网上找黄牛搞7号,8号的回程票,但是不知道门路和怎么操作.
summarize
5楼-- · 2019-12-26 17:13
kinsno 发表于 2014-1-2 17:00
话说你的GOTO版本呢?

switch你说是可以在在非任务函数(包函BEGIN的那个函数)的其它任意函数内调用, ...

放狗跑了一下,找到了一个帖子,里面的回复提到了GOTO实现

http://bbs.ednchina.com/BLOG_ARTICLE_1902535.HTM

但是这GOTO是用汇编来搞定的,这样移植性就不好了.
kinsno
6楼-- · 2019-12-26 21:34
summarize 发表于 2014-1-23 10:35
放狗跑了一下,找到了一个帖子,里面的回复提到了GOTO实现

http://bbs.ednchina.com/BLOG_ARTICLE_1902535 ...

3KS,哈哈!

一周热门 更多>