对于我的应用程序(运行在STM32L082上),我需要对几种类型的中断进行准确(相对)的时间戳。我通过在1MHz下运行计时器来实现这一点,并在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。。。确实有这样一个功能,叫做">或";不,这样的功能通常在任何平台上都不可用(但常见的解决方法是…)">。这些信息将引导我(以及未来的读者)找到软件解决方案和/或更好的硬件设计要求。
一般
精确时间戳的理想解决方案是使用定时器捕获硬件(内置于微控制器或外部实现)。除此之外,使用具有足够优先级的CPU使您的ISR始终处于最高优先级也可以工作,或者您可以通过使DMA引擎对GPIO引脚进行采样来共同破解一些东西(具体细节如下)。
一些微控制器在内置外设之间有连接,允许一个外设触发另一个外设(比如GPIO引脚触发定时器捕获,尽管它不是专用的定时器捕获输入引脚)。制造商对这种类型的互连有不同的名称,但可以在维基百科上找到一个大致的概述,以及各种名称的列表。具体功能因制造商而异。
我从未在微控制器中遇到过指示ISR是否被更高优先级的ISR延迟的功能。我不认为这是一个常用的功能,因为您的ISR随时可能被更高优先级的ISR中断,即使在您检查了假设的was_delayed
标志之后也是如此。优先级较高的ISR通常可以检查优先级较低的中断是否处于挂起状态。
针对您的具体情况
一种可能的方法是使用定时器和DMA(类似于音频流,首选双缓冲/循环模式)将GPIO引脚连续采样到缓冲区,然后扫描缓冲区以确定引脚何时更改。请注意,这意味着CPU必须在缓冲区再次被DMA覆盖之前扫描缓冲区,这意味著CPU只能在短时间内休眠,并且必须保持计时器和DMA时钟的运行。ST的AN4666是一个相关的文档,这里有示例代码(下载示例代码需要帐户)。他们使用了不同的微控制器,但他们声称这种方法可以适用于他们阵容中的其他微控制器。
否则,根据您当前的设置,我认为没有比您正在使用的解决方案(检测到延迟时设置的标志)更好的解决方案了。ARM Cortex-M0+NVIC没有指示ISR是否延迟的功能。
对当前方法的改进可能是使ISR尽可能短,因此它们只进行时间戳收集,然后将任何其他工作放入队列中,由主应用程序以较低的优先级进行处理(仅适用于工作比入队操作更复杂,并且工作对时间不敏感的情况)。消除或缩短中断禁用区域也会有所帮助。