__set_PRIMASK();函数的功能,以及和其他屏蔽中断函数的区别

__set_PRIMASK() 是 ARM Cortex-M 处理器中用于中断控制的重要函数,下面详细说明其功能及与其他中断屏蔽函数的区别。

__set_PRIMASK() 功能详解

基本功能

c

// 禁用所有中断(除了NMI和HardFault)
__set_PRIMASK(1);

// 启用所有中断
__set_PRIMASK(0);

特点

  • 全局中断控制:影响所有可屏蔽中断

  • 优先级最高:在三个中断屏蔽寄存器中级别最高

  • 简单粗暴:直接开关所有中断

三种主要的中断屏蔽寄存器对比

1. PRIMASK(最高级别)

c

// 使用方法
void critical_section(void) {
    uint32_t primask = __get_PRIMASK();  // 保存状态
    __set_PRIMASK(1);                    // 禁用所有中断
    
    // 临界区代码
    atomic_operation();
    
    __set_PRIMASK(primask);              // 恢复原状态
}

特点:

  • 只控制普通中断

  • 不影响 NMI、HardFault

  • 单比特寄存器(0=启用,1=禁用)

2. FAULTMASK(中级)

c

// 使用方法
__set_FAULTMASK(1);   // 禁用所有中断,包括HardFault
__set_FAULTMASK(0);   // 启用中断

特点:

  • 禁用所有中断,包括 HardFault

  • 不影响 NMI

  • 通常用于错误处理

3. BASEPRI(最精细)

c

// 使用方法
// 屏蔽所有优先级低于等于0x10的中断
__set_BASEPRI(0x10);

// 取消屏蔽
__set_BASEPRI(0);

特点:

  • 基于优先级屏蔽

  • 可选择性屏蔽低优先级中断

  • 不影响高优先级中断

详细区别对比表

特性 PRIMASK FAULTMASK BASEPRI
控制范围 所有可屏蔽中断 所有中断(除NMI) 基于优先级
影响HardFault
使用场景 一般临界区 错误处理 实时性要求高的场景
精细度 精细
推荐使用 ★★★★ ★★ ★★★★★

实际应用示例

推荐做法:使用 BASEPRI(最优)

c

void critical_operation(void) {
    // 屏蔽优先级低于0x20的中断
    uint32_t basepri = __get_BASEPRI();
    __set_BASEPRI(0x20 << (8 - __NVIC_PRIO_BITS));
    
    // 临界区代码 - 高优先级中断仍可响应
    do_critical_work();
    
    __set_BASEPRI(basepri);  // 恢复原优先级阈值
}

一般做法:使用 PRIMASK

c

void simple_critical_section(void) {
    uint32_t primask = __get_PRIMASK();
    __disable_irq();  // 等效于 __set_PRIMASK(1)
    
    // 简单的临界区操作
    shared_variable++;
    
    __set_PRIMASK(primask);
}

错误处理:使用 FAULTMASK

c

void fault_handler(void) {
    __set_FAULTMASK(1);  // 屏蔽所有中断,包括HardFault
    
    // 执行关键的错误恢复操作
    system_recovery();
    
    __set_FAULTMASK(0);  // 重新启用中断
}

总结建议

  1. 优先使用 BASEPRI - 提供最好的实时性

  2. 谨慎使用 PRIMASK - 会影响所有中断响应

  3. 特殊情况用 FAULTMASK - 仅在错误处理中使用

  4. 始终保存和恢复状态 - 支持嵌套调用

在大多数嵌入式应用中,推荐使用 BASEPRI 进行精细的中断控制,只有在极短的临界区或兼容性要求时才使用 PRIMASK

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