如何知道 IRQ 是否立即在 ARM Cortex M0+(或任何其他 MCU)上提供

How to know whether an IRQ was served immediately on ARM Cortex M0+ (or any other MCU)

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

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

虽然这行得通,但感觉好像走错了路。 所以我的问题是:是否有另一种方法可以知道是否立即处理了 IRQ?

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

更新

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

更新 2

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

一般

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

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

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

针对您的具体情况

一种可能的方法是使用计时器和 DMA(类似于音频流,首选 double-buffered/circular 模式)将 GPIO 引脚连续采样到缓冲区,然后扫描缓冲区以确定何时引脚改变了。请注意,这意味着 CPU 必须在缓冲区被 DMA 再次覆盖之前扫描缓冲区,这意味着 CPU 只能在短时间内休眠并且必须保持定时器和 DMA 时钟 运行。 ST 的 AN4666 is a relevant document, and has example code here(下载示例代码需要帐户)。他们使用的是不同的微控制器,但他们声称该方法可以适用于他们产品线中的其他人。

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

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