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

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

Guess you like

Origin blog.csdn.net/li_man_man_man/article/details/121534175