☰
PRIMASK和BASEPRI 中断优先级的区别和联系
2026/10/8 7:02:37 网站建设 项目流程

PRIMASK 和 BASEPRI 都是 Cortex-M 内核的中断屏蔽寄存器,区别在于屏蔽的“粒度”不同:

  • PRIMASK:全局开关,一关全关(除了 NMI 和 HardFault)。

  • BASEPRI:优先级阈值开关,只关掉优先级低于某个阈值的中断,高优先级中断不受影响。


1. PRIMASK

  • 位宽:1 位。

  • 作用:写 1 后,屏蔽所有可配置优先级的中断和异常,只有NMI和HardFault不受影响。

  • 写 0:不屏蔽任何中断。

  • CMSIS 函数:

    c

    __disable_irq(); // 设置 PRIMASK = 1 __enable_irq(); // 设置 PRIMASK = 0
  • 典型用途:全局关中断、低功耗进入 WFI 前防止临界区被打断。

  • 对 WFI 的影响:

    • 即使PRIMASK = 1,WFI 仍然可以被中断唤醒。

    • 但唤醒后不会执行中断服务函数,直到PRIMASK被清零。

    • 所以 FreeRTOS 的 tickless idle 常用__disable_irq()包住__WFI(),这样任何中断都能唤醒 CPU,但不会立刻执行 ISR。


2. BASEPRI

  • 位宽:8 位(实际有效位取决于芯片实现的优先级位数)。

  • 作用:

    • 写 0:不屏蔽任何中断。

    • 写非 0 值 N:屏蔽所有优先级数值 ≥ N的中断(即逻辑优先级 ≤ N 的中断)。

    • 优先级数值 < N 的高优先级中断不受影响。

  • CMSIS 函数:

    c

    __set_BASEPRI(N); __get_BASEPRI();
  • 典型用途:FreeRTOS 临界区,选择性屏蔽低优先级中断,允许高优先级中断继续响应。

  • 对 WFI 的影响:

    • 被 BASEPRI 屏蔽的中断不能唤醒 WFI。

    • 所以如果在BASEPRI != 0时执行WFI,只有优先级高于 BASEPRI 阈值的中断才能唤醒 CPU。

    • 这也是为什么低功耗睡眠前通常不用 BASEPRI 屏蔽中断,而用 PRIMASK。


3. 对比总结

特性PRIMASKBASEPRI
位宽1 位8 位
屏蔽范围所有可配置优先级中断优先级数值 ≥ 阈值的中断
影响 NMI/HardFault否否
写 0允许所有中断不屏蔽任何中断
典型用途全局关中断、WFI 前FreeRTOS 临界区、选择性屏蔽
WFI 唤醒仍可唤醒,但不执行 ISR被屏蔽的中断不能唤醒
CMSIS__disable_irq()/__enable_irq()__set_BASEPRI()/__get_BASEPRI()

4. 在 FreeRTOS 中的使用

  • 临界区:

    c

    taskENTER_CRITICAL(); // 此处 BASEPRI = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY taskEXIT_CRITICAL(); // BASEPRI = 0

    这样只有优先级高于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY的中断能打断临界区,且这些中断不能调用 FreeRTOS 的 FromISR API。

  • Tickless idle:
    使用__disable_irq()(PRIMASK)而不是 BASEPRI,确保任何中断都能把 CPU 从WFI唤醒,唤醒后再__enable_irq()让 ISR 执行。


5. 常见误区

  • PRIMASK = 1 不是让 WFI 不唤醒,而是唤醒后不执行 ISR。

  • BASEPRI 屏蔽的中断不能唤醒 WFI。

  • BASEPRI = 0 时,任何已使能的中断都能唤醒 WFI,与优先级无关。

  • 高优先级中断(优先级数值 <configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY)不能调用 FreeRTOS 的FromISRAPI,因为 FreeRTOS 无法用 BASEPRI 屏蔽它们。

一句话:PRIMASK 是全局中断开关,BASEPRI 是优先级阈值开关;WFI 怕 BASEPRI,不怕 PRIMASK

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询