00. 目录

文章目录

  • 00. 目录
  • 01. 概述
  • 02. 中断管理
  • 03. 优先级分组
  • 04. 优先级设置
  • 05. 特殊寄存器
  • 06. FreeRTOS中断配置宏
  • 07. FreeRTOS开关中断
  • 08. 附录
  • 09. 参考

01. 概述

中断是微控制器一个很常见的特性,中断由硬件产生,当中断产生以后CPU就会中断当前的流程转而去处理中断服务,Cortex-M内核的MCU提供了一个用于中断管理的嵌套向量中断控制器(NVIC)。

Cortex-M3和M4的NVIC最多支持240个IRQ中断请求,1个不可屏蔽中断NMI、1个Systick滴答定时器中断和多个异常。

02. 中断管理

Cortex-M处理器有多个用于管理中断和异常的可编程寄存器,这些寄存器大多数都在NVIC和系统控制块SCB中,CMSIS将这些寄存器定义为结构体。以STM32F407为例,打开core_cm4.h,有以下两个结构体。

NVIC_Type类型

/** \brief  Structure type to access the Nested Vectored Interrupt Controller (NVIC).*/
typedef struct
{__IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */uint32_t RESERVED0[24];__IO uint32_t ICER[8];                 /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register         */uint32_t RSERVED1[24];__IO uint32_t ISPR[8];                 /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register          */uint32_t RESERVED2[24];__IO uint32_t ICPR[8];                 /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register        */uint32_t RESERVED3[24];__IO uint32_t IABR[8];                 /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register           */uint32_t RESERVED4[56];__IO uint8_t  IP[240];                 /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */uint32_t RESERVED5[644];__O  uint32_t STIR;                    /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
}  NVIC_Type;

SCB_Type类型

/** \brief  Structure type to access the System Control Block (SCB).*/
typedef struct
{__I  uint32_t CPUID;                   /*!< Offset: 0x000 (R/ )  CPUID Base Register                                   */__IO uint32_t ICSR;                    /*!< Offset: 0x004 (R/W)  Interrupt Control and State Register                  */__IO uint32_t VTOR;                    /*!< Offset: 0x008 (R/W)  Vector Table Offset Register                          */__IO uint32_t AIRCR;                   /*!< Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register      */__IO uint32_t SCR;                     /*!< Offset: 0x010 (R/W)  System Control Register                               */__IO uint32_t CCR;                     /*!< Offset: 0x014 (R/W)  Configuration Control Register                        */__IO uint8_t  SHP[12];                 /*!< Offset: 0x018 (R/W)  System Handlers Priority Registers (4-7, 8-11, 12-15) */__IO uint32_t SHCSR;                   /*!< Offset: 0x024 (R/W)  System Handler Control and State Register             */__IO uint32_t CFSR;                    /*!< Offset: 0x028 (R/W)  Configurable Fault Status Register                    */__IO uint32_t HFSR;                    /*!< Offset: 0x02C (R/W)  HardFault Status Register                             */__IO uint32_t DFSR;                    /*!< Offset: 0x030 (R/W)  Debug Fault Status Register                           */__IO uint32_t MMFAR;                   /*!< Offset: 0x034 (R/W)  MemManage Fault Address Register                      */__IO uint32_t BFAR;                    /*!< Offset: 0x038 (R/W)  BusFault Address Register                             */__IO uint32_t AFSR;                    /*!< Offset: 0x03C (R/W)  Auxiliary Fault Status Register                       */__I  uint32_t PFR[2];                  /*!< Offset: 0x040 (R/ )  Processor Feature Register                            */__I  uint32_t DFR;                     /*!< Offset: 0x048 (R/ )  Debug Feature Register                                */__I  uint32_t ADR;                     /*!< Offset: 0x04C (R/ )  Auxiliary Feature Register                            */__I  uint32_t MMFR[4];                 /*!< Offset: 0x050 (R/ )  Memory Model Feature Register                         */__I  uint32_t ISAR[5];                 /*!< Offset: 0x060 (R/ )  Instruction Set Attributes Register                   */uint32_t RESERVED0[5];__IO uint32_t CPACR;                   /*!< Offset: 0x088 (R/W)  Coprocessor Access Control Register                   */
} SCB_Type;

NVIC和SCB都位于系统控制空间SCS内,SCS的地址从0xe000e000开始,scb和NVIC的地址也在core_cm4.h中有定义

/* Memory mapping of Cortex-M4 Hardware */
#define SCS_BASE            (0xE000E000UL)    /*!< System Control Space Base Address  */
#define NVIC_BASE           (SCS_BASE +  0x0100UL)  /*!< NVIC Base Address                  */
#define SCB_BASE            (SCS_BASE +  0x0D00UL)  /*!< System Control Block Base Address  */#define SCnSCB              ((SCnSCB_Type*)SCS_BASE)   /*!< System control Register not in SCB */
#define SCB                 ((SCB_Type*)SCB_BASE)   /*!< SCB configuration struct           */
#define NVIC                ((NVIC_Type*)NVIC_BASE)   /*!< NVIC configuration struct          */

