使用中断处理程序作为事件监听器有什么不对

时间:2014-09-16 13:12:55

标签: c embedded arm bare-metal

我的系统很简单,它运行时没有操作系统,我只是使用中断处理程序,就像在桌面程序中使用事件监听器一样。在我在线阅读的所有内容中,人们尝试在中断处理程序中花费尽可能少的时间,并将控制权交还给任务。但我没有操作系统或真正的任务系统,我无法真正找到无操作系统目标的设计信息。

我基本上有一个中断处理程序从USB读取一大块数据并将数据写入内存,一个中断处理程序读取数据,在GPIO上发送数据并在硬件计时器上再次安排自己。

以我的方式使用中断有什么问题,并使用NVIC(我使用cortex-M3)来管理工作层次结构?

5 个答案:

答案 0 :(得分:6)

首先,在这个问题的上下文中,我们将操作系统称为调度程序

现在,与线程不同,中断服务例程位于调度方案的“上方”。

换句话说,调度程序对它们没有“控制权”。

由于HW中断导致ISR进入执行状态,它将PC设置为代码段中的不同地址(更确切地说,在调用ISR之前,在“执行一些操作”的中断向量中) )。

因此,从本质上讲,任何ISR的优先级都高于具有最高优先级的线程的优先级。

因此,在ISR中花费尽可能少的时间的一个明显理由是,ISR对您为系统设计的调度方案具有“副作用”。

由于您的系统纯粹是中断驱动的(即没有调度程序而没有线程),因此这不是问题。

但是,如果不允许嵌套的ISR,则必须在中断发生时直到相应的ISR完成时禁用中断。在这种情况下,如果在ISR执行期间发生任何中断,那么您的程序将有效地忽略它。

因此,您在ISR中花费的时间越长,您在中断时“错失”的可能性就越高。

答案 1 :(得分:3)

在许多桌面程序中,事件被发送到队列,并且有一些"事件循环"处理此队列。此事件循环按事件处理事件,因此无法通过其他事件中断一个事件。事件驱动编程中的好习惯是让所有事件处理程序尽可能短,因为它们不可中断。

在裸机编程中,中断与事件类似,但它们不会发送到队列。

  • 中断处理程序的执行不是顺序的,它们可以被具有更高优先级的中断(Cortex-M3中数字较低的数字)中断
  • 没有相同中断的队列 - 例如当你处于那个中断时,你不能检测到多个GPIO中断 - 这就是你应该让所有例程尽可能短的原因。

可以自己实现队列,通过中断提供这些队列,并在超级循环中使用这些队列(在禁用所有中断时使用)。通过这种方法,您可以获得中断的顺序处理。如果你的处理程序很短,这通常是不需要的,你可以直接在处理程序中完成工作。

在基于操作系统的系统中,他们使用队列,信号量和"中断处理程序任务"这也是一种很好的做法。处理中断。

答案 2 :(得分:2)

使用裸机,只要进行分析,就可以设计应用程序绑定或中断/事件限制。因此,如果您知道什么事件/中断以什么速率发生,并且您可以确保您将在期望/设计的时间内处理所有事件/中断,那么您当然可以在事件/中断处理程序中花费时间而不是快速向前台任务发送一个标志。

当然,常见的方法是快速进出,保存足够的信息来处理前台任务中的事情。前台任务必须旋转它的轮子当然要寻找事件标志,优先级等等。

当然,你可以使它变得更复杂,当中断/事件到来时,保存状态,并以forground模式而不是中断模式返回forground处理程序。

现在这一切都是普遍的,但对于cortex-m3是特定的,我不认为有像大哥ARM这样的模式。只要您采用实时方法并确保您的处理程序是确定性的,并且您进行系统工程并确保在事件/中断堆积的情况下不会发生任何情况,这样响应不是确定性的,也不会太晚或太晚长或丢失的东西没关系

答案 3 :(得分:2)

您必须要问自己,所有事件是否都可以在所有情况下及时提供服务:

