禁用中断让 freeRTOS 运行 on stm32

Disable interrupt to let freeRTOS run on stm32

我正在做一个项目,我在 STM32f4 上通过 DMA 连续获取数字样本。在我执行某些 DSP 的每个样本之后,DMA 都会生成一个完整的回调中断。我的计划是让 freeRTOS 在 DMA 等待回调时处理其他任务。然而,DMA 生成回调过于频繁,不允许 freeRTOS 运行。我想让它在每次 DMA 完成回调后,允许 freeRTOS 任务 运行 6 毫秒。我想从完整的回调中调用 __disable_irq(),从其中一个任务中调用 __enable_irq(),但这不能保证 6ms,而且我有一个高优先级按钮中断。我还尝试仅禁用 DMA 中断调用 __set_BASEPRI(priority<<(8-__NVIC_PRIO_BITS)),然后启动一个 6ms 的计时器。在调用 __set_BASEPRI(0) 中的计时器周期已过回调以启用 DMA 中断。但出于某种原因,这根本不允许 freeRTOS 运行。它在 DMA 完成回调和定时器周期已用回调之间来回。

我是嵌入式编程的新手,所以对此的任何评论都会有所帮助。谢谢。

您不应该认为 DSP 进程与 RTOS 任务是分开的,在 RTOS 任务中执行 DSP - 信号处理是系统中时间最关键的方面,您必须在数据到达时尽可能快地处理它,不要丢失数据。

如果 DSP 是在中断上下文中完成的并且使您的任务挨饿,那么显然您在中断上下文中做了太多工作,并且中断率太高。您需要修改您的设计以获得更可安排的时间。

如果您的 DMA 传输是单个样本,您将在每个样本中获得一个中断 - ADC 将自行完成;因此以这种方式使用 DMA 与直接 ADC 中断处理相比没有任何优势。

相反,您应该使用块处理,因此您可以周期性地 DMA 一个包含 80 个样本的块,为此您在 40 个样本时获得半传输中断,在 80 个样本时获得全传输中断。因此,对于每个中断,您可能会触发一个任务事件或信号量,以将 DSP 处理推迟到 高优先级 RTOS 任务。这实现了两件事;

  1. 对于整个 n 样本块采集时间,RTOS 可以自由地:
  • 正在对前一个块执行 DSP 处理,
  • 使用任何剩余时间来处理优先级较低的任务。
  1. 任何花费在上下文切换等方面的中断开销减少了 1/n,允许有更多时间执行核心信号处理和后台任务。

除了减少中断数量和软件开销外,信号处理算法本身在执行块处理时也更容易优化。

上面的一个变体是从 DMA 中断处理程序触发任务事件或信号量,您可以将新的样本块放入消息队列中,然后提供一些缓冲。如果 DSP 处理可能不太确定,那么这很有用,因此不能 总是 保证在下一个块准备好之前完成一个块的处理。但是总的来说,仍然有必要在获取块所需的时间内平均完成块处理,并留出时间用于其他任务。

如果您的低优先级任务仍然不足,那么明确的迹象是您的 DSP 进程对您的处理器来说实在是太多了。可能有优化的空间,但那将是一个不同的问题。

使用建议的块处理策略,我过去曾将应用程序从 200MHz 和 98% CPU 负载的 TI C2000 DSP 运行 迁移到 60% 的 72MHz STM32F1xx CPU加载。如果你做对了,性能提升可能会非常显着。

关于您的“高优先级”按钮中断,我会质疑您的优先级分配。按钮是手动操作的,人类响应和感知时间以 10 毫秒甚至 100 毫秒为单位测量。这不是您的时间紧迫任务,而缺少几 微秒 的 ADC 样本会导致您的信号处理出现严重错误。

您可能误将“高优先级”与“重要”混淆了。在上下文或实时系统中,它们不是一回事。您可以简单地轮询 低优先级 任务中的按钮,或者如果您使用中断,中断应该只做一个任务信号(或者更实际地触发一个反跳计时器)(参见 Rising edge interrupt triggering multiple times on STM32 Nucleo 示例)。