zoukankan      html  css  js  c++  java
  • 第4章 裸机系统和多任务系统

    在真正动手写RTOS之前,我们先来讲解下单片机编程中的裸机系统和多任务系统的区别。

    4.1 裸机系统

    裸机系统通常分为轮询系统和前后台系统,有关这两者的具体实现方式请看下面的讲解。

    4.1.1 轮询系统

    轮询系统即是在裸机编程的时候,先初始化好相关的硬件,然后让主程序在一个死循环里面不断循环,顺序完成各种事情,大概的伪代码具体见代码清单 4-1。轮询系统是一种非常简单的软件结构,通常只适用于那些只需要顺序执行代码且不需要外部事件来驱动就能完成的事情。在代码清单4-1中,如果只是实现LED翻转,串口输出,液晶显示等这些操作,那么适用轮询系统将会非常完美。但是,如果加入按键操作等需要检测外部信号的事件,用来模拟紧急报警,那么整个系统的实时响应能力就不会那么好了。假设DoSomething3是按键扫描,当外部按键被按下,相应于一个报警,这个时候,需要立马响应,并做紧急处理,而这个时候程序刚好执行到DoSomething1,要命的是DoSomething1需要执行的时间比较久,久到按键释放之后都没有执行完毕,那么当执行到DoSomething3的时候就会丢失掉一次事件。足见,轮询系统只适合顺序执行的功能代码,当有外部事件驱动时,实时性就会降低。

    代码清单 4-1 轮询系统伪代码

    int main(void)
    {
        /* 硬件相关初始化 */
        HardWareInit();
    
        /* 无限循环 */
        for(;;) {
            /* 处理事情1 */
            DoSomethin1();
    
            /* 处理事情2 */
            DoSomethin2();
    
            /* 处理事情3 */
            DoSomethin3();
        }
    }
    轮询系统伪代码

    4.1.2 前后台系统

    相比轮训系统,前后台系统是在轮系系统的基础之上加入了中断。外部事件的响应在中断里面完成,事件的处理还是回轮训系统中完成,中断在这里我们称为前台,main函数里面的无限循环我们称为后台,大概的伪代码见代码清单4-2。

    代码清单4-2 前后台系统伪代码

    int flag1 = 0;
    int flag2 = 0;
    int flag3 = 0;
    
    int main(void)
    {
        /* 硬件相关初始化 */
        HardWareInit();
    
        /* 无限循环 */
        for(;;) {
            if(flag1) {
                /* 处理事情1 */
                DoSomethin1();
            }
            
            if(flag2) {
                /* 处理事情2 */
                DoSomethin2();
            }
    
            if(flag3) {
                /* 处理事情3 */
                DoSomethin3();
            }
        }
    }
    
    void ISR1(void)
    {
        /* 置位标志位 */
        flag1 = 1;
    
        /* 如果事件处理时间很短,则在中断里面处理
           如果事件处理事件较长,则回到后台处理   */
        DoSomethin1();
    }
    
    void ISR2(void)
    {
        /* 置位标志位 */
        flag2 = 1;
    
        /* 如果事件处理时间很短,则在中断里面处理
           如果事件处理事件较长,则回到后台处理   */
        DoSomethin2();
    }
    
    void ISR3(void)
    {
        /* 置位标志位 */
        flag3 = 1;
    
        /* 如果事件处理时间很短,则在中断里面处理
           如果事件处理事件较长,则回到后台处理   */
        DoSomethin3();
    }
    前后台系统伪代码

    在顺序执行后台程序的时候,如果有中断来临,那么中断会打断后台程序的正常执行流,转而去执行中断服务程序,在中断服务程序里面标记事件,如果事件要处理的事情很简短,则可在中断服务程序里面处理,如果事件要处理的事情比较多,则返回到后台程序里面处理。虽然事件的响应和处理是分开了,但是事件的处理还是在后台里面顺序执行的,但相比轮序系统,前后台系统确保了事件不会丢失,再加上中断具有可嵌套的功能,这可以大大的提高程序的实时响应能力。在大多数中小项目中,前后台系统运用的好,堪称有操作系统的效果。

    4.2 多任务系统

    相比前后台系统,多任务系统的事件响应也是在中断中完成的,但是事件的处理是在任务中完成的。在多任务系统中,任务跟中断一样,也具有优先级,优先级高的任务会被优先执行。当一个紧急的事件在中断被标记后,如果事件对应的任务的优先级足够高,就会立马得到响应。相比前后台系统,多任务系统的实时性又被提高了。多任务系统大概的伪代码具体见代码清单4-3

    代码清单4-3 多任务系统伪代码  

    int flag1 = 0;
    int flag2 = 0;
    int flag3 = 0;
    
    int main(void)
    {
        /* 硬件相关初始化 */
        HardWareInit();
    
        /* OS 初始化 */
        RTOSInit();
    
        /* OS 启动,开始多任务调度,不再返回 */
        RTOSStart();
    
    }
    
    void ISR1(void)
    {
        /* 置位标志位 */
        flag1 = 1;
    }
    
    void ISR2(void)
    {
        /* 置位标志位 */
        flag2 = 1;
    }
    
    void ISR3(void)
    {
        /* 置位标志位 */
        flag3 = 1;
    }
    
    void DoSomethin1(void)
    {
        /* 无限循环,不能返回 */
        for(;;) {
            /* 任务实体 */
            if(flag1) {
    
            }
        }
    }
    
    void DoSomethin2(void)
    {
        /* 无限循环,不能返回 */
        for(;;) {
            /* 任务实体 */
            if(flag2) {
    
            }
        }
    }
    
    void DoSomethin3(void)
    {
        /* 无限循环,不能返回 */
        for(;;) {
            /* 任务实体 */
            if(flag3) {
    
            }
        }
    }
    多任务系统伪代码

    相比前后台系统中后台顺序执行的程序主体,在多任务系统中,根据程序的功能,我们把这个程序的主体分割成一个个独立的,无限循环且不能返回的小程序,这个小程序我们称之为任务。每个任务都是独立的,互不干扰的,且具备自身的优先级,它由操作系统调度管理。加入操作系统后,我们在编程的时候,不需要精心地去设计程序执行流,不用担心每个功能模块之间是否存在干扰。加入了操作系统,我们的编程反而变得简单了。整个系统随之带来的额外开销就是操作系统占据的那一丁点的FLASH和RAM。现如今,单片机的FLASH和RAM是越来越大,完全足以抵挡RTOS那点开销。

    无论是裸机系统中的轮询系统、前后台系统和多任务系统,我们不能一锤子敲定孰优孰劣,它们是不同时代的产物,在各自的领域都还有相当大的应用价值,只有适合才是最好。有关这三者的软件模型区别具体见表格4-1。

    表格4-1 轮询、前后台、多任务系统软件模型区别

    模型 事件响应 事件处理 特点
    轮询系统 主程序 主程序 轮询响应事件,轮询处理事件
    前后台系统 中断 主程序 实时响应事件,轮询处理事件
    多任务系统 中断 任务 实时响应事件,实时处理事件
  • 相关阅读:
    Qt中的SIGNAL和SLOT
    Android单个模块编译
    decoupling of objetctoriented systems
    设计模式之Objectifier
    代码示例:调用SPS提供的remoting服务,在线把Office文档转换成html文档
    利用WSS做后台存储设计一个统一的信息发布平台
    元数据(metadata)在企业应用开发中的作用
    面向对象的软件设计中应当遵守的原则
    使用NUnit在.Net编程中进行单元测试
    最近在使用sps类库过程中发现了一个让我比较疑惑的问题(有关items属性的)
  • 原文地址:https://www.cnblogs.com/doitjust/p/10910181.html
Copyright © 2011-2022 走看看