请选择 进入手机版 | 继续访问电脑版

安富莱电子论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 4879|回复: 9
收起左侧

[FreeRTOS教程] 第12章 FreeRTOS中断优先级配置(重要)

[复制链接]

685

主题

2001

帖子

3371

积分

至尊会员

春暖花开

积分
3371
QQ
发表于 2016-8-20 16:27:03 | 显示全部楼层 |阅读模式



第12章      FreeRTOS中断优先级配置(重要)


    本章节为大家讲解FreeRTOS中断优先级配置,此章节非常重要,初学者经常在这里犯迷糊。对于初学者来说,本章节务必要整明白。
12.1 NVIC基础知识
12.2 使用FreeRTOS时如何配置外设NVIC
12.3 FreeRTOS配置选项中NVIC相关配置
12.4 不受FreeRTOS管理中的的深入讨论
12.5总结


12.1 NVIC基础知识

    NVIC的全称是Nested vectoredinterrupt 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]。
12.1.JPG
图12.1 优先级分组

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

    掌握了这些基础知识基本就够用了。另外特别注意一点,配置抢占优先级和子优先级,他们合并成的4bit数字的数值越小,优先级越高,这一点千万不要搞错了,下面通过12.2小节举一个实例。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

685

主题

2001

帖子

3371

积分

至尊会员

春暖花开

积分
3371
QQ
 楼主| 发表于 2016-8-20 16:30:22 | 显示全部楼层
12.2 使用FreeRTOS时如何配置外设NVIC


    强烈推荐用户将Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407以及STM32F429的NVIC优先级分组设置为4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);这样中断优先级的管理将非常方便。这个也是官方强烈建议的。此函数在bsp_Init中第一个被调用:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
  5. *             全局变量。
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void bsp_Init(void)
  11. {   
  12.      /* 优先级分组设置为4, 优先配置好NVIC */
  13.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  14.    
  15.      bsp_InitUart();    /* 初始化串口 */
  16.      bsp_InitLed();     /* 初始LED指示灯端口 */
  17.      bsp_InitKey();     /* 初始化按键 */
  18.    
  19. }
复制代码
    (注意:一旦初始化好NVIC的优先级分组后,切不可以在应用中再次更改。)
    设置NVIC的优先级分组为4表示支持0-15级抢占优先级(注意,0-15级是16个级别,包含0级),不支持子优先级。反映在STM32标准库的配置上就是如下:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: TIM_Config
  4. *    功能说明: 配置定时器TIM2的中断
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void TIM_Config(void)
  10. {
  11.      NVIC_InitTypeDef  NVIC_InitStructure;
  12.      NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  13. /* 抢占优先级设置,优先级分组为4的情况下,抢占优先级可设置范围0-15 */
  14.      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  15. /* 子优先级设置,优先级分组为4的情况下,子优先级无效,取数值0即可 */
  16.      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;      
  17.      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  18.      NVIC_Init(&NVIC_InitStructure);
  19. }
复制代码
在这里继续强调下这一点,在NVIC分组为4的情况下,抢占优先级可配置范围是0-15,那么数值越小,抢占优先级的级别越高,即0代表最高优先级,15代表最低优先级。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

685

主题

2001

帖子

3371

积分

至尊会员

春暖花开

积分
3371
QQ
 楼主| 发表于 2016-8-20 16:34:33 | 显示全部楼层
12.3   FreeRTOS配置选项中NVIC相关配置


    FreeRTOSConfig.h配置文件中设置到NVIC中断的有如下几个选项:
  1. /* Cortex-M specific definitions. */
  2. #ifdef __NVIC_PRIO_BITS
  3.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  4.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  5. #else
  6.      #define configPRIO_BITS              4        /* 15 priority levels */
  7. #endif
  8. /* The lowest interrupt priority that can be used in a call to a "set priority"
  9. function. */
  10. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  11. /* The highest interrupt priority that can be used by any interrupt service
  12. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  13. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  14. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  15. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01
  16. /* Interrupt priorities used by the kernel port layer itself.  These are generic
  17. to all Cortex-M ports, and do not rely on any particular library functions. */
  18. #define configKERNEL_INTERRUPT_PRIORITY        ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
  19. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
  20. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
  21. #define configMAX_SYSCALL_INTERRUPT_PRIORITY   ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
