一、STM32 (Cortex-M3) 中的优先级概念

  STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级和响应优先级,也把响应优先级称作“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。

  1. 何为占先式优先级(pre-emption priority)

  高占先式优先级的中断事件会打断当前的主程序/中断程序运行—抢断式优先响应,俗称中断嵌套。

  2. 何为副优先级(subpriority)

  在占先式优先级相同的情况下,高副优先级的中断优先被响应;

  在占先式优先级相同的情况下,如果有低副优先级中断正在执行, 高副优先级的中断要等待已被响应的低副优先级中断执行结束后才能得到响应—非抢断式响应(不能嵌套)。

  3. 判断中断是否会被响应的依据

  首先是占先式优先级,其次是副优先级;

  占先式优先级决定是否会有中断嵌套;

  Reset、NMI、Hard Fault 优先级为负(高于普通中断优先级)且不可调整。

  4. 优先级冲突的处理

  具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断的嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。

  当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。

  5. Cortex-M3中对中断优先级的定义

  既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位可以有8种分配方式,如下:

  所有8位用于指定响应优先级

  最高1位用于指定抢占式优先级,最低7位用于指定响应优先级

  最高2位用于指定抢占式优先级,最低6位用于指定响应优先级

  最高3位用于指定抢占式优先级,最低5位用于指定响应优先级

  最高4位用于指定抢占式优先级,最低4位用于指定响应优先级

  最高5位用于指定抢占式优先级,最低3位用于指定响应优先级

  最高6位用于指定抢占式优先级,最低2位用于指定响应优先级

  最高7位用于指定抢占式优先级,最低1位用于指定响应优先级

  这就是优先级分组的概念。

  6. STM32中对中断优先级的定义

  Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:

  第0组:所有4位用于指定响应优先级

  第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级

  第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级

  第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级

  第4组:所有4位用于指定抢占式优先级

  

  AIRC(Application Interrupt and Reset Register)寄存器中有用于指定优先级的 4 bits。这4个bits用于分配preemption优先级和sub优先级,在STM32的固件库中定义如下:

 

 /* Preemption Priority Group */

  #define NVIC_PriorityGroup_0 ((u32)0x700) /* 0 bits for pre-emption priority

  4 bits for subpriority */

  #define NVIC_PriorityGroup_1 ((u32)0x600) /* 1 bits for pre-emption priority

  3 bits for subpriority */

  #define NVIC_PriorityGroup_2 ((u32)0x500) /* 2 bits for pre-emption priority

  2 bits for subpriority */

  #define NVIC_PriorityGroup_3 ((u32)0x400) /* 3 bits for pre-emption priority

  1 bits for subpriority */

  #define NVIC_PriorityGroup_4 ((u32)0x300) /* 4 bits for pre-emption priority

  0 bits for subpriority */

  可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式,这个函数的参数有下列5种:

  NVIC_PriorityGroup_0 => 选择第0组

  NVIC_PriorityGroup_1 => 选择第1组

  NVIC_PriorityGroup_2 => 选择第2组

  NVIC_PriorityGroup_3 => 选择第3组

  NVIC_PriorityGroup_4 => 选择第4组

  接下来就是指定中断源的优先级,下面以一个简单的例子说明如何指定中断源的抢占式优先级和响应优先级:

  

// 选择使用优先级分组第1组

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  // 使能EXTI0中断

  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别1

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别0

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  // 使能EXTI9_5中断

  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别0

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定响应优先级别1

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  要注意的几点是:

  1. 如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;

  2. 抢占式优先级别相同的中断源之间没有嵌套关系;

  3. 如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。

  二、开关总中断

  在STM32/Cortex-M3中是通过改变CPU的当前优先级来允许或禁止中断。

  PRIMASK位:只允许NMI和hard fault异常,其他中断/异常都被屏蔽(当前CPU优先级=0)。

  FAULTMASK位:只允许NMI,其他所有中断/异常都被屏蔽(当前CPU优先级=-1)。

  在STM32固件库中(stm32f10x_nvic.c和stm32f10x_nvic.h) 定义了四个函数操作PRIMASK位和FAULTMASK位,改变CPU的当前优先级,从而达到控制所有中断的目的。

  下面两个函数等效于关闭总中断:

 

 void NVIC_SETPRIMASK(void);

  void NVIC_SETFAULTMASK(void);

  下面两个函数等效于开放总中断:

  void NVIC_RESETPRIMASK(void);

  void NVIC_RESETFAULTMASK(void);

  上面两组函数要成对使用,但不能交叉使用。

  例如:

  第一种方法:

 

 NVIC_SETPRIMASK(); //关闭总中断

  NVIC_RESETPRIMASK();//开放总中断

  第二种方法:

  NVIC_SETFAULTMASK(); //关闭总中断

  NVIC_RESETFAULTMASK();//开放总中断

  常常使用:

  NVIC_SETPRIMASK(); // Disable Interrupts

  NVIC_RESETPRIMASK(); // Enable Interrupts

  补充:

  可以用:

 

 #define CLI() __set_PRIMASK(1)

  #define SEI() __set_PRIMASK(0)

  来实现开关总中断的功能。

最后还是给大家搞一些stm32的资料便于参考学习

(STM32中断系统)
http://www.makeru.com.cn/live/1392_1124.html?s=45051

基于STM32-WiFi智能小车机器人开发实战
http://www.makeru.com.cn/course/details/3008?s=45051

