中断时应该做的事

在平常的嵌入式开发中我们经常会用到中断,但是有很多人不知道中断发生时我们应当做些什么?

在这里我提前说一下,主要讲的是mcu的终端逻辑(app指的是mcu的主程序,boot指的是升级程序)

复杂嵌入式软件(app)

在一个逻辑复杂的嵌入式软件中,存在着很多个外部中断,并且可能存在着不同的优先级,此时中断的使用不在简单。每一个中断来临时的代码运行流程应该是,中断来临跳入中断函数,首先关闭全局中断避免新的中断来临,这么说可能有点抽象,我们打一个比方我们有两个串口(UART),uatr0首先进入中断函数,中断函数中需要在通过uart0发送一段很长的数据出去,并且数据发送时不能中断,如果中断就会影响到uart0的从机运行收到影响。但是正不凑巧uart1在uart0像从机发送一大段数据时,也发生了中断,他的中断函数也是向从机发送一大段数据,这时我们的uart0的数据发送就收到了影响。为了避免相互影响的问题我们这里就需要引用全局中断这个概念,每当来一个中断时我们首先就关闭全局中断,让所有的中断都暂停下来,只运行当前中断函数中的内容,当当前中断函数逻辑的末尾处再打开全局中断,使系统回归正常。但是这样又会产生一个问题,我们在处理第一个中断时,第二个中断来临时我们根部就不知道,造成数据丢失。这个问题又该如何解决呢?我们需要引入message或者说是信息队列,比如我们来了第一个中断时先关闭中断,再根据接受到的信息判断对应的函数动作是什么,然后与向消息队列发送这个函数动作的message,开启全局中断,退出中断函数。这个流程跑下来的时间会非常非常短,几乎不会影响下一次中断的接收。但是我们第一次中断需要做出的动作还没有进行,实际上复杂设备中会不断地读取消息队列上的数据,当读取到第一次中断发送来的动作请求时,就开始了相应地动作,这个动作也怕被长时间打断,但是我们所有的中断函数内部处理都很简洁,并都采取消息队列的处理结构。特别短的时间被打断,本质上不会影响其他函数的动作。采取了消息队列,也可以保证所有的动作请求都可以实现。

在我们车载事业开发时中断的采用往往慎之又慎,也不是所有的消息接口都是采取中断方式进行处理的。在这里我举一个例子,比如说CAN, 我们在需求文档中一般也没见过对应can消息的反应时间低于1ms的,一般都是2ms往上,也没见过每隔1ms发送一条can消息的。这是为什么呢?因为can这个东西根本就不用中断中去处理事项,也不用发送message(排除特殊情况,因为有的模块可能存在三路can信号,其中很有可能有一路就是用来做紧急事项处理的),这个东西采取一个timer的思路进行,也就是每隔一定的时间对CAN的寄存器进行一个数据读取(打个比方timer的时间为2ms),查看读取的数据格式是否和发过来的数据格式相符,如果不相符就直接pass掉,如果相符就清空寄存器数据,发一个message给消息处理函数,进行后续的动作处理。不仅仅是总线检测是用这种timer的方式,普通的传感器检测也是这种方式。

简单嵌入式软件(boot)

boot往往都有升级的作用,因此设备处理也比较单一。打个比方,比如说升级时的can消息接受发送逻辑,主机发送一条升级的文件,从机接受并写入flash之后再给主机发送回去一个我接收到了,并写完了的指令。这一部分的都是顺序执行,且不会被打断时可以使用。另外就是我们上文说的,就完成很短的指令时,也可以采用在中断内部进行处理。

总结:

在单一线程顺序执行,且不会被打断时,可以使用中断内做小小的事。

在多线程和复杂中断中最好用信号箱加短中断函数模式。

目前的操作系统都支持信号箱功能和任务优先级,我个人建议有条件的话尽量都使用这个东西,省事省心。

你可能感兴趣的:(嵌入式汽车开发常识,单片机,stm32,物联网)