复制代码
u  #define configPRIO_BITS             4
        此宏定义用于配置STM32的8位优先级设置寄存器实际使用的位数。STM32F103,STM32F407和STM32F429都是使用的4位。另外注意一点,这里使用了一个条件编译,用户可以选择将条件编译删掉,直接定义一个#defineconfigPRIO_BITS  4即可。使用条件编译的好处就是方便与系统统一。这个__NVIC_PRIO_BITS在STM32F103标准库的头文件stm32f10x.h中以及STM32F407/439的标准库的头文件stm32f4xx.h中分别有定义。如果用户在FreeRTOSConfig.h文件里面包含了这个标准库的头文件,那么就会执行条件编译选项:
           #define configPRIO_BITS                    __NVIC_PRIO_BITS

    l __NVIC_PRIO_BITS
       关于这个__NVIC_PRIO_BITS有必要跟大家深入的说明下,我们要刨根问底。在CMSIS软件包的M3内核头文件core_cm3.h和M4内核的头文件core_cm4.h文件里面已经进行了定义:
                  #ifndef __NVIC_PRIO_BITS
                      #define __NVIC_PRIO_BITS          4U
                   #endif
        也就是说,如果用户没有定义的话,这里的定义就会起作用。而STM32F103标准库的头文件stm32f10x.h和STM32F407/439的标准库的头文件stm32f4xx.h有定义了,而且相应的头文件core_cm3.h和core_cm4.h是放在了宏定义#define __NVIC_PRIO_BITS  4的后面,如此一来,头文件core_cm3.h和core_cm4.h的定义就会被屏蔽掉。STM32F103标准库的头文件stm32f10x.h和STM32F407/439的标准库的头文件stm32f4xx.h里面的定义是有效的。

u  #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY                     0x0f
        此宏定义是用来配置FreeRTOS用到的SysTick中断和PendSV中断的优先级。在NVIC分组设置为4的情况下,此宏定义的范围就是0-15,即专门配置抢占优先级。这里配置为了0x0f,即SysTickPendSV都是配置为了最低优先级,实际项目中也建议大家配置最低优先级即可。

    l SVC中断
        在FreeRTOS的移植文件ports.c中有用到SVC中断的0号系统服务,即SVC 0。此中断在FreeRTOS中仅执行一次,用于启动第一个要执行的任务。另外,由于FreeRTOS没有配置SVC的中断优先级,默认没有配置的情况下,SVC中断的优先级就是最高的0。如果用户在不清楚自己配置的PendSVSysTick中断是否跟实际情况一致时,可以进行硬件调试。比如MDK,我们可以在硬件调试的状态下,先点击全速运行,然后查看如下调试组件:
12.2.jpg


      打开后可以看到如下状态,其中SysTick和PendSV中断的优先级240就是0x0f左移4位的结果。这里为什么要左移四位呢,前面我们已经多次强调了,STM32的优先级设置仅使用高4位。而SVC的优先级就是0,可以理解为0左移4位还是0
12.3.jpg

u  #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01
        此宏定义比较重要,定义了受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。设置NVIC的优先级分组为4的情况下。配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为0x01表示用户可以在抢占式优先级为1到15的中断里面调用FreeRTOS的API函数,抢占式优先级为0的中断里面是不允许调用的。不受FreeRTOS管理的中断有什么深层的含义吗?且看12.4小节继续为大家讲解。


u  #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。


u  #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,那么被关闭的中断会被打开。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

685

主题

2001

帖子

3371

积分

至尊会员

春暖花开

积分
3371
QQ
 楼主| 发表于 2016-8-20 16:38:41 | 显示全部楼层
