打印

老生常谈---一种裸奔多任务模型

[复制链接]
30058|143
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dld2|  楼主 | 2008-6-21 11:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一种裸奔多任务模型

一个网友的总结:stateMachine + timerTick + queue。

在RTOS环境下的多任务模型:
任务通常阻塞在一个OS调用上(比如从消息队列取数据)。
外部如果想让该任务运转,就要向消息队列发送消息。
任务收到消息时,根据当前状态,决定如何处理消息。这就是状态机。
任务将消息队列中的消息处理完毕后,重新进入阻塞状态。
任务在处理中,有时要延时一段时间,然后才继续工作:
    为了充分使用CPU,可以通过OS调用让其它任务去工作。
    OS通常会提供一个taskDelay调用。
    当任务调用taskDelay时,即进入阻塞状态,直到超时,才重新进入可工作状态(就绪状态)。

下面说说裸奔环境下的多任务模型:
裸奔也可以多任务,但调度是由用户自主控制。
在RTOS环境下,一般提供抢占式调度。在裸奔时,一般是任务在处理告一段落后,主动结束处理。
RTOS环境下的任务,一般处于一个while(1)循环中。
    while(1){
        从消息队列接收消息。如果没有,将阻塞。
        处理消息。
        }
裸奔下的任务,一般采用查询方式:

    查询是否有待处理的事件。
    如果没有,返回。
    如果有,根据任务的当前状态,进行处理。处理完毕后,可能返回,也可能将待处理事件全部处理完毕后再返回。