03. 优先级分组

当多个中断来临的时候处理器应该响应哪一个中断是由中断的优先级决定的,高优先级的中断(优先级编号小)肯定是首先得到响应,而且高优先级的中断可以抢占低优先级的中断,这个就是中断嵌套。Cortex-M处理器的有些中断是具有固定的优先级的,比如复位、NMI、HardFault,这些中断的优先级都是负数,优先级也是最高的。

Cortex-M处理器有是三个固定优先级和256个可编程的优先级,最多有128个抢占等级,但是实际的优先级数量是有芯片厂商来决定的。但是绝大多数的芯片都会精简设计的,导致实际上支持的优先级会更少,如8级、16级、32级等等。比如stm32就只有16级优先级。在设计芯片的时候会裁掉表达优先级的几个低端有效位,以减少优先级数,所以不管用多少位来表示优先级,都是MSB对齐的。下图都是用三位来表示优先级。

优先级配置寄存器是位宽的,为什么只有128个抢占等级?8位不应该是256个抢占等级吗?为了是抢占机能变得更可控,cortex-M处理器还把256个优先级按位分为高低两段:抢占优先级(分组优先级)和亚优先级(子优先级),NVIC中有一个寄存器是“应用程序中断及复位控制寄存器(AIRCR)”,AIRCR寄存器里面有个位段名为“优先级组”。

STM32使用了4位,因此最多有5组优先级分组设置,在msic.h中有定义:

/** @defgroup MISC_Preemption_Priority_Group * @{*/#define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority4 bits for subpriority */
#define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority3 bits for subpriority */
#define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority2 bits for subpriority */
#define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority1 bits for subpriority */
#define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority0 bits for subpriority */#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \((GROUP) == NVIC_PriorityGroup_1) || \((GROUP) == NVIC_PriorityGroup_2) || \((GROUP) == NVIC_PriorityGroup_3) || \((GROUP) == NVIC_PriorityGroup_4))

04. 优先级设置

每个外部中断都有一个对应的优先级寄存器,每个寄存器占8位,因此最大宽度是8位,但是最小为3位。4个相邻的优先级寄存器拼成1个32位寄存器。如前所述,根据优先级组的设置,优先级又可以分为高低两个位段,分别是抢占优先级和亚优先级。STM32我们已经设置位组4,所以就只有抢占优先级了。优先级就餐器都可以按字节访问,当然也可以按半字、字来访问,有意义的优先级寄存器数目由芯片厂商来实现。

05. 特殊寄存器

5.1 PRIMASK和FAULTMASK寄存器

5.2 BASEPRI寄存器

06. FreeRTOS中断配置宏

6.1 configPRIO_BITS

此宏用来设置MCU使用几位优先级,STM32使用的是4位,因此该宏为4。

#define configPRIO_BITS              4        /* 15 priority levels */

6.2 configLIBRARY_LOWEST_INTERRUPT_PRIORITY

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         0xf

该宏用来设置最低优先级,STM32优先级使用了4位,而且STM32配置的使用组4,也就是4位都是抢占优先级。因此优先级数数就是16个,最低优先级就是15。所以该值为15。不同的MCU,此值不同,具体是多少要看所使用的MCU的架构。

6.3 configKERNEL_INTERRUPT_PRIORITY

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

该宏用来设置内核中断优先级。

6.4 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5

此宏用来设置FreeRTOS系统可管理的最大优先级,就是我们之前讲解的BASEPRI寄存器说的那个阈值优先级,这个可以自由设置,我们这里设置为5.也就是高于5的优先级(优先级小于5)不归FreeRTOS管理。

6.5 configMAX_SYSCALL_INTERRUPT_PRIORITY

See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

此宏设置好以后,低于此优先级的中断可以安全的调用FreeRTOS的API函数,高于此优先级的中断FreeRTOS是不能禁止的。中断服务函数也不能调用FreeRTOS的API函数。

07. FreeRTOS开关中断

FreeRTOS开关中断函数为portDISABLE_INTERRUPTS()和portENABLE_INTERRUPTS(),这两个函数在portmacro.h文件中有定义。

    #define portDISABLE_INTERRUPTS()                  vPortRaiseBASEPRI()#define portENABLE_INTERRUPTS()                   vPortSetBASEPRI( 0 )

可以看出开关中断实际上是通过函数vPortSetBASEPRI( 0 )和vPortRaiseBASEPRI()来实现的,这两个函数如下:

    static portFORCE_INLINE void vPortRaiseBASEPRI( void ){uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;__asm{/* Set BASEPRI to the max syscall priority to effect a critical* section. */
/* *INDENT-OFF* */msr basepri, ulNewBASEPRIdsbisb
/* *INDENT-ON* */}}static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI ){__asm{/* Barrier instructions are not used as this function is only used to* lower the BASEPRI value. */
/* *INDENT-OFF* */msr basepri, ulBASEPRI
/* *INDENT-ON* */}}