12.4 不受FreeRTOS管理中断的深入讨论


    讲解不受FreeRTOS管理的中断之前要说一个小知识点----中断延迟。中断延迟时间是衡量RTOS实时操作系统的一项重要指标,那什么又是中断延迟呢?从中断触发到执行中断服务程序的第一条指令这段时间就是中断延迟时间。
    FreeRTOS内核源码中有多处开关全局中断的地方,这些开关全局中断会加大中断延迟时间。比如在源码的某个地方关闭了全局中断,但是此时有外部中断触发,这个中断的服务程序就需要等到再次开启全局中断后才可以得到执行。开关中断之间的时间越长,中断延迟时间就越大,这样极其影响系统的实时性。如果这是一个紧急的中断事件,得不到及时执行的话,后果是可想而知的。
    针对这种情况,FreeRTOS就专门做了一种新的开关中断实现机制。关闭中断时仅关闭受FreeRTOS管理的中断,不受FreeRTOS管理的中断不关闭,这些不受管理的中断都是高优先级的中断,用户可以在这些中断里面加入需要实时响应的程序。FreeRTOS能够实现这种功能的奥秘就在于FreeRTOS开关中断使用的是寄存器basepri,而像uCOS这种使用的是primask,详情请看下面整理的表格:
12.4.JPG
        对寄存器basepri我们举一个例子,帮助大家理解,比我们配置寄存器basepri的数值为16,所有优先级数值大于等于16的中断都会被关闭,优先级数值小于16的中断不会被关闭。对寄存器basepri寄存器赋值0,那么被关闭的中断会被打开。这个就是FreeRTOS开关中断的实现方案。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

685

主题

2001

帖子

3371

积分

至尊会员

春暖花开

积分
3371
QQ
 楼主| 发表于 2016-8-20 16:39:07 | 显示全部楼层
12.5   总结

    本章节为大家讲解FreeRTOS中断优先级配置,内容相比前面章节要复杂些,不知道大家是否已经理解透彻了?如果没有理解透彻,务必多读几遍,直到完全弄明白。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

0

主题

1

帖子

0

积分

新手上路

积分
0
发表于 2016-11-30 00:17:10 | 显示全部楼层
回复的人几乎没有啊,谢谢楼主
回复

使用道具 举报

0

主题

2

帖子

0

积分

新手上路

积分
0
发表于 2017-7-6 17:30:00 | 显示全部楼层
首先谢谢楼主辛苦写的教程,然后有点小疑问想请教下,教程中的这一段(如下文),红色部分是不是应该写成 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01。这只是我的猜测,不知道对不对。
还有一点,如下4个宏定义是不是可以归为两组,互相代替,同时只使用一组就可以了,还请指教。
初接触FreeRTOS,好多都不懂,看到楼主写的教程很详细,解决了我很多的疑惑,再次谢谢楼主
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01

#define configKERNEL_INTERRUPT_PRIORITY
#define configMAX_SYSCALL_INTERRUPT_PRIORITY


#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,那么被关闭的中断会被打开。
回复

使用道具 举报

5667

主题

3万

帖子

4万

积分

管理员

做人第一,工作第二

Rank: 9Rank: 9Rank: 9

积分
45615
QQ
发表于 2017-7-7 01:34:45 | 显示全部楼层

回 hell0w0rd 的帖子

hell0w0rd:首先谢谢楼主辛苦写的教程,然后有点小疑问想请教下,教程中的这一段(如下文),红色部分是不是应该写成 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01。这只是我的猜测,不知道对不对。
还有一点,如下4个宏定义是不是可以归为两组,互相 .. (2017-07-06 17:30)
1. 对的,教程中写的有误。
2. 可以这么理解。
淘宝小店: https://armfly.taobao.com/
专注,努力,用心的做好每一件事情,Fighting!
回复

使用道具 举报

0

主题

2

帖子

0

积分

新手上路

积分
0
发表于 2017-7-10 11:18:16 | 显示全部楼层

回 eric2013 的帖子

eric2013:

1. 对的,教程中写的有误。
2. 可以这么理解。
谢谢楼主,解惑
回复

使用道具 举报

3

主题

15

帖子

21

积分

新手上路

积分
21
发表于 2019-3-8 06:32:18 | 显示全部楼层
这么好的贴,给你点赞
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|安富莱电子论坛 ( 鄂ICP备09023347号,公安机关备案号42010602000201 )

GMT+8, 2019-5-21 06:41 , Processed in 0.269793 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表