裸奔任务其实也处于一个while(1)循环中,只不过这个循环在任务外部。
main()
{
    A_taskInit();        //任务的初始化
    B_taskInit();
    ...
    while(1){
        A_taskProc();    //任务的处理
        B_taskProc();
        }


状态机既适用于OS环境,也适用于裸奔环境。
但在裸奔环境下,状态可能被切分得更细。例如后面讲的如何在裸奔环境实现taskDelay()。

消息队列既适用于OS环境,也适用于裸奔环境。
在OS环境下,消息队列机制由OS提供。
在裸奔环境下,消息队列要自己来实现。如果对队列的概念不清楚,可参考《数据结构》教材。
这个队列机制,可做成通用模块,在不同的程序中复用。
消息队列用于缓冲事件。事件不知道什么时候会到来,也不能保证来了就能迅速得到处理。
    使用消息队列,可以保证每个事件都被处理到,以及处理顺序。
一般在两种情况下会用到消息队列:
    存储外部事件:外部事件由中断收集,然后存储到队列。
        串口接收程序中的接收循环缓冲区,可理解为消息队列。
    任务间通讯:一个任务给其它任务发送消息。

timerTick,就是系统中的时钟基准。OS中总是有一个这样的基准。
在裸奔时,我们要用一个定时器(或RTC或watchdog)来建立这个时间基准。
一个tick间隔可以设置为10ms(典型RTOS的缺省设置)。让定时器10ms中断一次,中断发生时给tickNum++。
    以前,我在定时器中断中设置1S标志、200ms标志等等。时间相关的任务根据这些标志判断是否要执行。
    近来,一般让任务直接去察看tickNum。两次相减来判断定时是否到达。
    也可以在系统中建立一个通用定时器任务,管理与不同任务相关的多个定时器;在定时到达时,由定时器任务去调用相应的callback。
系统时钟基准是所谓“零耗时裸奔”的基础。
timerTick的分辨率,决定了只适于于较大的时间延时。
    在做时序时的小延时,用传统方法好了。

OS中的taskDelay()在裸奔环境下的一种实现:
OS环境:
void xxxTask(void)
{

    while(1){
        //waitEvent

        //do step_1

        taskDelay(TIME_OUT_TICK_NUM);

        //do step_2
    }

裸奔环境:
void xxxTask(void)
{
    static unsigned int taskStat = STAT_GENERAL;    //任务状态变量
    static timer_t startTick;
    timer_t currTick;
    
    if (taskStat == STAT_GENERAL)
    {
        //check event

        //if no event
            return;

        //do step_1

        startTick = sysGetTick();    //sysGetTick()就是察看系统时间
        taskStat = STAT_WAIT;
        return;
    }
    else if (taskStat == STAT_WAIT)
    {
        currTick = sysGetTick();    //sysGetTick()就是察看系统时间
        if ((currTick - startTick) >= TIME_OUT_TICK_NUM)
        {
            //do step_2    

            taskStat = STAT_GENERAL;
            return;
        }
        else
            return;
    }
}

相关帖子

沙发
桂电飞天鼠| | 2008-6-21 11:56 | 只看该作者

好帖,收藏下~

使用特权

评论回复
板凳
hotpower| | 2008-6-21 13:53 | 只看该作者

最近天气很热需要裸奔~~~

使用特权

评论回复
地板
soso| | 2008-6-21 14:33 | 只看该作者

RE:

timer_t是什么变量类型

使用特权

评论回复
5
dld2|  楼主 | 2008-6-21 14:39 | 只看该作者

re 4 楼

#define timer_t unsigned long

使用特权

评论回复
6
古道热肠| | 2008-6-21 17:01 | 只看该作者

说得不错,定时器管理很重要

定时器回调功能函数,通过信号量与主程序交换消息比较方便.

使用特权

评论回复
7
huangqi412| | 2008-6-22 11:01 | 只看该作者

标记

使用特权

评论回复
8
wxj1952| | 2008-6-22 19:46 | 只看该作者

OS的多任务是跳跃优选的。

 6楼更快。受启发了。

使用特权

评论回复
9
forthlab| | 2008-6-22 20:47 | 只看该作者

现在基本都是按照这个模式裸奔的

                     

使用特权

评论回复
10
程序匠人| | 2008-6-22 22:47 | 只看该作者

潜力贴,加裤子,置顶

使用特权

评论回复
11
dld2|  楼主 | 2008-6-23 03:52 | 只看该作者

谢匠人青眼有加

Italy Vs Spain,巨沉闷。

使用特权

评论回复
12
原野之狼| | 2008-6-23 09:09 | 只看该作者

如此好贴

得顶。
消息队列要做成:
1、环形
2、动态长度。

使用特权

评论回复
13
古道热肠| | 2008-6-23 10:22 | 只看该作者

贴个代码能大家评说

uchar ucDisplayBarStatus;
uchar ucDisplayLength;        //显示长度

#define c_StatusBar_Start        1
#define c_StatusBar_Scroll         2
#define c_StatusBar_Off         3
uchar  ucLoopCount;
uchar code ucStatusDispInformation[] = " WWW.21IC是一个好地方,欢迎大家经常光临侃单片机版块,古道热肠版主研制Ver(1.00)                ";
//滚动显示帮助信息
void ScrollDisplayHelp(void)
{

    if(ucDisplayBarStatus == c_StatusBar_Start)
    {
        //启动状态态显示进程
        ucDisplayLength = 0;
        LcdShowString(4,1,ucStatusDispInformation);
        //启动定时器1进行延时
        bDelayCompleteFlag_T1 = false;
        TmrCfgFnct(1, Tmr1TDisp_P1, (void *)0);                  /* Execute when Timer #1 times out          */
        TmrSetMST(1,0, 0, 1); 
        TmrStart(1);

        ucDisplayBarStatus = c_StatusBar_Scroll;
    }
    if(ucDisplayBarStatus == c_StatusBar_Scroll)
    {
        if(bDelayCompleteFlag_T1)    //定时操作完成
        {
            bDelayCompleteFlag_T1 = false;
            ucDisplayLength += 2;
            if(ucDisplayLength > (strlen(ucStatusDispInformation)-16))    //结束滚动显示
            {
                ucDisplayBarStatus = c_StatusBar_Off;    //关闭显示    
                LcdShowString(4,1,"                ");
            }
            else
            {
                LcdShowString(4,1,ucStatusDispInformation+ucDisplayLength);
                TmrSetMST(1,0, 0, 1); 
                TmrStart(1);
            }
        }
    }

}

系统有空闲循环调用此函数,滚动节拍由定时值控制,采用状态机,CPU活得很滋润,还可以干其它的很多事.
哈哈,"裸奔"其实也是要讲究艺术的.

使用特权

评论回复
14
gyt| | 2008-6-23 10:52 | 只看该作者

不错不错

使用特权

评论回复
15
dld2|  楼主 | 2008-6-23 11:38 | 只看该作者

关于数码管显示的一个想法

通常,我们在需要显示什么内容的时候,直接调用底层显示函数去显示。
后来,考虑借鉴framebuffer方式。在此方式下,更新显示时直接向framebuffer写入相应的点阵数据;专门的显示任务(或硬件操作)完成底层处理。

例如:
有8个数码管,对应8个字节的显示缓冲。当应用程序需要更新显示时,写显示缓冲。
如果数码管是定时刷新的,则显示驱动任务定时从显示缓冲读数据来刷新显示。
如果数码管是改变时才刷新的,则应用程序在写显示缓冲之后,要给显示驱动任务传递一个事件(例如一个更新标志)。显示驱动任务在收到事件时更新显示。

这样,有利于把比较费时间的显示工作做成零耗时的状态机。

嘿嘿,可能是通用做法,但俺不知道。

使用特权

评论回复
16
农民讲习所| | 2008-6-23 11:48 | 只看该作者

看俺的〈建立MCU通用处理程序〉就够了

这些俺都讲过,系统化和理论化。

使用特权

评论回复
17
dld2|  楼主 | 2008-6-23 12:04 | 只看该作者

呵呵,俺从所长这里学到很多东西

实际工作中简化了很多。

使用特权

评论回复
18
liyli2003| | 2008-6-23 12:43 | 只看该作者

好贴,要留记号

使用特权

评论回复
19
wxj1952| | 2008-6-23 20:20 | 只看该作者

没人唱反调,大家都一样就没什么意思。

那岂不是“既生瑜,何生亮。”都成了多余的人。如今人口众多,到处都是50年不遇的气候。

我试试故意找茬:

做OS的是外国高手,做裸奔的是中国高手。两者的差别在那里?
1、中国的高手追求的是自我实现,自己的美感,或者简约,或者艺术。很少想到别人会怎么做,还有会与自己想法不同的人。

2、外国的高手,我发现他们的程序处处体现了一种东西——可靠性。他们做到哪都在想:如果程序在这里发生崩溃,我(们)将怎么办?于是,他们能做出嵌入式OS,能产生微软。

中国的高手水平其实一点都不差,但是中国为什么不能做出OS,甚至简单的嵌入式OS?好像韩国、日本都有自己的OS,都能独立,不靠微软。

其实中科院不是做不出中国的windows ,而是做的人喜欢自由发挥,追求自己的美感,——裸奔。结果是奔出来的程序功能上能够实现,就是动不动死机。他不是按照可靠性整套规则去设计的。

什么时候中国人有了更多的软件设计规则,设计出更多的可靠性模块,......

发现北京为了奥运添了不少建筑。有些房子一看就是本土设计的,又贵又难看。有些一看就是外国的建筑师设计的。简约,大气。其实不是中国的建筑师没有审美观,而是他只顾自己自由发挥,不知道有很多前人设计成熟的漂亮模块可以拿来就用的。而外国的设计师不是艺术创新能力怎么样,而是他看得多,知道前人众多大师是怎么干的,他学(仿)得好,他“积木”搭的好,不是他自由创新的好。

刚看了2本中外专家写的汇编语言教材,中国写、教得最好的大概是王爽教授了。他写的教材可以有200篇书评,全是美誉。可是书中根本没有谈到CPU的特权级保护内容,——这个Windows操作系统的可靠性设计依赖。

看完另一本外国人写的CPU特权级保护内容,另样感觉:竟然脆弱的CPU的可靠性设计解决是采用这种设计方法,他们怎么想得到!

使用特权

评论回复
20
菜人菜语| | 2008-6-23 20:42 | 只看该作者

哈哈,楼上真能扯

~~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

74

主题

2442

帖子

3

粉丝