• STM32 中的嵌套向量中断控制器(NVIC)详解


    首先明确:

    抢占优先级决定“能不能打断”;响应优先级决定“同时等待时谁先执行”。

    1. NVIC 是什么

    NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)负责:

    • 开启、关闭中断
    • 保存中断的挂起状态
    • 判断多个中断的执行顺序
    • 实现中断嵌套
    • 根据中断号找到对应的中断服务函数

    所谓“嵌套”,就是 CPU 正在执行一个中断服务函数时,可以被更高抢占优先级的中断打断。

    2. STM32 的优先级数字越小,等级越高

    优先级数值 0 > 优先级数值 1 > 优先级数值 2 ...

    这里的 > 表示“实际优先级更高”。

    例如:

    中断A:抢占优先级 = 0
    中断B:抢占优先级 = 2

    A 的优先级高于 B。B 执行过程中,A 可以打断 B。

    3. NVIC的 4 位优先级

    很多 STM32 芯片实际实现了 4 个优先级位,因此一共有:[2^4=16]
    个编码值,也就是 0~15。

    这 4 位可以切分成两部分:

    4个优先级位 = 抢占优先级位 + 响应优先级位

    分成五种模式:

    分组 抢占优先级位数 抢占值范围 响应优先级位数 响应值范围
    分组0 0位 只能为0 4位 0~15
    分组1 1位 0~1 3位 0~7
    分组2 2位 0~3 2位 0~3
    分组3 3位 0~7 1位 0~1
    分组4 4位 0~15 0位 只能为0

    这里的 4 位不是说每个中断都有两个独立的 4 位字段,而是说:

    总共只有 4 位,需要在抢占优先级和响应优先级之间分配。

    4. 抢占优先级:决定能否发生中断嵌套

    假设:

    中断A:抢占优先级 1
    中断B:抢占优先级 2

    由于数值越小优先级越高,因此 A 的抢占优先级高于 B。

    如果 CPU 正在执行 B,此时 A 到来:

    执行B → A到来 → 暂停B → 执行A → A结束 → 继续执行B

    这就是中断嵌套。

    反过来,如果正在执行 A,B 到来,B 不能打断 A,只能进入挂起状态,等 A 执行完再处理。

    重要规则

    只有抢占优先级不同,才可能发生嵌套。

    响应优先级再高,也不能打断正在执行的中断。

    5. 响应优先级:决定挂起中断的先后顺序

    响应优先级也常被称为:

    • 子优先级
    • SubPriority
    • 次优先级

    假设两个中断的抢占优先级相同:

    中断A:抢占优先级 1,响应优先级 0
    中断B:抢占优先级 1,响应优先级 2

    如果 CPU 正在执行主程序,并且 A、B 几乎同时进入挂起状态,那么响应优先级更高的 A 先执行。

    A先执行 → A结束 → B执行

    但如果 B 已经开始执行,这时 A 才到来,A通常不能打断 B,因为二者抢占优先级相同。

    也就是说:

    响应优先级只负责“排队”,不负责“抢占”。

    6. 如果抢占优先级和响应优先级都相同

    抢占优先级和响应优先级均相同的,按中断号排队。

    此时由异常号/IRQ 编号进行最终裁决,通常中断号较小者优先。

    例如两个中断的配置完全相同:

    EXTI0_IRQn = 6
    TIM2_IRQn = 28

    如果二者同时挂起,一般 EXTI0_IRQn 对应的异常编号更小,因此会先得到响应。

    不过实际程序不应过度依赖这一条,最好通过合理设置优先级明确执行次序。

    7. 五种分组分别适合什么情况

    分组0:没有中断嵌套

    抢占优先级:无
    响应优先级:0~15

    所有外部中断的抢占等级都相同,因此外部中断之间不能相互抢占,只能排队执行。

    适合:

    • 不希望出现中断嵌套
    • 系统结构简单
    • 通过响应优先级安排执行次序

    分组1

    抢占优先级:0~1
    响应优先级:0~7

    只有两个抢占等级,但每个等级内部可以进行较细的排序。

    适合嵌套层数较少、同级中断较多的系统。

    分组2

    抢占优先级:0~3
    响应优先级:0~3

    抢占能力和排队能力比较均衡,是常见选择之一。

    分组3

    抢占优先级:0~7
    响应优先级:0~1

    可以划分较多抢占等级,但同一抢占等级下只有两个响应等级。

    分组4:全部用于抢占

    抢占优先级:0~15
    响应优先级:无

    可以设置很多抢占层级,但没有可配置的响应优先级。

    适合更强调中断嵌套层次的系统。

    8. 分组2实例

    假设系统采用分组2:

    NVIC_PRIORITYGROUP_2

    此时:

    抢占优先级范围:0~3
    响应优先级范围:0~3

    配置三个中断:

    中断 抢占优先级 响应优先级
    USART1 1 2
    TIM2 2 0
    EXTI0 1 0

    可以得出:

    1. USART1 能打断 TIM2,因为 1 < 2。
    2. EXTI0 也能打断 TIM2。
    3. USART1 与 EXTI0 抢占优先级相同,不能互相打断。
    4. 当二者同时等待时,EXTI0 的响应优先级为 0,因此先于 USART1 执行。
    5. 如果 USART1 已经进入中断服务函数,随后 EXTI0 到来,EXTI0 不能仅凭响应优先级打断 USART1。

    一句话记忆

    抢占优先级不同:看谁能打断谁。
    抢占优先级相同:不能互相打断。
    同时处于等待状态:再比较响应优先级。
    两者都相同:通常由中断号较小者先响应。
    所有优先级都是数值越小越高。

本文作者:wangzhengyi

本文链接:https://www.cnblogs.com/wangzhengyi/p/22948947

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

  • 相关阅读:
    深度解析服务细分赛道公链
    山西电力市场日前价格预测【2023-10-12】
    webpack之Scope Hoisting(范围提升)
    读书感悟【Vue.js设计与实现】第1章 权衡的艺术 【Vue进阶系列】
    Linux 下搭建 Hadoop 环境
    小红书七夕营销攻略,玩出新花样(内附小红书推广方案干货)
    前端工程师的vue面试题笔记
    别再用if-else了,分享一下我使用“策略模式”的项目经验...
    JAVA 实现《JAVA打砖块》游戏
    进入“终端”又名“命令提示符”、“黑窗口”的方式
  • 原文地址:https://www.cnblogs.com/wangzhengyi/p/22948947