以下转载自安富莱电子: http://forum.armfly.com/forum.php

NVIC 的全称是 Nested vectored interrupt controller,即嵌套向量中断控制器。
对于 M3 和 M4 内核的 MCU,每个中断的优先级都是用寄存器中的 8 位来设置的。 8 位的话就可以
设置 2^8 = 256 级中断,实际中用不了这么多,所以芯片厂商根据自己生产的芯片做出了调整。比如 ST
的 STM32F1xx 和 F4xx 只使用了这个 8 位中的高四位[7:4],低四位取零,这样 2^4=16,只能表示 16
级中断嵌套。
对于这个 NVIC,有个重要的知识点就是优先级分组,抢占优先级和子优先级,下面就以 STM32 为
例进行介绍,STM32F1xx 和 F4xx 都是只使用了这个 8 位寄存器的高四位[7:4]。

从上面的表格可以看出,STM32 支持 5 种优先级分组,系统上电复位后,默认使用的是优先级分组
0,也就是没有抢占式优先级,只有子优先级,关于这个抢占优先级和这个子优先级有几点一定要说清楚。
 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断服务程序执行过程中被响应,即中
断嵌套,或者说高抢占式优先级的中断可以抢占低抢占式优先级的中断的执行。
 在抢占式优先级相同的情况下,有几个子优先级不同的中断同时到来,那么高子优先级的中断优
先被响应。
 在抢占式优先级相同的情况下,如果有低子优先级中断正在执行,高子优先级的中断要等待已被
响应的低子优先级中断执行结束后才能得到响应,即子优先级不支持中断嵌套。
 Reset、 NMI、 Hard Fault 优先级为负数,高于普通中断优先级,且优先级不可配置。
 对于初学者还有一个比较纠结的问题就是系统中断(比如:PendSV,SVC,SysTick)是不是一
定比外部中断(比如 SPI,USART)要高,答案:不是的,它们是在同一个 NVIC 下面设置的。

具体可以点击这里查看之前的随笔。

强烈推荐用户将 Cortex-M3 内核的 STM32F103 和 Cortex-M4 内核的 STM32F407 以及
STM32F429 的 NVIC 优先级分组设置为 4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);这
样中断优先级的管理将非常方便。 这个也是官方强烈建议的。

(注意:一旦初始化好 NVIC 的优先级分组后,切不可以在应用中再次更改。)
设置 NVIC 的优先级分组为 4 表示支持 0-15 级抢占优先级 (注意, 0-15 级是 16 个级别,包含 0 级), 不支持子优先级。
在这里继续强调下这一点,在 NVIC 分组为 4 的情况下,抢占优先级可配置范围是 0-15,那么数值越小,抢占优先级的级别越高,即 0 代表最高优先级,15 代表最低优先级。

FreeRTOS 配置选项中 NVIC 相关配置
FreeRTOSConfig.h 配置文件中设置到 NVIC 中断的有如下几个选项:

