嵌入式系统的软件框架简述

目录

总述

1.循环轮询系统

2.前后台系统

3.时间片轮循系统

4.操作系统RTOS

4.1单处理器多任务系统

4.2多处理器多任务系统


前后台程序框架中单定时器实现多延时任务 

盘点那些常见的单片机编程框架,前后台,定时器,轮询,操作系统

在底层代码编写中,初始的框架设计总会面临选择,针对实际的硬件使用环境,大家对于使用的软件框架有很多选择。

总述

按嵌入式系统软件结构来分类:

1. 循环轮询系统 :简单的顺序执行程序,这类写法,不需要思考程序的具体架构,直接按照执行顺序编写应用程序即可。

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

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

4. 操作系统RTOS实时操作系统又叫RTOS,实时性,RTOS的内核负责管理所有的任务,内核决定了运行哪个任务,何时停止当前任务切换到其他任务,这个是内核的多任务管理能力。多任务 管理给人的感觉就好像芯片有多个CPU,多任务管理实现了CPU资源的最大化利用,多任务管理有助于实现程序的模块化开发,能够实现复杂的实时应用。除了实时性,还有可剥夺内核,顾名思义就是可以剥夺其他任务的CPU使用权,它总是运行就绪任务中的优先级最高的那个任务。

5. 有限状态机系统

1)循环轮询系统:主程序

2)前后台系统:中断+主程序

3)多任务系统:中断+子任务

1.循环轮询系统

即在裸机编程时,先初始化相关硬件,让主程序在一个死循环里面不断循环,顺序地处理各种事件。不能说轮询是低端的,轮询系统是一种非常简单的软件结构,但适用于仅需要顺序执行代码且不需要外部事件来驱动就能完成的事情,这会变得简单可靠。

在这里插入图片描述

顺序执行的程序模型(1) 

int main(void)
{
    initialize()  //初始化
    while(true)   //死循环
    {
	    if (condition_1) action_1();
	    if (condition_2) action_2();
	    ......
	    if (condition_n) acition_n();
    }
}
 

 顺序执行的程序模型(2) 

int main(void) 
{      
    uint8 TaskValue;     
    InitSys();                  //初始化    
    while (1)                   //死循环
    {         

      TaskValue= GetTaskValue();         
      switch (TaskValue)        
      {             
        case x: 
          TaskDispStatus(); 
        break;             
        ...             
        default:
        break;         
      }     
   } 
}

优点:

  • 对于简单的系统而言,便于编程和理解。
  • 没有中断的机制,程序运行良好,不会出现随机的问题。

缺点:

  • 有限的应用领域。
  • 对于大量的I/O服务的应用,不容易实现。特别是对有时间要求的I/O服务。
  • 大的程序不便于调试。
  • 主循环的逻辑比较复杂的时候,如果没有完整的流程图指导,其他人很难看懂程序运行逻辑。

如果加入按键操作等需要检测外部信号的事件,整个系统的实时响应能力就会体现不好。试想一下,但按键按下时,程序正在运行顺序1程序,而且顺序1程序占用的程序时间片比较长,系统就有可能错过对按键的检测(直到按键松开),实时性极差,用户无法接受。

循环轮询,适合于慢速和非常快速的简单系统

2.前后台系统

相比轮询系统,前后台系统在轮询系统的基础上加入了中断的概念,外部事件的响应在中断里面完成,事件的处理还是回到轮询系统中完成。

中断处理我们称之为前台,main()函数中的循环轮询系统称为后台

当有前台的外部事件发生时,引起中断, 进行前台处理, 处理完成后又回到后台(通常又称主程序)。

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

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

图片   在这里插入图片描述

前后台系统的基本程序流程
在这里插入图片描述

前后台的程序模型(1) 

void isr()  //中断服务程序
{

}    
 
int main()
{
 
    HardWareInit();
    /* 注册中断 */
    isrregister(isr);
    for(;;)
    {
        fun1();
        fun2();
        fun3();
     }
     return 0;
 }
 

前后台的程序模型(2) 


void IRQHandler(void)       /*中断服务程序ISR*/
{
  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;         
      }     
   } 
}

前后台系统需要考虑的问题

  • 中断的现场保护(出栈)和恢复(入栈),中断嵌套,中断处理过程与主程序的协调(共享资源互斥)问题。主程序和中断处理程序,可能要共享一个相同的资源,比如都要对一段数据进行读和写,这时就需要有一种协调机制来解决资源的共享问题。比如用关中断的方式。
  • 系统的性能主要由中断延迟时间(Interrupt latency time), 响应时间(response time)和恢复时间(recovery time)来刻画。

 在顺序执行后台程序时,如果有中断,那么中断会打断后台程序的正常执行流,转而去执行中断服务程序,在中断服务程序中标记事件。如果事件要处理的事情很简短,则可在中断服务程序里面处理,如果事件要处理的事情比较多,则返回后台程序处理。通过中断可以大大提供程序的实时响应能力,避免造成外部事件的丢失。

3.时间片轮循系统

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

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

图片

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

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

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

