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

两种常见开关中断方式对比

经常会遇到两种典型的中断禁用 / 启用实现:一种是基于纯汇编编写的Arch_IntSave/Arch_IntDisable函数,另一种是编译器内置的__enable_irq/__disable_irq内联函数,这两种的区别和功能具体拆解一下。

一、核心实现与功能拆解

1. 纯汇编实现:Arch_IntSave/Arch_IntDisable

.globl Arch_IntSave Arch_IntSave: MRS R0, PRIMASK @ 读取PRIMASK寄存器值到R0 CPSID I @ 禁用IRQ中断 BX LR @ 返回 .globl Arch_IntDisable Arch_IntDisable: CPSID I @ 禁用IRQ中断 BX LR @ 返回
  • 核心指令解析
    • MRS R0, PRIMASK:将 PRIMASK 寄存器(ARM Cortex-M 核心的中断屏蔽寄存器)的值读取到通用寄存器 R0 中。PRIMASK 是 1 位寄存器,值为 0 时表示中断未屏蔽,值为 1 时表示仅屏蔽普通 IRQ 中断(硬件 FAULT 类异常不受影响)。
    • CPSID I:修改 CPSR(当前程序状态寄存器)的 I 位,直接禁用所有普通 IRQ 中断。
    • BX LR:函数返回,ARM 汇编中通过链接寄存器 LR 返回调用处。

2. 编译器内联汇编实现:__enable_irq/__disable_irq

/** \brief Enable IRQ Interrupts \details Enables IRQ interrupts by clearing the I-bit in the CPSR. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __enable_irq(void) { __ASM volatile ("cpsie i" : : : "memory"); } /** \brief Disable IRQ Interrupts \details Disables IRQ interrupts by setting the I-bit in the CPSR. Can only be executed in Privileged modes. */ __STATIC_FORCEINLINE void __disable_irq(void) { __ASM volatile ("cpsid i" : : : "memory"); }
  • 核心指令解析
    • __STATIC_FORCEINLINE:编译器强内联关键字,确保函数直接嵌入调用处,无函数调用开销。
    • __ASM volatile ("cpsie/cpsid i" : : : "memory"):内联汇编执行中断开关指令,volatile防止编译器优化该指令,memory约束告知编译器该指令会修改内存状态,避免内存重排序。
    • cpsie i:清除 CPSR 的 I 位,启用 IRQ 中断;cpsid i:设置 CPSR 的 I 位,禁用 IRQ 中断。

二、核心区别对比

1. 功能完整性:“仅禁用” vs “保存 + 禁用”

这是二者最核心的区别,也是嵌入式开发中最易踩坑的点:

  • Arch_IntDisable:仅执行CPSID I,单纯禁用中断,无任何状态保存;Arch_IntSave则在禁用中断前,先读取当前 PRIMASK 寄存器的值并通过 R0 返回 —— 这意味着Arch_IntSave保存中断禁用前的原始状态
  • __disable_irq:仅执行cpsid i禁用中断,无状态保存;__enable_irq仅执行cpsie i启用中断,二者均不涉及任何中断状态的读取或保存。

直接调用__disable_irq后调用__enable_irq,可能破坏系统原有中断状态 —— 若调用__disable_irq前中断已被禁用,执行__enable_irq会错误启用中断,导致临界区保护失效。

2. 调用开销:汇编函数 vs 内联函数

  • Arch_IntSave/Arch_IntDisable:作为独立汇编函数,调用时会产生函数调用开销(如 LR 寄存器入栈、PC 跳转),在对执行效率要求极高的临界区(如实时性要求微秒级的外设操作)中,额外开销可能影响性能。
  • __enable_irq/__disable_irq:通过__STATIC_FORCEINLINE实现强内联,汇编指令直接嵌入调用处,无函数调用开销,执行效率与直接写汇编指令一致。

内联汇编的中断操作指令,在编译器优化开启时(-O2/-O3),执行周期与纯汇编指令完全一致,且避免了函数调用的栈操作开销。