/*
* Cortex-M内核使用8bit来配置优先级,但是STM32只使用了高4bit,数值越小,优先级越高。
* 在往寄存器里面写数值配置的时候,是按照8bit来写的,所以真正写的时候需要经过转换,公式为:
* ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff),其中的priority就是我们配置的真正的优先级
*/
#ifdef __NVIC_PRIO_BITS /* __NVIC_PRIO_BITS 已经在stm32f4xx.h里面定义为4 */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
/*============================================== SysTick中断优先级配置 ============================================*/
/*
* 在往寄存器里面写数值配置的时候,是按照8bit来写的,所以真正写的时候需要经过转换,公式为:
* ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff),其中的priority就是我们配置的真正的优先级。经过这个公式之后得到的是
* 下面的这个宏:configKERNEL_INTERRUPT_PRIORITY
* SysTick的优先级我们一般配置为最低,即0xf 。这样可以提高系统的实时响应能力,即其他的外部中断可以及时的得到响应。
*/
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) /*===========================================可屏蔽的中断优先级配置====================================================*/
/*
* 用于配置STM32的特殊寄存器basepri寄存器的值,用于屏蔽中断,当大于basepri值的优先级的中断将被全部屏蔽。basepri只有4bit有效,
* 默认只为0,即全部中断都没有被屏蔽。configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY配置为:5,意思就是中断优先级大于5的中断都被屏蔽。
* 当把配置好的优先级写到寄存器的时候,是按照8bit来写的,所以真正写的时候需要经过转换,公式为:
* ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff),其中的priority就是我们配置的真正的优先级。经过这个公式之后得到的是下面的这个宏:
* configMAX_SYSCALL_INTERRUPT_PRIORITY
*
* 在FreeRTOS中,关中断是通过配置basepri寄存器来实现的,关掉的中断由配置的basepri的值决定,小于basepri值的
* 中断FreeRTOS是关不掉的,这样做的好处是可以系统设计者可以人为的控制那些非常重要的中断不能被关闭,在紧要的关头必须被响应。
* 而在UCOS中,关中断是通过控制PRIMASK来实现的,PRIMASK是一个单1的二进制位,写1则除能除了NMI和硬 fault的所有中断。当UCOS关闭
* 中断之后,即使是你在系统中设计的非常紧急的中断来了都不能马上响应,这加大了中断延迟的时间,如果是性命攸关的场合,那后果估计挺严重。
* 相比UCOS的关中断的设计,FreeRTOS的设计则显得人性化很多。
*
*/
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

#define configPRIO_BITS 4
此宏定义用于配置 STM32 的 8 位优先级设置寄存器实际使用的位数。 STM32F103,STM32F407
和 STM32F429 都是使用的 4 位。 另外注意一点,这里使用了一个条件编译,用户可以选择将条件编
译删掉,直接定义一个#define configPRIO_BITS 4 即可。使用条件编译的好处就是方便与系统统
一。这个__NVIC_PRIO_BITS 在 STM32F103 标准库的头文件 stm32f10x.h 中以及 STM32F407/439
的标准库的头文件 stm32f4xx.h 中分别有定义。如果用户在 FreeRTOSConfig.h 文件里面包含了这个
标准库的头文件,那么就会执行条件编译选项:
#define configPRIO_BITS __NVIC_PRIO_BITS

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f
此宏定义是用来配置 FreeRTOS 用到的 SysTick 中断和 PendSV 中断的优先级。在 NVIC 分组设置为
4 的情况下,此宏定义的范围就是 0-15,即专门配置抢占优先级。这里配置为了 0x0f,即 SysTick
和 PendSV 都是配置为了最低优先级,实际项目中也建议大家配置最低优先级即可。
 SVC 中断
在 FreeRTOS 的移植文件 ports.c 中有用到 SVC 中断的 0 号系统服务,即 SVC 0。此中断在 FreeRTOS
中仅执行一次, 用于启动第一个要执行的任务。 另外, 由于 FreeRTOS 没有配置 SVC 的中断优先级,
默认没有配置的情况下, SVC 中断的优先级就是最高的 0。 如果用户在不清楚自己配置的 PendSV 和
SysTick 中断是否跟实际情况一致时,可以进行硬件调试。 比如 MDK,我们可以在硬件调试的状态下,
先点击全速运行,然后查看如下调试组件:

#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY  0x01
此宏定义比较重要,定义了受 FreeRTOS 管理的最高优先级中断。简单的说就是允许用户在这个中断
服务程序里面调用 FreeRTOS 的 API 的最高优先级。 设置 NVIC 的优先级分组为 4 的情况下。 配置
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 为 0x01 表示用户可以在抢占式优先级为 1

到 15 的中断里面调用 FreeRTOS 的 API 函数,抢占式优先级为 0 的中断里面是不允许调用的。 不受
FreeRTOS 管理的中断有什么深层的含义吗?

