NVIC:在 ARM Cortex-M 上禁用中断和内存屏障指令的需要

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

掌握中断对于使嵌入式应用程序可重入至关重要。重入的挑战在于事情可能会以错误的方式实现,并且问题可能只是偶尔出现(请参阅“ EnterCritical() 和 ExitCritical():为什么事情会严重失败 ”)。 ARM Cortex 中断控制器被命名为 NVIC(嵌套向量中断控制器)。

ARM Cortex NVIC 寄存器

正如 NVIC 中的“嵌套”所示,该控制器支持嵌套中断,从中断延迟和灵活性的角度来看,这是一件好事。我可以使用 NVIC 有选择地禁用/启用中断。如果操作得当,我不必在整个系统范围内禁用中断:我可以将中断锁定的范围缩小到最少的中断。

NVIC 具有以下用于启用/禁用中断的寄存器(每个向量号对应一位):

  1. NVIC_ISER :中断设置启用寄存器以启用中断源
  2. NVIC_ICER :中断清除启用寄存器以禁用中断源
  3. NVIC_ISPR :中断设置挂起寄存器以引发中断
  4. NVIC_ISCR : Interrupt Clear Pending Register 清除挂起的中断

下面显示了在 Freescale KL25Z 设备上启用 DMA 中断的位:

NVIC ISER

要禁用中断源,我可以通过以下 CMSIS 方式执行此操作:


 NVIC_DisableIRQ(device_IRQn); // Disable interrupt

使用正确的 IRQ 号。但是,体系结构可能存在问题。


:idea: 使用这些现代处理器,事情将“立即完成”是一种错误的想法:由于内部流水线、缓存、总线和传播延迟设置不会立即产生影响。相反,可能会有一些延迟。

因此,如果在禁用指令之前发生中断,则在我禁用中断后它可能仍会发生:

中断禁用延迟(来源:ARM)

这对我的设计来说可能是也可能不是问题。但是如果我想创建一个关键部分来防止中断以这种方式发生,我需要添加“内存屏障”指令(参见 http://infocenter.arm.com/help/index.jsp?topic=/com .arm.doc.dai0321a/BIHEBHFF.html ):

  • DSB :数据同步屏障。确保在执行 DSB 之后的任何指令之前完成 DSB 之前的所有显式数据存储器传输。
  • ISB :指令同步屏障。确保在 ISB 之前所有上下文更改操作的影响被后续指令识别。这导致指令流水线的刷新, ISB 之后的指令被重新获取。

ARM 建议首先使用 DSB,然后再使用 ISB:


 NVIC_DisableIRQ(device_IRQn); // Disable interrupt

如果我不想触发挂起的中断,或者如果需要访问与中断源相关的外围空间中的某些内容,例如更改中断向量或外围设置,例如将更改矢量位置。或者换句话说,该外设的任何中断活动都会成为问题。

概括

不考虑 ARM Cortex M0/M4 架构中存在传播延迟这一事实可能会导致有缺陷的中断处理。令人讨厌的是,该问题很少发生,而且很难追踪。添加内存屏障也可能是解决您的问题的金弹 :-)

快乐打扰 :-)