当前位置: 首页 > news >正文

ARM杂谈——临界段保护恢复的中断状态可靠吗

0 前言

在MCU中,临界段保护是指在多任务或多线程环境中,确保某段代码在执行时不会被其他任务或中断打断,从而避免数据竞争或不一致的问题。临界段保护通常用于共享资源的访问,如全局变量、硬件寄存器等。

我们有一些常用的临界段保护方法,但他们在任何场景下都可靠吗?

1 常用的临界段保护方法

PRIMASK是1bit的中断屏蔽寄存器,在置位时会阻止除不可屏蔽中断和HardFault异常外的所有中断。

在CMSIS库中,可以直接用__disable_irq()__enable_irq()来操作PRIMASK寄存器。
使用汇编指令MSRMRS可以访问该寄存器。

  • 直接关掉中断
void main()
{/* 代码段1 */__disable_irq();	// 关闭全局中断/* 需要临界段保护的代码 */__enable_irq();		// 打开全局中断/* 代码段2 */
}

在执行临界段前后,中断使能状态应该保持一致。
而这段代码如果在__disable_irq()的时候全局中断是关闭的,那么在后面调用__enable_irq()的时候就会打开全局中断,改变了系统的中断屏蔽状态。

  • 临界段后,恢复中断状态
void main()
{/* 代码段1 */uint32_t intFlag = __get_PRIMASK();	// 获取当前中断状态__disable_irq();					// 关闭全局中断/* 需要临界段保护的代码 */__set_PRIMASK( intFlag );			// 恢复之前的中断状态/* 代码段2 */
}

这段代码先保存了当前的中断屏蔽状态,在执行临界段后恢复了之前的中断屏蔽状态,保证了执行临界段前后中断屏蔽状态的一致性。

但这样是否会也会存在一些问题呢?

2 问题:上面方法恢复的中断状态可靠吗?

在上面的代码中:
(1)使用了一个变量intFlag保存当前的中断屏蔽状态
(2)使用了__disable_irq()关闭全局中断
(3)执行临界段
(4)使用__set_PRIMASK( intFlag )恢复中断。

如果在步骤(1)和步骤(2)之间,一个中断被响应,并且在该中断中关闭了全局中断,那么在步骤(4)恢复中断的时候,就会错误的将中断开启。

这么做当然很蠢,因为如果一个中断希望获取临界段保护,那么在它关闭中断后应该恢复之前的状态。
但我想知道的是:如果有一个中断,他的目标就是触发的时候禁止全局中断,这样会导致临界段保护恢复一个错误的中断状态吗?

上述情况的前提:
1.在临界段之前全局中断是使能的
——否则也不会响应中断,更不会关掉全局中断了
.
2.Cortex-M内核
在处理器接受了一个异常后,寄存器组中的一些寄存器(R0R1R2R3R12R14)、返回地址(PC)以及程序状态寄存器(xPSR)会被自动压入当前栈空间里,以便在退出中断后恢复运行环境,使被中断的程序正确执行。
.
而保存中断屏蔽状态的PRIMASK寄存器中是没有被压栈的。因此,若在中断处理期间修改了PRIMASK寄存器,从而改变了中断屏蔽状态,那么在退出中断后,中断屏蔽状态将保持与中断处理期间修改后的状态一致。
.
而在ARM7TDMI内核中,中断屏蔽状态保存在其CPSR寄存器中,而该寄存器在处理器接受异常后会被压栈,因此在退出异常后CPSR寄存器会被恢复为中断处理前的状态。

由此可见,在Cortex-M处理器中,若某个中断的意图是关闭全局中断,则可能导致临界段保护机制恢复至错误的中断状态。

为了进一步分析,我想看一下成熟的代码是怎么处理该问题的。

3 FreeRTOS的临界段保护操作

注:这里用的是FreeRTOS在Cortex M0/M0+上的接口文件,Cortex M3及以上内核的有不同的实现方法。

3.1 不可在中断中使用的临界段保护

  • taskENTER_CRITIAL() 进入临界段保护
void vPortEnterCritial( void )
{portDISABLE_INTERRUPTS();			// __disable_irq(),即关闭全局中断uxCriticalNesting++;				// 支持嵌套使用,调用一次计数变量+1__dsb( portSY_FULL_READ_WRITE );	// portSY_FULL_READ_WRITE  = 15__isb( portSY_FULL_READ_WRITE );	// portSY_FULL_READ_WRITE  = 15
}

DSB:数据同步屏障。确保下一条指令执行前,所有的存储器访问都已完成。
例如对存储器映射切换寄存器变成后,为了确保写操作完成并且存储器配置已经得到更新,在进行下一步以前,应该使用DSB命令。

