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


    引言

    在平时的工作中,我们经常会遇到这样的情况:有人来找你做一些事情,而且这些事情要比手头的工作更重要。那现在就需要停下手中的工作,先去完成突然到来的这部分工作。这样的情况也类似于图论中的关键路径中,突然在当前事件之前插入了一个新的事件,那我们不得不先去完成之前的那个任务,才能继续完成后面的工作。

    上述情况是非常常见的,那在STM32中,我们如果遇到了比当前任务更紧急的事情需要去处理,我们应该怎么办呢?这个时候,我们需要通过中断来完成这样的任务。

    在现实生活中,突然出现的任务一定有轻重缓急之分。如果同时出现许多的临时任务,我们一定会首先评估他们谁更需要先被处理掉,然后再依次进行处理。在STM32中,我们也需要这样的功能,多个中断来临的时候,我们需要首先判断这个中断紧不紧急,然后再考虑处理的先后顺序。那我们是由什么来控制这样的顺序的呢?毫无疑问,这就是通过嵌套向量中断控制器(NVIC)完成的。




    NVIC简介

    CM3内核支持256个中断,包括16个内核中断和250个外部中断,同时具有256级的可编程中断设置。而STM32只使用了一部分。STM32拥有84个中断,包括16个内核中断和68个可屏蔽中断(STM32F107系列才使用了68个可屏蔽中断),还拥有16级可编程的中断优先级。STM32F103系列只使用了60个可屏蔽中断。

    STM32中控制中断优先级的寄存器组是IP[240]。是由240个8bit的寄存器组成的。而STM32F103只用了前六十个(0 ~ 59)。在STM32F103系列单片机中,这8bit也没有全部使用,而是只使用了其高四位(4 ~ 7位)。下图是中断分组的分配情况。

    优先级分组 抢占优先级 响应优先级 高四位描述
    0 0级 0 ~ 15级 0bit用于抢占优先级
    4bit用于响应优先级
    1 0 ~ 1级 0 ~ 7级 1bit用于抢占优先级
    3bit用于响应优先级
    2 0 ~ 3级 0 ~ 3级 2bit用于抢占优先级
    2bit用于响应优先级
    3 0 ~ 7级 0 ~ 1级 3bit用于抢占优先级
    1bit用于响应优先级
    4 0 ~ 15级 0级 4bit用于抢占优先级
    0bit用于响应优先级

    响应优先级又称为子优先级。
    数值越小,优先级越高。

    这里需要关注的是,抢占优先级的级别高于子优先级。高抢占优先级的中断可以在低抢占优先级中断执行的过程中被响应,反之则不行。这就是所谓的中断嵌套。换句话说呢,就是高抢占优先级中断可以抢占低抢占优先级中断的执行。当多个中断同时到来,而且他们的抢占优先级相同,则先进入子优先级更高的中断。

    但是,当抢占优先级相同的情况下,高子优先级中断不能打断低子优先级中断,也就是不能实现中断嵌套。这种情况下,高子优先级中断必须先等待低子优先级中断执行完成,在进行自己的中断。




    软件部分

    配置某个中断优先级的步骤如下:

    • 配置中断优先级分组
    • 配置某一中断的优先级

    配置中断优先级分组

    这一步可以通过函数 NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) 来完成。关于优先级分组的内容上文已经做过了讲解。这里提供一个使用范例:

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    配置某一个中断的优先级

    这一步我们需要用到一个函数 NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) 。里面的结构体的成员变量如下:

    typedef struct
    {
    	uint8_t NVIC_IRQChannel;			//中断名称
    	uint8_t NVIC_IRQChannelPreemptionPriority;	//抢占优先级
    	uint8_t NVIC_IRQChannelSubPriority;		//响应优先级
    	FunctionalState NVIC_IRQChannelCmd;		//中断使能
    
    }NVIC_InitTypeDef;
    

    因此,配置某一中断优先级的步骤如下:

    • 声明上述结构体
    • 配置结构体成员变量的值
    • 利用 NVIC_Init 函数初始化

    这里给出一个范例:

    NVIC_InitTypeDef NVIC_InitStructure;	//声明结构体
    
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                  //声明中断名称
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;      //设置抢占优先级为2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;             //设置响应优先级为3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		          //使能中断
    
    NVIC_Init(&NVIC_InitStructure);			//对上述配置进行初始化
    

    至此,我们就完成了对某一中断优先级的配置,再根据不同的中断配置不同的触发条件等信息,就可以完成在特定条件下的中断。这里不再展开叙述。


    关于NVIC和中断嵌套的更多的神奇理解可以参考下面这篇文章的后半部分:STM32 NVIC

    我是这耀眼的瞬间,是划过天边的刹那火焰。
  • 相关阅读:
    pandas 修改列顺序
    read_csv,to_csv 前n行
    郭盛华:未来黑客攻击的将远不止网络
    微软的 Linux 存储库停机 18 多个小时
    警惕黑客利用 Google Docs进行网络钓鱼
    苹果发布紧急补丁!修复被黑客利用的2个零日漏洞
    谷歌发布新框架以防止软件供应链攻击
    郭盛华:以知识见识锤炼真本领,年轻人要有理想
    通过 GDPR 加强密码政策,是企业网络的第一道防线
    肉类供应商遭黑客攻击,并支付了 1100 万美元的赎金
  • 原文地址:https://www.cnblogs.com/Rane/p/13603323.html
Copyright © 2020-2023  润新知