嵌入式底层开发的软件框架简述

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

总述

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

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

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

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

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

1.简单的顺序执行程序

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

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

int main(void) { uint8 TaskValue; InitSys(); // 初始化     while (1)         {         
      TaskValue= GetTaskValue();              switch (TaskValue)             {                  case x:      TaskDispStatus();      break;                  ...                  default:        break;              }        } }
2.前后台执行程序

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

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

前后台执行的程序

void IRQHandler(void){  if(GetITStatus == 1)  {     SysFlag = 1;    GetITStatus = 0;  }}int main(void) {          uint8 TaskValue;         InitSys();                  // 初始化        while (1)         {      TaskValue= GetTaskValue();               switch (TaskValue)              {                     case x:           if(SysFlag == 1)          {            TaskDispStatus();             SysFlag == 0;           }        break;                     ...                     default:        break;               }        } }
3.时间片轮循架构

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

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

时间片轮循程序

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

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

step

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

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

#define TaskTAB_NUM  6 //任务数量__packed typedef struct{  u8 flag;  //定时标志  u32 numcount;//按照定时中断进行计数  u32 target;  //设置的定时目标数值  int(*fun)(void);//设置定时执行的目标任务函数}TaskTimTypeDef

step

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

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

/*MdmSendTimTab任务函数默认周期,单位5ms,TIM7*/static TaskTimTypeDef TaskTimTab[TaskTAB_NUM] ={                                                 {1, 0, 30000,      *Task00},          //Task00 3000数值是设置的定时目标值,如果觉得反应过慢,可以将此值设置小  {1, 0, 3000,       *Task01},          //Task01  {1, 0, 300,        *Task02},          //Task02  {1, 0, 30,         *Task03},          //Task03  {1, 0, 3,          *Task04},          //Task04  {1, 0, 0xFFFFFFFF, *Task05},          //Task05    //可以按照TaskTAB_NUM数量添加任务};int Task00(void)//按照结构体的函数模板(int(*fun)(void);)写任务函数{...}//假设执行按键操作int Task01(void){...}//假设执行USART发送任务int Task02(void){...}//假设执行CAN通讯int Task03(void){...}//假设执行继电器控制int Task04(void){...}//假设执行网络解析int Task06(void){...}//假设执行空

step

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

 //定时中断服务函数 void TimerInterrupt(void) {    for(char i=0; i<TaskTAB_NUM; i++) { if(TaskTimTab[i].flag == 1) {           (TaskTimTab[i].numcount< TaskTimTab[i].target)//比较目前定时计数与目标时间 ? (TaskTimTab[i].numcount++):(TaskTimTab[i].flag = 0); } } }

step

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

int main(void) {        InitSys();                  // 初始化       while (1)       {                 for(char i=0; i<TaskTAB_NUM; i++)//// 任务处理            {        if(TaskTimTab[i].flag == 0)        {          if(TaskTimTab.flag == 0)          {            TaskTimTab[i].flag  = 1;            TaskTimTab[i].numcount= 0;            TaskTimTab[i].fun();          }        }  } } 
4.操作系统RTOS

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

(图片来源博客)

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

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

扫描二维码获取更多信息

文章:良知犹存

排版:良知犹存

校稿:回梦游先

(0)

相关推荐

  • 单片机非RTOS时,临界区保护的实现办法

    嵌入式专栏 153篇原创内容 公众号 来源 | 痞子衡嵌入式 今天给大家分享的是Cortex-M裸机环境下临界区保护的三种实现. 搞嵌入式玩过 RTOS 的朋友想必都对 OS_ENTER_CRITIC ...

  • RTOS 任务入口函数执行完之后去哪里了?

    RTOS 任务入口函数执行完之后去哪里了?

  • 图解FreeRTOS 原理系列之任务管理器基本框架

    本文主要学习梳理FreeRTOS任务管理器的基本原理,大体框架. 内核任务管理器需求 先来对比一下裸奔系统与RTOS应用系统的编程模型,看看两种编程的不同画风. 裸奔系统 在不用RTOS的单片机应用开 ...

  • RTOS任务的堆栈大小与代码量有关吗?

    最近有小伙伴问了这样一个问题:我有个任务中的代码量很多,是不是这个任务的堆栈需要分配很大才行? 下面就围绕任务代码量,以及堆栈进行描述相关内容. 1RTOS任务堆栈分配 市面上很多RTOS的任务都是需 ...

  • 嵌入式软件底层开发的框架陈述

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

  • 嵌入式驱动开发到底学什么

    嵌入式大体分为以下四个方向: 一.嵌入式硬件开发:熟悉电路等知识,非常熟悉各种常用元器件,掌握模拟电路和数字电路设计的开发能力.熟练掌握嵌入式硬件知识,熟悉硬件开发模式和设计模式,熟悉ARM32位处理 ...

  • 通用为因起火风险而召回的EV Bolt开发诊断软件

    通用汽车称其工程师已经找到补救措施来解决先前发现的电池隐患问题. 据悉,经销商将利用通用汽车开发的诊断工具来识别潜在的电池异常,并在必要时更换出现故障的电池模块部件.除此之外,通用还将在这些车辆中安装 ...

  • Python Web开发有哪些框架?五大框架

    想必很多人都知道Python语言,Python是一门非常不错的编程语言,在爬虫.数据分析.人工智能领域有着非常不错的作用,初次之外,我们熟知的web开发也是Python的应用领域之一,那么你知道Pyt ...

  • 陈根:研究开发新软件——高效处理基因数据

    文/陈根 现代医学的发展,让基因表达得以检测,其最经典的方法是根据在细胞或生物体中所观察到的生物化学或表型的变化来决定某种特定基因是否表达.大分子分离技术的进步,使得特异的基因产物或蛋白分子的识别和分 ...

  • Microsoft Office(微软公司开发办公软件Microsoft Office)

    Microsoft Office office一般指Microsoft Office 微软公司开发办公软件Microsoft Office共5个含义 微软公司开发办公软件Microsoft Offic ...

  • 谷歌“驾到”,现可通过所有主要量子软件框架访问IonQ!

    当地时间6月10日,IonQ宣布与谷歌开源量子计算框架Cirq全面整合.   且大众集团已经通过Cirq在IonQ上运行了"油漆车间调度问题" (paint shop proble ...

  • 直播源码开发+直播软件搭建+直播平台搭建

    在当前大市场的环境下,直播软件搭建有着庞大的潜在市场,用户量的增长让资本市场的加入越来越多,正是赶上社交直播软件开发的好时期. 直播软件搭建,采集 编码 推流. 首先是采集.目前最常见的两种采集方法是 ...

  • 总结了一份嵌入式硬件开发的具体流程

    李肖遥 技术让梦想更伟大 1周前 来源:网络素材 整理:李肖遥 传送门 : 总结了一份嵌入式产品研发的具体流程 之前,我们详细讲述了嵌入式产品的研发流程,那么在这一节,我们具体以嵌入式产品的硬件部分为 ...