不受 FreeRTOS 管理中断的深入讨论
讲解不受 FreeRTOS 管理的中断之前要说一个小知识点----中断延迟。 中断延迟时间是衡量 RTOS 实
时操作系统的一项重要指标,那什么又是中断延迟呢?从中断触发到执行中断服务程序的第一条指令这段
时间就是中断延迟时间。
FreeRTOS 内核源码中有多处开关全局中断的地方,这些开关全局中断会加大中断延迟时间。 比如在
源码的某个地方关闭了全局中断,但是此时有外部中断触发,这个中断的服务程序就需要等到再次开启全
局中断后才可以得到执行。开关中断之间的时间越长,中断延迟时间就越大,这样极其影响系统的实时性。
如果这是一个紧急的中断事件,得不到及时执行的话,后果是可想而知的。
针对这种情况,FreeRTOS 就专门做了一种新的开关中断实现机制。 关闭中断时仅关闭受 FreeRTOS
管理的中断,不受 FreeRTOS 管理的中断不关闭,这些不受管理的中断都是高优先级的中断,用户可以在
这些中断里面加入需要实时响应的程序。 FreeRTOS 能够实现这种功能的奥秘就在于 FreeRTOS 开关中断
使用的是寄存器 basepri,而像 uCOS 这种使用的是 primask,详情请看下面整理的表格:

#define configKERNEL_INTERRUPT_PRIORITY
宏定义 configLIBRARY_LOWEST_INTERRUPT_PRIORITY的数值经过 4bit偏移后得到一个 8bit
的优先级数值,即宏定义 configKERNEL_INTERRUPT_PRIORITY 的数值。这个 8bit 的数值才可以
实际赋值给相应中断的优先级寄存器。
也许初学者有疑问了,为什么前面 NVIC 配置的时候不是 8bit 的方式进行配置?这是因为 ST 的
库函数 NVIC_Init()已经为我们做好了。 这里的宏定义数值是供 PendSV 和 SysTick 中断进行优先级
配置的。 比如:我们这里配置宏定义 configLIBRARY_LOWEST_INTERRUPT_PRIORITY 是 0x0f,经
过 4bit 偏移后就是 0xf0,即 SysTick 和 PendSV 的中断优先级就是 240。

#define configMAX_SYSCALL_INTERRUPT_PRIORITY
宏定义 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 的数值经过 4bit 偏移后得到一
个 8bit 的优先级数值,即宏定义 configMAX_SYSCALL_INTERRUPT_PRIORITY 的数值。 这个数值
是赋值给寄存器 basepri 使用的,8bit 的数值才可以实际赋值给相应中断的优先级寄存器。
这里的宏定义数值赋给寄存器 basepri 后就可以实现全局的开关中断操作了。 比如:我们这里配
置宏定义 configLIBRARY_LOWEST_INTERRUPT_PRIORITY 是 0x01,经过 4bit 偏移后就是 0x10,
即 16。 调用了 FreeRTOS 的关中断后,所有优先级数值大于等于 16 的中断都会被关闭。优先级数值
小于 16 的中断不会被关闭,对寄存器 basepri 寄存器赋值 0,那么被关闭的中断会被打开。

上面的优先级数值,240和16,是十进制数,是真正8bit的数值,但是ST给我们了库函数,我们只配置4-7位,就可以了,其实就在配置这4-7位为0xf,表示优先级为15,实际十进制为240,配置这4-7位为 0x1,表示优先级为1,实际十进制为16.不要混淆了。
 NOTE:

这里configMAX_SYSCALL_INTERRUPT_PRIORITY的优先级是个8bit的,之前的configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY是4bit,注意有没有LIBRARY。

