6

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

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

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

4

5 回答 5

7

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

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

换句话说,调度程序无法“控制”它们。

ISR 作为硬件中断的结果进入执行,这会将 PC 设置到代码部分中的不同地址(更准确地说,设置到中断向量,在调用 ISR 之前您“做一些事情”)。

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

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

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

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

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

于 2014-09-16T13:42:13.040 回答
3

在许多桌面程序中,事件被发送到队列,并且有一些“事件循环”处理这个队列。此事件循环逐个事件处理,因此不可能通过另一个事件中断一个事件。在事件驱动编程中,让所有事件处理程序尽可能短也是一种很好的做法,因为它们是不可中断的。

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

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

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

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

于 2014-09-16T14:40:06.973 回答
2

你要问自己的是,是否所有的事件都能在所有情况下及时服务:

例如;

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

在后一种情况下,您可以使用速率单调分析来分配优先级以确保最大的响应能力(最短的执行时间处理程序获得最高优先级)。在第一种情况下,您的系统可能缺乏一定程度的确定性,并且在事件负载和代码更改下性能会发生变化。

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

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

于 2014-09-16T18:39:34.113 回答
2

我先处理你描述的问题

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

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

在您的情况下,这是关于可以考虑的内容。

一些一般性指导

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

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

在设计这样的低级系统(无操作系统、一个“后台”任务和一些中断)时,了解每个优先级(如果您使用这些优先级)发生了什么是基本的。一般来说,您会将最实时的关键任务设置为最高优先级,最关心的是快速为这些任务提供服务,同时对较低优先级的级别更加放松。

另一方面,通常在设计阶段,可以计划系统应如何对丢失的中断做出反应,因为在有中断的地方,无论如何最终都会发生丢失的中断。通过通信线路的关键数据应该有足够的校验和,特别关键的计时器应该来自计数寄存器,而不是来自事件计数等。

中断的另一个令人讨厌的部分是它们的异步性质。如果您未能正确设计相关的锁,它们最终会破坏某些东西,让不得不调试它的可怜的灵魂做噩梦。“在中断处理程序中花费尽可能少的时间”语句还鼓励您保持中断代码合理短,这意味着也可以减少针对此问题考虑的代码。如果您还使用 RTOS 辅助的多任务处理,您应该知道这部分(但有一些区别:较高优先级的中断处理程序的代码不需要针对较低优先级的处理程序的保护)。

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

于 2014-09-16T18:47:57.197 回答
2

使用裸机,只要您进行分析,就可以针对应用程序绑定或中断/事件绑定进行设计。因此,如果您知道哪些事件/中断以何种速率发生,并且您可以确保您将在所需/设计的时间内处理所有事件/中断,您当然可以花时间处理事件/中断处理程序,而不是快速和向前台任务发送标志。

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

你当然可以让它更复杂,当中断/事件来临时,保存状态,并在前台模式而不是中断模式下返回前台处理程序。

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

于 2014-09-16T14:06:42.633 回答