一般来说,嵌入式设备上硬件中断的ISR应该非常短:通常只需设置一个标志,该标志将在正常执行过程中(例如在任务循环中)被读取。
这就引出了一个问题:如果是这样,那么成熟的硬件中断和中断控制的目的是什么?为什么MCU不简单地设置一个标志(在指定的寄存器中,内存映射中),同样可以通过任务循环检查该标志?如果我们要做的只是设置一个标志,为什么要花费实际转移执行的费用(MCU 电路、执行中断和复杂性)?
背景:我的目标是理解。如果答案是“99% 的情况下,你是对的,但只有 1% 的情况会产生影响……”,这将实现我的目标。
您的假设“通常只是设置一个标志[...]”根本不是 99% 的用例,甚至不是接近的。
我在嵌入式软件领域工作了 40 多年,根据我个人的主观经验,设置标志的中断服务例程只是少数。
保持中断服务例程短期运行是一个常见规则。但这仅在与要求相关的情况下才是正确的。在目标系统的上下文中什么是“短”?有些系统需要的运行时间短于几微秒,甚至更短。其他人可以完美地忍受几秒钟。因此,您需要先指定要求,然后才能知道中断服务例程需要运行多短。
我遇到或编写的绝大多数中断服务例程不仅仅是设置一个标志。
例如,服务 UART 通常包括获取下一个要发送的数据或缓冲接收到的数据。在不止一种情况下,这些例程还会对数据进行额外的预处理。
在我自己项目的另一个示例中,输入引脚的边沿触发中断服务例程对“曼彻斯特编码”数据流进行解码。它最终将解码的字节排队。对于主线程来说,它看起来像一个在其缓冲区中提供字节流的模块。 一个特殊但奇怪的例子是早期个人电脑
ZX81的“操作系统”。诚然,这并不是一个真正的嵌入式系统,而且它已经有 42 年的历史了。不管怎样,它创建视频信号以在电视机上观看,同时混合了不可屏蔽和可屏蔽中断。运行时间最长的程序是垂直回扫信号的产生,大约需要3.5ms。在此期间,它会扫描整个键盘矩阵并对其进行去抖处理,以及执行其他任务。 接下来,考虑例外情况。这些也是硬件中断,由硬件在某些条件下检测到,例如被零除、访问冲突等等。您不会希望他们只是设置一个标志并返回到触发指令。
最后(对于我的回答),抢占式多任务系统将使用其中断服务例程来切换任务。
因此,中断仍然有意义,并且将继续有意义。
顺便说明一下,您建议的这些硬件标志已经存在。我使用的任何系统都有软件可以轮询的中断标志。实际上,我们只是通过轮询(和重置)中断标志来构建不使用中断服务例程的系统。我们有我们的理由。
您在评论中询问 STM32 的示例。由于您没有进一步说明,我选择了在快速网络研究中找到的第一个具有
用户手册的MCU:STM32L0x0。 第21.8.8章描述了寄存器
USART_ISR
,其中包括位7中的标志
TXE
:
当 USART_TDR 寄存器的内容已被设置时,该位由硬件置位。
转入移位寄存器。通过写入 USART_TDR 寄存器来清除它。也可以通过向 USART_RQR 寄存器中的 TXFRQ 写 1 来清除 TXE 标志,以丢弃数据(仅限智能卡 T=0 模式,以防传输失败)。如果 USART_CR1 寄存器中的 TXEIE 位=1,则会产生中断。
您可以在软件中轮询该位并做出相应反应。实现留给读者作为练习。