FreeRTOS 中断优先级配置(重要)的更多相关文章

  1. FreeRTOS中断优先级配置(重要)

    FreeRTOS中断优先级配置(重要) 本章节为大家讲解FreeRTOS中断优先级配置,此章节非常重要,初学者经常在这里犯迷糊.对于初学者来说,本章节务必要整明白.12.1 NVIC基础知识12.2  ...

  2. 记一次FreeRTOS错误配置导致无法进入临界区

    最近项目用到FreeRTOS,在实际调试中发现我自己的一段代码本来好用的(在无RTOS的情况下),但是当我在带RTOS的情况下把代码放到一个单独的任务中运行时我发现本来好用的代码莫名其妙的出现问题,有 ...

  3. FreeRTOS 中断优先级嵌套错误引发HardFault异常解决(转)

      最近在使用FreeRTOS的时候,突然发现程序在运行了几分钟之后所有的任务都不再调用了,只有几个中断能正常使用,看来是系统挂掉了,连续测试了几次想找出问题,可是这个真的有点不知所措.      我 ...

  4. FreeRTOS 中断优先级嵌套错误引发HardFault异常解决

          最近在使用FreeRTOS的时候,突然发现程序在运行了几分钟之后所有的任务都不再调用了,只有几个中断能正常使用,看来是系统挂掉了,连续测试了几次想找出问题,可是这个真的有点不知所措.   ...

  5. FreeRTOS 中断配置和临界段

    中断屏蔽寄存器 PRIMASK.FAULTMASK和BASEPRI 1.PRIMASK:这是个只有1个位的寄存器.当它置1时, 就关掉所有可屏蔽的异常,只剩下 NMI和硬fault可以响应.它的缺省值 ...

  6. FreeRTOS基础篇教程目录汇总

    以下教程(大部分章节)(尤其理论介绍部分)转载自安富莱电子,官网链接: http://forum.armfly.com/forum.php 然后根据安富莱的教程自己做了分析和测试,希望大家共同进步. ...

  7. 使用 FreeRTOS 时注意事项总结(基础篇教程完结)

    以下转载自安富莱电子: http://forum.armfly.com/forum.php FreeRTOS 的初始化流程推荐的初始化流程如下,本教程配套的所有例子都是采用的这种形式,当然,不限制必须 ...

  8. 1、FreeRTOS移植

    1.FreeRTOS目录结构 FreeRTOS FreeRTOS简略目录如下: ├─FreeRTOS │ ├─Demo // 各种开发工具的完整Demo,开发者可以方便的以此搭建出自己的项目,甚至直接 ...

  9. freeRTOSConfig.h文件对FreeRTOS进行系统配置

    FreeRTOS内核是高度可定制的,使用配置文件FreeRTOSConfig.h进行定制.每个FreeRTOS应用都必须包含这个头文件,用户根据实际应用来裁剪定制FreeRTOS内核.这个配置文件是针 ...

随机推荐

  1. cocob优化算法

    cocob算法是一个启发式的算法,针对SGD不需要设置learning rate. https://github.com/bremen79/cocob

  2. 【转载】惠新宸:PHP在百度的应用现状及展望

    http://blog.sina.com.cn/s/blog_645f8e970100qvd8.html 惠新宸,百度PHP高级顾问,年二十有八,好追根究底,有不良嗜好, 幸性本善.乙酉年识互联网,丁 ...

  3. windows 7 64bit安装apche php

    http://windows.php.net/download#php-5.6-ts-VC11-x64http://www.apachehaus.com/cgi-bin/download.plx 下载 ...

  4. (C++)函数参数传递中的一级指针和二级指针

    主要内容: 1.一级指针和二级指针 2.函数指针传递的例子 3.什么时候需要传递二级指针? 4.二级指针在链表中的使用 1.一级指针和二级指针 一级指针:即我们一般说的指针,就是内存地址: 二级指针: ...

  5. Log4j配置文件例子

    Log4j配置文件例子: # Define somedefault values that can be overridden by system properties hbase.root.logg ...

  6. es5 - array - shift

    /** * 描述:该shift()方法从数组中删除第一个元素并返回已删除的元素.此方法更改数组的长度. * 语法:arr.shift() * 返回:该shift方法删除零点索引处的元素并将连续索引处的 ...

  7. Unity开发 手机平台播放影片

    http://www.cnblogs.com/zhaoqingqing/p/3401747.html 截止到目前的Unity4.2版本,要在手机平台上播放影片,有两种方法: 使用Unity自带的Mov ...

  8. eclipse maven Cannot change version of project facet Dynamic web module to 3.0

      eclipse maven Cannot change version of project facet Dynamic web module to 3.0 (eclipse 修改maven项目的 ...

  9. servlet request

    request.getRequestURI(); request.getRequestURL(); getQueryString();//返回查询信息 getRemoteAddr();//得到来访者地 ...

  10. Flume入门:安装、部署

    一.什么是Flume? flume 作为 cloudera 开发的实时日志收集系统,受到了业界的认可与广泛应用.Flume 初始的发行版本目前被统称为 Flume OG(original genera ...