ISB:清除流水线。确保在执行新指令前,之前的所有指令都已完成。
例如在使用MSR指令改变CONTROL寄存器的值之后,应该使用ISB,以确保接下来的操作使用已经更新的设置。

  • taskEXIT_CRITIAL() 退出临界段保护
void vPortExitCritial( void )
{configASSERT( uxCriticalNesting );uxCriticalNesting--;				// 支持嵌套使用,调用一次计数变量-1if( uxCriticalNesting == 0 )		// 支持嵌套使用,在计数变量为0时打开终端{portENABLE_INTERRUPTS();		// __enable_irq(),即打开全局中断}
}

3.2 可在中断中使用的临界段保护

  • taskENTER_CRITIAL_FROM_ISR()进入临界段保护(可在中断中使用)
__asm uint32_t ulSetInterruptMaskFromISR( void )
{mrs r0, PRIMASK		// 将PRIMASK寄存器的值保存到r0寄存器中(即返回值)cpsid i				// 关闭中断bx lr				// 将LR中的返回地址装入PC,即返回到调用程序
}

注:C语言在ARM内核上函数参数的传递通常遵循ARM Architecture Procedure Call Standard (AAPCS),该标准要求第一个参数通过R0 寄存器传递。

  • taskEXIT_CRITIAL_FROM_ISR()进入临界段保护(可在中断中使用)
__asm uint32_t vClearInterruptMaskFromISR( uint32_t ulMask )
{msr PRIMASK, r0		// 将r0寄存器的值(即ulMask)赋给PRIMASK寄存器bx lr				// 将LR中的返回地址装入PC,即返回到调用程序
}

注:AAPCS标准要求返回值通过R0 寄存器传递。

MRS:将特殊寄存器送到寄存器
MSR:将寄存器送到特殊寄存器

看来FreeRTOS也是用的这种方式来实现临界段保护的,即先保存当前状态,再禁止中断,再恢复状态。
FreeRTOS不可能没考虑到这个问题,因此看看ARM对MSR这个指令是怎么说的,有没有可能是从内核上保证了这个问题呢?

4 ARM官方对MRS指令的描述

developer.arm.com / M33 User Guide - MRS
在这里插入图片描述

翻译过来就是:
结合使用 MRSMSR 作为读-修改-写序列的一部分,用于更新 PSR,例如清除 Q 标志。
在进程交换代码中,被换出进程的程序员模型状态必须被保存,包括相关的 PSR 内容,同样,被换入进程的状态也必须被恢复。 这些操作在状态保存指令序列中使用 MRS,在状态恢复指令序列中使用 MSR

显然,ARM要求MRSMSR必须成对使用。

因此我认为前文所说的 “在中断中屏蔽全局中断,而不恢复调用中断前的屏蔽状态就退出中断” 的使用方式是不被ARM允许的,原因之一就是会破坏临界段保护。

5 参考资料

  • 《ARM Cortex-M0/M0+ 权威指南 第二版》
  • Arm Developer

相关文章:

  • 【解析:新能源汽车芯片主要玩家及技术发展】
  • 码题集——魔数、A的B次方、网球比赛、三角形、点与线段的关系
  • 数据清洗的艺术:如何为AI模型准备高质量数据集?
  • ACM算法
  • redis 缓存穿透,缓存击穿,缓存雪崩
  • LeetCode Hot100 (1/100)
  • 数据科学和机器学习的“看家兵器”——pandas模块 之一
  • flutter 视频通话flutter_webrtc
  • 【网络编程】八、Cookie Session 抓包原理
  • 火山引擎实时音视频 高代码跑通日志
  • 深度学习Dropout实现
  • day25-异常处理
  • Python爬虫之品牌口碑数据抓取
  • 设计模式(9)——创建型模式之工厂方法
  • golang -- 如何让main goroutine等一等
  • 微信小程序之按钮短时间内被多次点击问题
  • 【taro3 + vue3 + webpack4】在微信小程序中的请求封装及使用
  • DeepSeek 赋能 VR/AR:开启智能交互新纪元
  • 基于开源AI大模型与S2B2C生态的个人品牌优势挖掘与标签重构研究
  • vue使用路由技术实现登录成功后跳转到首页
  • 商务部新闻发言人就暂停17家美国实体不可靠实体清单措施答记者问
  • 盛和资源海外找稀土矿提速:拟超7亿元收购匹克,加快推动坦桑尼亚项目
  • “女硕士失踪13年生两孩”案进入审查起诉阶段,哥哥:妹妹精神状态好转
  • 白玉兰奖征片综述丨动画的IP生命力
  • 京东一季度净利增长五成,营收增速创近三年新高,称外卖业务取得显著进展
  • 山东省市监局“你点我检”专项抽检:一批次“无抗”鸡蛋农兽药残留超标