例如;

  • 如果你的中断系统是完全运行的,那么一个中断的服务是否会导致另一个中断的服务出现无法接受的延迟?
  • 另一方面,如果中断系统是基于优先级和抢占式的,那么高优先级中断的服务会不可接受地延迟较低的中断?

在后一种情况下,您可以使用Rate Monotonic Analysis来分配优先级,以确保最大的响应能力(最短的执行时间处理程序获得最高优先级)。在第一种情况下,您的系统可能缺乏一定程度的确定性,并且在事件加载和代码更改的情况下性能都是可变的。

一种方法是将处理程序划分为实时关键部分和非关键部分,时间关键代码可以在处理程序中完成,然后设置标志以提示在“处理”中执行非关键操作background“大循环”系统中的非中断上下文,它简单地轮询事件标志或共享数据以完成工作。通常,中断处理程序中可能需要的只是将一些数据复制到某个事件的时间戳 - 使数据可用于后台处理,而不会阻止处理新事件。

对于更复杂的调度,有许多简单,低成本或免费的RTOS调度器,它们提供具有非常小的占用空间的多任务,同步,IPC和定时服务,并且可以在非常低端的硬件上运行。如果您有硬件计时器和10K代码空间(有时更少),则可以部署RTOS。

答案 4 :(得分:2)

我首先解决您描述的问题

正如我所解释的那样,你的目标是创建一个设备,通过接收来自USB的命令,输出一些GPIO,如LED,继电器等。对于这个简单的任务,你的方法似乎是很好(如果USB层可以充分利用它)。

虽然存在优先级问题,但在这种情况下,如果您使USB侧过载(使用来自电缆另一端的数据),并且中断处理它的优先级高于定时器触发的优先级,则处理在GPIO中,GPIO端可能会丢失滴答声(就像其他人解释的那样,中断不能排队)。

在你的情况下,这是关于可以考虑的事情。

一些一般性指导

对于“在中断处理程序中花费尽可能少的时间”,理由就是其他人所说的:操作系统可能实现队列等,但硬件中断不提供这样的概念。如果发生导致中断的事件,则CPU进入处理程序。然后,直到您处理它的源(例如在UART的情况下读取接收保持寄存器),您将丢失该事件的任何进一步发生。在此之后,在退出处理程序之前,您可能会收到事件是否发生,但不会发生多少次(如果事件在CPU处理处理程序时再次发生,则关联的中断线再次激活,因此从您返回后处理程序,CPU立即重新输入它,只要没有更高的优先级等待。)

上面我描述了在8位处理器和AVR 32bit上可观察到的一般概念(我对这些有经验)。

在设计这样的低级系统(无操作系统,一个“后台”任务和一些中断)时,了解每个优先级上发生的事情(如果您使用此类优先级)是至关重要的。一般而言,您可以将最实时的关键任务放在最优先的位置,尽可能快速地为这些任务提供服务,同时在较低优先级的情况下更轻松。

从设计阶段的另一个方面来看,可以规划系统应该如何对错过的中断作出反应,因为在有中断的情况下,最终会遗漏一个 。通信线路上的关键数据应该有足够的校验和,特别关键的计时器应该来自计数寄存器,而不是来自事件计数等。

中断的另一个令人讨厌的部分是它们的异步性质。如果你没有正确地设计相关的锁,他们最终会腐败给那些必须调试它的那个可怜的灵魂的噩梦。 “在中断处理程序中花费尽可能少的时间”语句还鼓励您将中断代码保持在合理的短时间内,这意味着要考虑更少的代码来解决此问题。如果您还使用RTOS辅助的多任务处理,您应该知道这一部分(虽然存在一些差异:更高优先级的中断处理程序代码不需要针对较低优先级处理程序的保护)。

如果你可以正确设计你的架构关于必要的异步任务,那么在没有操作系统的情况下(从没有多任务处理方面),甚至可以证明是一个更好的解决方案。需要更多思考才能正确设计它,但是后来锁定相关问题要少得多。我完成了一些中型安全关键项目,这些项目是在一个单一的后台“任务”中设计的,只有很少的中断,而且与那些公司中的其他人相比,对这些项目的经验和维护要求(特别是跟踪错误)非常令人满意。建立在多任务概念之上。