08. 附录

8.1 【STM32】STM32系列教程汇总

网址:【STM32】STM32系列教程汇总

09. 参考

《FreeRTOS Reference Manual》

《Using the FreeRTOS Real Time Kernel -A Practical Guide》

《The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors,3rd Edition》

【STM32】FreeRTOS中断配置相关推荐

  1. FreeRTOS中断配置与临界段

    Cortex-M中断 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序(中断服务程序),处理完毕后又返回原被暂停的程序继续运行.Cortex- ...

  2. stm32定时器中断配置及使用

    stm32定时器中断配置及使用 定时器中断就是:可以周期性的执行某些功能,而不受main函数的影响. 我们以通用定时器time3为例说明 1.首先配置时钟源为内部时钟,分频和充装载值根据自己需要填入, ...

  3. (二)stm32之中断配置

    一.stm32的中断和异常 Cortex拥有强大的异常响应系统,它能够打断当前代码执行流程事件分为异常和中断,它们用一个表管理起来,编号为0~15为内核异常,16以上的为外部中断,这个表就是中断向量表 ...

  4. stm32之中断配置

    一.stm32的中断和异常 Cortex拥有强大的异常响应系统,它能够打断当前代码执行流程事件分为异常和中断,它们用一个表管理起来,编号为0~15为内核异常,16以上的为外部中断,这个表就是中断向量表 ...

  5. STM32定时器中断配置

    1.使能时钟 定时器时钟 2.配置定时器结构体.使能 3.开启定时器中断,配置中断结构体 配置例子 #include "tim.h" #include "stm32f10 ...

  6. 【STM32】FreeRTOS 中断配置和临界段

    文章目录 main.c 中断是微控制器一个很常见的特性,中断由硬件产生,当中断产生以后 CPU 就会中断当前 的流程转而去处理中断服务,Cortex-M 内核的 MCU 提供了一个用于中断管理的嵌套向 ...

  7. FreeRTOS源码分析与应用开发01:中断配置与临界段

    目录 1. 异常与中断的基本概念 1.1 异常分类 1.2 中断概述 1.2.1 中断处理宜短暂 1.2.2 临界段影响中断实时性 1.3 中断硬件基础 1.3.1 外设 1.3.2 中断控制器 1. ...

  8. STM32单片机外部中断配置讲解

    2019独角兽企业重金招聘Python工程师标准>>> 单片机外部中断简介 所谓外部中断,就是通过外部信号所引起的中断,如单片机引脚上的电平变化(高电平.低电平).边沿变化(上升沿. ...

  9. STM32 外部中断详解(原理+配置代码)

    本文介绍了STM32基于标准外设库的外部中断配置,以及基于参考手册如何更加寄存器配置外部中断 文章目录 1 前言 2 STM32的外部中断 3 中断服务函数的映射关系 4 外部中断的配置 5 寄存器的 ...

最新文章

  1. Blender纹理基础学习视频教程 CGCookie – Fundamentals of Texturing in Blender
  2. java中我爱你_Java线程学习(转)
  3. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown database 'test'
  4. Citrix桌面及应用虚拟化系列之二:XenServer补丁
  5. spring boot 集合mysql_Spring boot整合mysql和druid
  6. 前端学习(1081):构造函数和原型概述
  7. Mac终端:pip command not found
  8. Nginx 实现封杀恶意访问
  9. java Byte Stream and Character Stream的不同
  10. Java - BeanUtils.copyProperties 与 PropertyUtils.copyProperties 用法及区别
  11. linux war 权限,Linux中mv重命名作用及打包war压缩文件及分配权限
  12. win7网络打印机重启后脱机的问题
  13. 概率统计Python计算:双正态总体均值差的双侧区间估计
  14. instagram 和不联网
  15. Vim 插件管理工具 pathogen
  16. python中zlib库用法详解(压缩与解压缩)
  17. CSS清除浮动的方法
  18. Spring Cloud Alibaba - 27 Gateway源码解析
  19. “阿法狗”之父:关于围棋,人类3000年来犯了一个错!
  20. NOI.5.37雇佣兵

热门文章

  1. 读《JavaScript dom编程艺术(第2版)》笔记 1-2
  2. 29. 栈的push,pop序列
  3. Rose2003的安装和破解
  4. MySQL根被拒绝_[转载]phpMyAdmin 尝试连接到 MySQL 服务器,但服务器拒绝连接。...
  5. 快搜浏览器_opera、Google、firefox三个浏览器的选择
  6. 哥伦比亚大学浙江大学计算机,大神offer | 恭喜C同学录取哥伦比亚大学-数据科学硕士!...
  7. 红旗Linux可以兼容,红旗 Linux 桌面操作系统11来了:支持国产自主CPU,全新UI风格设计,兼容面广...
  8. 用指向指针方法对N个字符串进行排序并输出
  9. Flutter 中的基本路由
  10. Codeforces Round #448 (Div. 2)