图片

4.1单处理器多任务系统

对于一个复杂的嵌入式系统,当前后台系统无法满足实时性,准确性,可靠性的要求的时候,就需要有嵌入式的操作系统来支撑。让这个嵌入式系统简化,把后台部分解耦了,把后台分解成多个任务,每个任务赋予不同的优先级,使能够保证实时性的要求。

对于一个复杂的嵌入式实时系统来说
• 当前后台系统这种软件结构难以实时的、准确的、可靠的完成时…
• 存在一些互不相关的过程需要在一个计算机中同时处理时…

基本结构
• 由多个任务,多个中断处理过程,实时操作系统组成的有机的整体。
• 每个任务是顺序执行的,并行性通过操作系统来完成,任务间的相互通信和同步也需要操作系统的支持。

相比前后台系统,多任务系统的事件响应也是在中断中完成的,但是事件的处理是在任务中完成的。在多任务系统中,任务与中断一样,也具有优先级,优先级高的任务会被优先执行。但一个紧急事件在中断中被标志之后,如果事件对应的任务优先级足够高,就会立刻得到响应,相比前后台系统,多任务系统的实时性又被提高了

单处理器多任务系统基本流程
这个结构中,后台是由并发的多个任务组成,每个任务就相当于一个"主程序",每个任务都有自己的初始化,有自己的一个循环的执行过程。前台是中断处理程序。这个中断处理程序可以打断不同的任务。

在这里插入图片描述

  • 多个顺序执行的程序并行运行。
  • 宏观上看,所有的程序同时运行,每个程序运行在自己独立的CPU上。
  • 实际上,不同的程序是共享同一个CPU和其它硬件。因此,需要RTOS来对这些共享的设备和数据进行管理。
  • 每个程序都被编制成无限循环的程序,等待特定的输入,执行相应的任务等。
  • 这种程序模型将系统分成相对简单的,相互合作的模块。

优点

将复杂的系统分解为相对独立的多个线程, 达到“分而制之”的目的,从而降低系统的复杂性。
保证系统的实时性。
系统的模块化好,提高系统的可维护性。

缺点

需要采用一些新的软件设计方法,理解操作系统,要分解系统。
需要增加功能:线程间的协调,同步和通信功能。
需要对每一个共享资源互斥。
导致线程间的竞争。
需要使用RTOS,RTOS要增加系统的开销。

单处理器多任务的程序模型(1) 

void task1(){}
void task2(){}
void task3(){}
 
int main()
{
 
    HardWareInit();
 
    /* 注册中断 */
    isrregister(isr);
 
    /* RTOS初始化 */
    RTOSInit();
 
    /* RTOS调度启动 */
    RTOSStart();
 
    return 0;
}
 

在多任务系统中,程序的主体会分割成一个个独立的、无限循环且不能返回的任务,每个任务都是独立的、互不干扰的,而且具备自身的优先级,由操作系统调度管理。整个系统的额外开销就是操作系统占据的少量FLASH和RAM,但是对于现在的片上资源,已经是微不足道。

4.2多处理器多任务系统

多任务可运行在多个处理器上,由操作系统来统一调度和处理。


• 宏观上看是并发的,微观上看也是并发的。
• 嵌入式系统中常采用片上多处理器系统,即在单一芯片上集成多个处理器核心(Multi-Processor System-On-a-Chip, MPSoC)。从体系结构上来看,常见的有SMP(Symmetrical Multi-Processing)架
构和AMP(Asymmetric Multi-Processing)架构。

SMP结构:对称多处理器架构。
AMP结构:非对称多处理架构。大小核

在这里插入图片描述
 

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嵌入式软件框架设计是指在嵌入式软件开发过程中,通过定义合理的结构和模块之间的交互方式,为软件开发提供一个稳定、可重用和可扩展的基础。 首先,嵌入式软件框架设计需要考虑硬件平台的特性和约束,以确保软件能够在特定的嵌入式设备上运行。这涉及到对硬件资源的有效管理,包括内存、处理器和外设等。 其次,框架设计需要明确定义模块之间的接口和功能划分,以便各个模块可以独立开发和测试。这有助于提高代码的可维护性和可重用性。同时,模块之间的交互方式也需要考虑,可以采用消息队列、事件驱动或者消息传递等机制。 另外,框架设计还需要考虑软件的可扩展性和灵活性。嵌入式软件通常需要满足不断变化的需求和新的功能要求。因此,框架应该提供一种扩展机制,使得新的功能可以方便地添加到软件中,而且不会对现有功能产生影响。 最后,框架设计还需要考虑软件的性能和资源利用率。嵌入式设备通常具有有限的计算能力和存储资源。因此,在框架设计中应该避免不必要的计算和内存占用,保证软件的响应速度和资源利用效率。 总而言之,嵌入式软件框架设计是一个重要的环节,可以为软件开发提供一个稳定、可重用和可扩展的基础。它需要考虑硬件平台的特性、模块之间的接口和功能划分、软件的可扩展性和灵活性,以及软件的性能和资源利用率等方面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值