在底层代码编写中,初始的框架设计总会面临选择,针对实际的硬件使用环境,大家对于使用的软件框架有很多选择,今天我简单描述一些比较常用的架构,让大家能够理解并选择合适的架构。

    总述

    1. 简单的顺序执行程序:这类写法是大多数人使用的方法,不需用思考程序的具体架构,直接按照执行顺序编写应用程序即可。

    2. 前后台执行程序: 在顺序执行的情况上增添中断前台处理机制,配置顺序执行的后台大循环程序, 组合成可以实时响应的程序。

    3. 时间片轮循法: 在前后台的执行架构上,通过计数器进一步规划程序,定时执行特定的片段。

    4.**实时 ** 操作系统: 实时操作系统又叫 RTOS,实时性,RTOS 的内核负责管理所有的任务,内核决定了运行哪个任务,何时停止当前任务切换到其 他任务,这个是内核的多任务管理能力。多任务 管理给人的感觉就好像芯片有多个 CPU,多任务管理实现了 CPU 资源的最大化利用,多任务管理有助于实现程序的模块化开发,能够实现复杂的实时应用。

    除了实时性,还有可剥夺内核,顾名思义就是可以剥夺其他任务的 CPU 使用权,它总是运行就绪任务中的优先级最高的那个任务。

    1. 简单的顺序执行程序

    这种应用程序比较简单,一般作为初阶简单使用,实时性以及要求不太高的情况下,可以使用。程序的设计比较简单,思路比较清晰。但是主循环的逻辑比较复杂的时候,如果没有完整的流程图指导,其他人很难看懂程序运行逻辑。

    下面写一个顺序执行的程序模型

    1. int main(void)
    2. {
    3. uint8 TaskValue;
    4. InitSys(); // 初始化
    5. while (1)
    6. {
    7. TaskValue= GetTaskValue();
    8. switch (TaskValue)
    9. {
    10. case x:
    11. TaskDispStatus();
    12. break;
    13. ...
    14. default:
    15. break;
    16. }
    17. }
    18. }

    2. 前后台执行程序

    【嵌入式】软件开发框架 - 图1

    这种程序特点是,后台大循环中一直执行默认的程序,中断服务程序(ISR)产生相应中断标记,主程序运行与中断标记相关联的任务程序。一般实现有如下思路:

    通过设置标志变量,然后在前台响应中断的时候进行对标志变量的置位或者复位,实现事件的信号获取,再在后台主循环进行中断所对应事物或者数据的处理,将程序流程转移到主程序。

    前后台执行的程序

    1. void IRQHandler(void)
    2. {
    3. if(GetITStatus == 1)
    4. {
    5. SysFlag = 1;
    6. GetITStatus = 0;
    7. }
    8. }
    9. int main(void)
    10. {
    11. uint8 TaskValue;
    12. InitSys();
    13. while (1)
    14. {
    15. TaskValue= GetTaskValue();
    16. switch (TaskValue)
    17. {
    18. case x:
    19. if(SysFlag == 1)
    20. {
    21. TaskDispStatus();
    22. SysFlag == 0;
    23. }
    24. break;
    25. ...
    26. default:
    27. break;
    28. }
    29. }
    30. }

    3. 时间片轮循架构

    时间片轮循法,大家看到它的时候,一般会将它与操作系统进行比较。不是说操作系统包含这种方法,而是在前后台程序中配合时间管理形成时间片轮循架构。

    这种架构已经最大限度接近 RTOS,时间管理,中断管理,任务管理,已经都有了,只不过 RTOS 会对内核进行更深入的修改,有针对 delay 延时的线程切换,抢占式任务切换这些更为复杂一些的功能等。

    【嵌入式】软件开发框架 - 图2

    时间片轮循程序

    时间片管理主要是通过对定时多处复用,在定时器计数,定时进行标志位的变化,继而主程序对标志真假的判断,实现不同时间不同任务状态执行。

    因为此架构代码比较好,我适当进行详细描述。

    step

    1:初始化相应的定时器:注意设置定时器的间隔频率,可以按照芯片的性能设置。例如,设置定时中断为 1ms,也可以设置为 10ms,轮循架构中的定时器部分与操作系统的定时器部分具有一样的功能,中断过于频繁,影响主程的序执行效率;中断间隔过长,实时响应效果差。

    2:针对定时器运行的任务设置一个函数结构体标志,用来在定时程序进行时间计数以及标志操作。

    1. #define TaskTAB_NUM 6
    2. __packed typedef struct{
    3. u8 flag;
    4. u32 numcount;
    5. u32 target;
    6. int(*fun)(void);
    7. }TaskTimTypeDef

    step

    3:建立一个任务表,通过结构体表的设置,确定任务执行的时间表。

    在定义变量时,我们已经初始化了值,这些值的初始化,非常重要,跟具体的执行时间优先级等都有关系,这个需要自己掌握。

    1. static TaskTimTypeDef TaskTimTab[TaskTAB_NUM] =
    2. {
    3. {1, 0, 30000, *Task00},
    4. {1, 0, 3000, *Task01},
    5. {1, 0, 300, *Task02},
    6. {1, 0, 30, *Task03},
    7. {1, 0, 3, *Task04},
    8. {1, 0, 0xFFFFFFFF, *Task05},
    9. };
    10. int Task00(void)
    11. {...}
    12. int Task01(void)
    13. {...}
    14. int Task02(void)
    15. {...}
    16. int Task03(void)
    17. {...}
    18. int Task04(void)
    19. {...}
    20. int Task06(void)
    21. {...}

    step

    4:定时中断服务函数,按照我们需要的时间以及标志操作进行计时。

    1. void TimerInterrupt(void)
    2. {
    3. for(char i=0; i<TaskTAB_NUM; i++)
    4. {
    5. if(TaskTimTab[i].flag == 1)
    6. {
    7. (TaskTimTab[i].numcount< TaskTimTab[i].target)
    8. ?(TaskTimTab[i].numcount++):(TaskTimTab[i].flag = 0);
    9. }
    10. }
    11. }

    step

    5:主函数进行任务函数执行。

    1. int main(void)
    2. {
    3. InitSys();
    4. while (1)
    5. {
    6. for(char i=0; i<TaskTAB_NUM; i++)
    7. {
    8. if(TaskTimTab[i].flag == 0)
    9. {
    10. if(TaskTimTab.flag == 0)
    11. {
    12. TaskTimTab[i].flag = 1;
    13. TaskTimTab[i].numcount= 0;
    14. TaskTimTab[i].fun();
    15. }
    16. }
    17. }
    18. }

    4. 操作系统 RTOS

    嵌入式操作系统是更加优化的执行框架,针对多任务,功能复杂,扩展性要求强项目的代码有非常好的使用。RTOS 是针对不同处理器优化设计的高效率实时多任务内核,RTOS 可以面对几十个系列的嵌入式处理器 MPU、MCU、DSP、SOC 等提供类同的 API 接口,这是 RTOS 基于设备独立的应用程序开发基础。因此,基于 RTOS 的 C 语言程序具有极大的可移植性。目前针对微嵌入式或者单片机的操作系统有VxWorksUCOS、Free RTOS、国产的 RTT,这些操作系统大同小异,基本的功能都类似:任务管理、任务间同步和通信、内存管理、实时时钟服务、中断管理服务

    【嵌入式】软件开发框架 - 图3

    (图片来源博客)

    RTOS 在时间轮循的架构上继续增加了任务挂起以及恢复,阻塞切换线程等,属于功能累加,进一步的优化。由于本次不是对 RTOS 的讲解,本人学习应用有 UCOS、RTT、Free RTOS 几个操作系统,因为篇幅有限,时间有限,我抽时间再进行详细的 RTOS 系统架构学习等的介绍

    目前 RTOS 系统有很多,很多项目都倾向于使用 RTOS,但是通过几种架构的分析明白不同的项目需要不同的架构,并不是所有项目都需要,也都适合使用 RTOS,例如项目中各个任务耦合性过大,如果用 RTOS 需要很多的任务同步,甚至都无法进行线程的规划。这样就完全失去 RTOS 意义,此时用某些裸机的架构反而更合适。

    —————— END ——————
    https://mp.weixin.qq.com/s?__biz=MzI4MDI4MDE5Ng==&mid=2247495425&idx=1&sn=344b47268782416cefd030f01aab6480&chksm=ebb842eadccfcbfc4924f351ede4a7212b778153a952b57736c0fb9f6f9150c035f1791882cd&mpshare=1&scene=23&srcid=1129kawNsg3sSFt5XtxcTMLA&sharer_sharetime=1606663493470&sharer_shareid=6e6cc16fbf9fdd9f3694ccb7b223e719#rd