3. 状态恢复能力:可精准恢复 vs 强制恢复

  • Arch_IntSave:返回值为中断禁用前的 PRIMASK 状态,开发者可保存该值,在临界区结束后通过MSR PRIMASK, R0恢复原始中断状态 —— 即使调用前中断已被禁用,也不会错误启用。示例:
    ; 调用Arch_IntSave保存状态并禁用中断 BL Arch_IntSave PUSH R0 ; 保存原始PRIMASK值到栈 ; 临界区代码(如操作共享资源) POP R0 ; 取出原始PRIMASK值 MSR PRIMASK, R0 ; 恢复中断状态(而非强制启用)
  • __enable_irq:强制执行cpsie i启用中断,无论调用前中断状态如何,都会直接开启 IRQ—— 若临界区嵌套调用(如 A 函数禁用中断后调用 B 函数,B 函数执行__enable_irq),会导致 A 函数的临界区失去中断保护。

4. 可移植性与编译器兼容性

  • Arch_IntSave/Arch_IntDisable:纯汇编代码,与编译器无关(如 ARMCC、GCC、Clang 均可兼容),但依赖具体的 ARM 内核架构(仅适用于 Cortex-M 系列)。
  • __enable_irq/__disable_irq:属于编译器内置函数(如 ARMCC 的cmsis_gcc.hcmsis_armcc.h中定义),不同编译器的实现可能略有差异(如 GCC 需添加memory约束,ARMCC 则无需),但符合 CMSIS 标准的编译器均提供该接口,可移植性更强。

三、使用场景选择

1. 优先使用 Arch_IntSave 的场景

  • 临界区嵌套调用:如中断服务函数中调用其他需要禁用中断的函数,需保存原始中断状态,避免错误启用;
  • 精准控制中断状态:如仅临时禁用中断,执行完临界区后需完全恢复原有状态(而非强制启用);
  • 底层内核代码:如操作系统的任务切换、锁机制实现,需最大程度保证中断状态的准确性。

2. 优先使用__enable_irq/__disable_irq 的场景

  • 简单临界区:无嵌套调用的单次中断禁用 / 启用,如单次读写外设寄存器;
  • 跨编译器开发:项目需兼容 ARMCC、GCC 等多种编译器,遵循 CMSIS 标准;
  • 对执行效率要求极高:内联函数无调用开销,适合微秒级响应的实时场景。
http://www.jsqmd.com/news/139685/

相关文章:

  • 装配制造业 - 风机核心产品
  • 解决requestFullscreen()全屏模式下复制功能丢失问题
  • Windows系统文件usbperf.dll丢失损坏问题 下载修复
  • 从理论到实战:SVM 参数调优与核技巧可视化全解析
  • 12-22 关于顺FENG在数字化转型方向上的思考
  • 软件工程基础第四次作业
  • Windows系统文件user32.dll丢失损坏 下载修复
  • Python在微服务分布式设置中心与动态服务发现中的架构设计实践
  • 第六十五篇
  • 2025 MBA必备!10个降AI率工具测评榜单
  • 供应链计划系统架构实战(一):核心概念与体系概述 - 详解
  • 软件工程组第四次作业
  • 模块化多电平变换器MMC的两种调制策略实现与仿真:NLM与CPS-PWM的对比研究
  • 禅道创建成品
  • 2025最强AI写论文神器:9款实测,AIGC率82%狂降至12%! - 麟书学长
  • 人生是否是NP难问题?
  • 三相PWM整流器闭环仿真,电压电流双闭环控制,输出直流电压做外环 模型中包含主电路,坐标变换...
  • 从化房地产开发公司选哪家:官方排名与深度解析 - 品牌测评家
  • Java毕设选题推荐:基于springboot的物流管理系统基于Springboot+Vue智能物流管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 【场景篇】这家头部家纺品牌的AI能力底座王牌是AI系统工程
  • 【NDK / JNI】Sceneform-EQR 集成 Filament JNI 源码:关键点与逐步操作记录 - EQ
  • 流量洪峰下的交通指挥家:详解负载均衡与限流实战
  • 团队推行敏捷开发两年,为何感觉效率不升反降?
  • 防水胶带正规厂商、品牌商、生产企业的全面解读与南通众皓推荐
  • 别再自己飞无人机了!这4个网站,高清航拍素材直接免费用!
  • 防水丁基胶带大型厂家及定制生产厂家的选购指南
  • 人工智能之数学基础 离散数学:第四章 离散概率
  • 探秘辉昂印刷厂的发展前景、技术实力
  • 探寻辉昂印刷厂:研发、排版与团队实力揭秘
  • Vue.js 中 Axios 的使用学习感悟与实践总结