首页 > 解决方案 > 如何知道 IRQ 是否立即在 ARM Cortex M0+(或任何其他 MCU)上提供服务

问题描述

对于我的应用程序(在 STM32L082 上运行),我需要几种类型的中断的准确(相对)时间戳。我通过在 1 MHz 上运行一个计时器并在 ISR 运行后立即计数来做到这一点。它们都被赋予最高优先级,因此它们抢占了不太重要的中断。我面临的问题是,它们可能仍会被具有相同优先级的其他中断和禁用中断的代码延迟,而且似乎没有简单的方法可以知道发生了这种情况。ISR 被延迟是没有问题的,只要我知道特定的时间戳因此不准确。

我目前的方法是让每个 ISR 和每个禁用中断的代码块检查中断是否正在挂起,NVIC->ISPR[0]并为挂起的 ISR 标记它。每个 ISR 都会检查此标志,并在需要时将时间戳标记为不准确。

虽然这行得通,但感觉它是错误的方式。所以我的问题是:是否有另一种方法可以知道是否立即提供了 IRQ?

有问题的 IRQ 是用于 GPIO 引脚更改的 EXTI4-15 和用于唤醒定时器的 RTC。不幸的是,我无法更改 PCB 布局并在输入引脚上使用 TIM 输入捕获,也无法更改使用的 MCU。

更新

当前设置中精度的基本限制取决于内部 RTC 校准的性质,它会周期性地添加/移除 32kHz 滴答声,从而导致约 31 µs 的抖动。我的目标是尽可能消除(或至少检测)额外的时间戳错误。偶然阻塞中断(例如 50+ µs)很难避免并影响测量,因此至少需要知道何时发生这种情况。

更新 2

澄清一下,我认为这是一个软件问题,询问是否存在特定功能,如果存在,如何使用它。我正在寻找的答案之一是:“是的,有可能,只需检查寄存器 Y 的位 X”,或者“不,这是不可能的,但是 MCU ......确实有这样的功能,称为......”“不,这样的功能通常在任何平台上都不可用(但常见的解决方法是......)”。这些信息将引导我(和未来的读者)找到软件解决方案,和/或更好的硬件设计要求。

标签: armcortex-misrirqtimestamping

解决方案


一般来说

准确时间戳的理想解决方案是使用定时器捕获硬件(内置于微控制器或外部实现)。除此之外,使用具有足够优先级的 CPU 以使您的 ISR 始终具有最高优先级可以工作,或者您可以通过使 DMA 引擎对 GPIO 引脚进行采样(具体如下)来破解某些东西。

一些微控制器在内置外设之间有连接,允许一个外设触发另一个外设(例如触发定时器捕获的 GPIO 引脚,即使它不是专用的定时器捕获输入引脚)。制造商对这种类型的互连有不同的名称,但可以在Wikipedia上找到一般概述以及各种名称的列表。具体功能因制造商而异。

我从未在微控制器中遇到过用于指示 ISR 是否被更高优先级的 ISR 延迟的功能。我认为这不是一个常用的功能,因为您的 ISR 随时可能被更高优先级的 ISR 中断,即使在您检查了假设was_delayed标志之后也是如此。不过,较高优先级的 ISR 通常可以检查较低优先级的中断是否正在挂起。

针对您的具体情况

一种可能的方法是使用定时器和 DMA(类似于音频流,首选双缓冲/循环模式)将 GPIO 引脚连续采样到缓冲区,然后扫描缓冲区以确定引脚何时更改。请注意,这意味着 CPU 必须在缓冲区被 DMA 再次覆盖之前对其进行扫描,这意味着 CPU 只能在短时间内休眠,并且必须保持定时器和 DMA 时钟运行。ST的AN4666是相关文档,这里有示例代码(下载示例代码需要账号)。他们使用的是不同的微控制器,但他们声称这种方法可以适应他们阵容中的其他人。

否则,根据您当前的设置,我认为没有比您正在使用的解决方案更好的解决方案(检测到延迟时设置的标志)。ARM Cortex-M0+ NVIC 没有指示 ISR 是否延迟的功能。

对您当前方法的改进可能是使 ISR 尽可能短,因此它们仅进行时间戳收集,然后将任何其他工作放入队列中,以由主应用程序以较低优先级处理(仅适用于工作更多比入队操作复杂,并且如果工作对时间不敏感)。消除或缩短中断禁用区域也应该有所帮助。


推荐阅读