ARM之中断GIC分析
http://www.makeru.com.cn/live/1758_328.html?s=45051

嵌入式操作系统uC/OS
http://www.makeru.com.cn/live/5413_2094.html?s=45051

关于STM32 (Cortex-M3) 中NVIC的分析的更多相关文章

  1. STM32学习之路入门篇之指令集及cortex——m3的存储系统

    STM32学习之路入门篇之指令集及cortex——m3的存储系统 一.汇编语言基础 一).汇编语言:基本语法 1.汇编指令最典型的书写模式: 标号 操作码        操作数1, 操作数2,... ...

  2. ARM 架构、ARM7、ARM9、STM32、Cortex M3 M4 、51、AVR 之间有什么区别和联系?(转载自知乎)

    ARM架构:  由英国ARM公司设计的一系列32位的RISC微处理器架构总称,现有ARMv1~ARMv8种类. ARM7:       一类采用ARMv3或ARMv4架构的,使用冯诺依曼结构的内核. ...

  3. stm32和cortex M3学习内核简单总结

    1.stm32综述 2.寄存器组 3.操作模式和特权级别 4.存储器映射 5.中断和异常 6.其他 Stm32综述 这可以说是我第一款认真学习的单片机了,学完这个就要开启我通往arm9的大门了,接下来 ...

  4. ARM Cortex M3系列GPIO口介绍(工作方式探讨)

    一.Cortex M3的GPIO口特性    在介绍GPIO口功能前,有必要先说明一下M3的结构框图,这样能够更好理解总线结构和GPIO所处的位置. Cortex M3结构框图     从图中可以看出 ...

  5. ARM Cortex M3(V7-M架构)硬件启动程序 一

    Cortex-m3启动代码分析笔记 启动代码文件名是STM32F10X.S,它的作用先总结下,然后再分析. 启动代码作用一般是: 1)堆和栈的初始化: 2)中断向量表定义: 3)地址重映射及中断向量表 ...

  6. 【freertos】002-posix模拟器设计与cortex m3异常处理

    目录 前言 posix 标准接口层设计 模拟器的系统心跳 模拟器的task底层实质 模拟器的任务切换原理 cortex M3/M4异常处理 双堆栈指针 双操作模式 栈帧 EXC_RETURN 前言 如 ...

  7. Android中AppWidget的分析与应用:AppWidgetProvider .

    from: http://blog.csdn.net/thl789/article/details/7887968 本文从开发AppWidgetProvider角度出发,看一个AppWidgetPrv ...

  8. JAVA WEB 中的编码分析

    JAVA WEB 中的编码分析 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src {background-co ...

  9. Android 中图片压缩分析(上)

    作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情 ...

随机推荐

  1. io流-文件流\节点流

    FileOutputStream类(jdk1.0) 描述 java.io.FileOutputStream 类是文件字节输出流,用于将数据写入到文件中. 构造方法 //构造方法 FileOutputS ...

  2. pymysql基础教程

    pymysql基础教程 1.下载pymysql 在命令框输入指令即可 pip install pymysql 2.连接pymysql 连接数据库: import pymysql conn = pymy ...

  3. python函数模块

    python函数模块 学习完本篇,你将会深入掌握 函数相关知识 1.函数定义 2.函数如何调用 3.递归函数以及匿名函数使用 模块相关知识 1.模块如何导入调用 2.函数调用顺序 函数定义 函数代码块 ...

  4. Markdown公式用法大全

    目录 基本语法 两种代码引用方式 插入链接并描述 插入图片 有序列表 无序列表 分割线 表格 如何插入公式 如何输入上下标 如何输入括号和分隔符 如何输入分数 如何输入开方 如何输入省略号 如何输入矢 ...

  5. dede织梦会员模板调用template下模板head.htm方法及解析变量

    1.找到dedecms会员中心的的目录 member ,然后在目录下用编辑器打开config.php 加入对dede模板解释函数如下:   //php脚本开始 //引入arc.partview.cla ...

  6. TP5更新数据成功,但判断结果不符

    thinkphp的CURD中,使用save方法时会出现一个奇怪的问题,即如果数据没有更新(与原数据相同),返回值判断为false.其实很久之前就发现了这个问题,一度以为是官方代码的问题,但是一直拖延到 ...

  7. ecshop二次开发秒杀、限时折扣、清仓等功能

    限时抢购,秒杀商品的二次开发 1,先在后台admin/templates 中找goods_info.htm文件到促销部分,改为一个下拉列表的分别是促销,限时,秒杀,值分别是1,2,3这样,代码如下: ...

  8. LeetCode2-链表两数和

    目录 LeetCode2-链表两数和 题目描述 示例提示 经验教训 参考正解 题目描述 示例提示 经验教训 链表题的判空条件不是万能的,有时候示例会极其复杂,根本难以通过判空来区分不同情况. /** ...

  9. IDL读取fits文件

    使用mrdfits函数 这是天文学标准库中的函数,下载地址:https://idlastro.gsfc.nasa.gov/homepage.html,下载后,将pro文件夹导入到IDL工程中. str ...

  10. bzoj4025-二分图【线段树分治,并查集】

    正题 题目链接:https://darkbzoj.tk/problem/4025 题目大意 \(n\)个点\(m\)条边,每条边会在一个\(T\)以内的时间段内出现,对于任意一个\(T\)以内的时刻求 ...