前后台系统及嵌入式前后台模式实时性优化

一、前后台系统

前后台系统,即计算机前后台系统,早期的嵌入式系统中没有操作系统的概念,程序员编写嵌入式程序通常直接面对裸机及裸设备,在这种情况下,通常把嵌入式程序分成两部分,即前台程序和后台程序。

实现模式

应用程序是一个无限的循环,循环中调用相应的函数完成相应的操作,这部分可以看成后台行为。前台程序通过中断来处理事件;后台程序则掌管整个嵌入式系统软、硬件资源的分配、管理以及任务的调度,是一个系统管理调度程序。这就是通常所说的前后台系统。一般情况下,后台程序也叫事件处理任务,前台程序也叫中断级任务。在程序运行时,后台程序检查每个任务是否具备运行条件,通过一定的调度算法来完成相应的操作。对于实时性要求特别严格的操作通常由中断来完成,仅在中断服务程序中标记事件的发生,不再做任何工作就退出中断,经过后台程序的调度,转由前台程序完成事件的处理,这样就不会造成在中断服务程序中处理费时的事件而影响后续和其他中断。

实际上,前后台系统的实时性比预计的要差。这是因为前后台系统认为所有的任务具有相同的优先级别,即是平等的,而且任务的执行又是通过FIFO队列排队,因而对那些实时性要求高的任务不可能立刻得到处理。另外,由于后台程序是一个无限循环的结构,一旦在这个循环体中正在处理的任务崩溃,使得整个任务队列中的其他任务得不到机会被处理,从而造成整个系统的崩溃。由于这类系统结构简单,几乎不需要RAM/ROM的额外开销,因而在简单的嵌入式应用被广泛使用。

二、嵌入式前后台模式实时性优化

已剪辑自: https://blog.csdn.net/li_man_man_man/article/details/121534175

软件系统的实时响应能力越强,响应时间越短。响应时间是指系统识别到一个事件开始到做出响应的时间。举一个简单的例子:一个工控系统有一个急停按键开关,用户希望按下急停开关的时候系统立即将停止所有的动作,假设用户在第1.001秒时按下了急停开关,软件系统在第1.011秒时停止了所有动作,此时响应时间为0.01秒。

很多小型的嵌入式软件系统通常设计成前后台结构,这个结构包含一个死循环和若干中断服务程序:应用程序是一个无限循环的代码块,循环中调用相应的函数完成相应的操作(后 台),中断程序用于处理系统的异步事件(前台)。前台称做中断级,后台称做任务级。下面是一个典型的前后台结构的代码:
在这里插入图片描述
为了保证事件得到及时处理,有些关键代码只能放在中断里执行,这导致中断程序的运行时间变长(这显然是不可取的,中断函数要短平快)。中断程序即使立刻生成了特定的数据,后台程序也必须运行到对应的处理代码时才能进行处理,这称为响应延迟。最长的任务级响应延迟取决于后台循环的运行时间,因此特定模块的运行时间间隔是随机的不确定的,前后台系统如图所示:
在这里插入图片描述
根据上图我们假设,在中断点1处系统收到了处理函数1的外部响应信号,中断程序中设置了处理函数的标志位(标志位设置好处理函数1会执行相应的操作),但是此时软件系统不得不等处理函数3和处理函数4执行完毕后才能执行相应的操作,因此就产生了响应延迟,响应延迟的时间随机的不确定的,有的时候是几毫秒的时间,有的时候是几百毫秒甚至更长(如执行FLASH写操作,LCD刷新图片操作)。

如何提高软件系统的实时响应能力?

我这里以cortex-M4核的MCU为例进行讲解。cortex-M4核有一个PendSV(可挂起的系统调用)异常,其异常编号为14并且具有可编程的优先级。当软件将PendSV设置成挂起时,程序将进入PendSV异常(可以理解为一个中断函数),PendSV异常时序框图如下:
在这里插入图片描述
我们可以使用PendSV异常来执行对实时性要求较高的处理函数(这不是违背了中断函数要短平快的原则),我们可以将PendSV异常优先级设置为最低,这样其他的中断函数都可以正常中断,不会受到PendSV异常,因此即使在PendSV异常中执行较长的函数也不会影响系统的其他中断任务(相当于将关键性代码优先于任务级函数执行),时序框图如下:
在这里插入图片描述
根据上图我们假设,在处理函数1执行过程中产生了一个外部中断,此时需要执行处理函数4相关的操作,我们在外部中断处理中触发PendSV异常,处理函数4中相关的操作在PendSV异常中执行(不需要等待处理函数1,处理函数2和处理函数3执行完毕),同时系统也照常响应其他的中断函数。因此响应延迟得到明显改善。

接下来我们看一下代码如何实现,后台函数如下:
在这里插入图片描述
中断函数我们这里使用时钟中断函数做模拟演示,实际上我们可以使用各种中断:外部IO中断,UASRT中断,ADC中断,DMA中断等。中断代码如下:
在这里插入图片描述
中断代码根据实际情况设置调用号,这样PendSV异常可以根据调用号为所有的处理函数提供服务,如我们可以外部IO中断处理中将调用号设置成0,UASRT中断处理中将调用号设置成1,ADC中断处理中将调用号设置成2,DMA中断处理中将调用号设置成3,在设置号调用号后挂起PendSV,然后系统将进入PendSV异常,PendSV异常根据调用号(一个全局变量)执行相应的操作。

PendSV异常代码如下:
在这里插入图片描述
PendSV异常可以根据调用号调用相应的回调函数。需要执行的高实时性的函数我们全部放在一个跳转表中,跳转表(跳转表就是一个函数指针数组)的实现如下
在这里插入图片描述
通过这样的设计我们提高了软件系统的实时响应能力。

**创作不易希望朋友们点赞,转发。希望获取源码的朋友们在评论区里留言。
作者:李巍
Github:liyinuoman2017

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小熊coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值