zoukankan      html  css  js  c++  java
  • 第16章 STM32中断应用概览

    本章参考资料《STM32F76xxx参考手册》第十一章-中断和事件、《Cortex®-M7内核编程手册》-4.2章节:NVIC4.4章节:SCB4.3.5AIRCR

    STM32中断非常强大,每个外设都可以产生中断,所以中断的讲解放在哪一个外设里面去讲都不合适,这里单独抽出一章来做一个总结性的介绍,这样在其他章节涉及到中断部分的知识我们就不用费很大的篇幅去讲解,只要示意性带过即可。

    本章如无特别说明,异常就是中断,中断就是异常,请不要刻意钻牛角尖较劲。

    16.1  异常类型

    F767在内核水平上搭载了一个异常响应系统, 支持为数众多的系统异常和外部中断。其中系统异常有10个,外部中断有110个。除了个别异常的优先级被定死外,其它异常的优先级都是可编程的。有关具体的系统异常和外部中断可在标准库文件stm32f767xx.h这个头文件查询到,在IRQn_Type这个结构体里面包含了F7系列全部的异常声明。

    表格 12  F767系统异常清单

    编号

    优先级

    优先级类型

    名称

    说明

    地址

     

    -

    -

    -

    保留(实际存的是MSP地址)

    0X0000 0000

     

    -3

    固定

    Reset

     复位

    0X0000 0004

     

    -2

    固定

    NMI

    不可屏蔽中断。 RCC 时钟安全系统
    (CSS) 连接到 NMI 向量

    0X0000 0008

     

    -1

    固定

    HardFault

    所有类型的错误

    0X0000 000C

     

    0

    可编程

    MemManage

    存储器管理

    0X0000 0010

     

    1

    可编程

    BusFault

    预取指失败,存储器访问失败

    0X0000 0014

     

    2

    可编程

    UsageFault

    未定义的指令或非法状态

    0X0000 0018

     

    -

    -

    -

    保留

    0X0000 001C-

    0X0000 002B

     

    3

    可编程

    SVCall

    通过 SWI 指令调用的系统服务

    0X0000 002C

     

    4

    可编程

    Debug Monitor

    调试监控器

    0X0000 0030

     

    -

    -

    -

    保留

    0X0000 0034

     

    5

    可编程

    PendSV

    可挂起的系统服务

    0X0000 0038

     

    6

    可编程

    SysTick

    系统嘀嗒定时器

    0X0000 003C

    表格 13 F767外部中断清单

    编号

    优先级

    优先级类型

    名称

    说明

    地址

    0

    7

    可编程

    -

    窗口看门狗中断

    0X0000 0040

    1

    8

    可编程

    PVD

    连接EXTI 线的可编程电压检测中断

    0X0000 0044

    2

    9

    可编程

    TAMP_STAMP

    连接EXTI 线的入侵和时间戳中断

    0X0000 0048

    中间部分省略,详情请参考STM32F76xxx参考手册》第十章-中断和事件-向量表部分

    103

    110

    可编程

    SDMMC2

    SDMMC2全局中断

    0X0000 0190

    104

    111

    可编程

    CAN3_TX

    CAN3 TX中断

    0X0000 0194

    105

    112

    可编程

    CAN3_RX0

    CAN3  RX0中断

    0X0000 0198

    106

    113

    可编程

    CAN3_RX1

    CAN3  RX1中断

    0X0000 019C

    107

    114

    可编程

    CAN3_SCE

    CAN3  SCE中断

    0X0000 01A0

    103

    110

    可编程

    SDMMC2

    SDMMC2全局中断

    0X0000 0190

    104

    111

    可编程

    CAN3_TX

    CAN3 TX中断

    0X0000 0194

    16.2  NVIC简介

    在讲如何配置中断优先级之前,我们需要先了解下NVICNVIC是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对Cortex-M7内核里面的NVIC进行裁剪,把不需要的部分去掉,所以说STM32NVICCortex-M7NVIC的一个子集。

    16.2.1  NVIC寄存器简介

    在固件库中,NVIC的结构体定义可谓是颇有远虑,给每个寄存器都预览了很多位,恐怕为的是日后扩展功能。不过STM32F767可用不了这么多,只是用了部分而已,具体使用了多少可参考《Cortex®-M7内核编程手册》-4.2:NVIC寄存器映射。

    代码 12 NVIC结构体定义,来自固件库头文件:core_cm7.h

    1 typedef struct {
     2     __IO uint32_t ISER[8U];       // 中断使能寄存器
     3     uint32_t RESERVED0[24U];
     4     __IO uint32_t ICER[8U];       // 中断清除寄存器
     5     uint32_t RSERVED1[24U];
     6     __IO uint32_t ISPR[8U];       // 中断使能悬起寄存器
     7     uint32_t RESERVED2[24U];
     8     __IO uint32_t ICPR[8U];       // 中断清除悬起寄存器
     9     uint32_t RESERVED3[24U];
    10     __IO uint32_t IABR[8U];       // 中断有效位寄存器
    11     uint32_t RESERVED4[56U];
    12     __IO uint8_t  IP[240U];       // 中断优先级寄存器(8Bit wide)
    13     uint32_t RESERVED5[644U];
    14     __O  uint32_t STIR;          // 软件触发中断寄存器
    15 }  NVIC_Type; 

    在配置中断的时候我们一般只用ISERICERIP这三个寄存器,ISER用来使能中断,ICER用来失能中断,IP用来设置中断优先级。

    16.2.2  NVIC 中断配置固件库

    固件库文件core_cm7.h的最后,还提供了NVIC的一些函数,这些函数遵循CMSIS规则,只要是Cortex-M7 的处理器都可以使用,具体如下:

    表格 14 符合CMSIS标准的NVIC库函数

    NVIC库函数

    描述

    void NVIC_EnableIRQ(IRQn_Type IRQn)

    使能中断

    void NVIC_DisableIRQ(IRQn_Type IRQn)

    失能中断

    void NVIC_SetPendingIRQ(IRQn_Type IRQn)

    设置中断悬起位

    void NVIC_ClearPendingIRQ(IRQn_Type IRQn)

    清除中断悬起位

    uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)

    获取悬起中断编号

    void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

    设置中断优先级

    uint32_t NVIC_GetPriority(IRQn_Type IRQn)

    获取中断优先级

    void NVIC_SystemReset(void)

    系统复位

    这些库函数我们在编程的时候用的都比较少,甚至基本都不用。在配置中断的时候我们还有更简洁的方法,请看中断编程小节。

    16.3  优先级的定义

    16.3.1  优先级定义

    NVIC 有一个专门的寄存器:中断优先级寄存器NVIC_IPRx(在F767中,x=0...109)用来配置外部中断的优先级,IPR宽度为8bit,原则上每个外部中断可配置的优先级为0~255,数值越小,优先级越高。但是绝大多数CM7芯片都会精简设计,以致实际上支持的优先级数减少,在F767中,只使用了高4bit,如下所示:

    表格 15 F767 使用4bit表达优先级

    bit7

    bit6

    bit5

    bit4

    bit3

    bit2

    bit1

    bit0

    用于表达优先级

    未使用,读回为0

    用于表达优先级的这4bit,又被分组成抢占优先级和子优先级。如果有多个中断同时响应,抢占优先级高的就会 抢占 抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。

    16.3.2  优先级分组

    优先级的分组由内核外设SCB的应用程序中断及复位控制寄存器AIRCRPRIGROUP[10:8]位决定,F767分为了5组,具体如下:主优先级=抢占优先级

    PRIGROUP[2:0]

    中断优先级值PRI_N[7:4]

    级数

    二进制点

    主优先级位

    子优先级位

    主优先级

    子优先级

    0b 011

    0b xxxx

    [7:4]

    None

    16

    None

    0b 100

    0b xxx.y

    [7:5]

    [4]

    8

    2

    0b 101

    0b xx.yy

    [7:6]

    [5:4]

    4

    4

    0b 110

    0b x.yyy

    [7]

    [6:4]

    2

    9

    0b 111

    0b .yyyy

    None

    [7:4]

    None

    16

    设置优先级分组可调用库函数HAL_NVIC_SetPriorityGrouping 实现,有关NVIC中断相关的库函数都在库文件stm32f7xx_hal_cortex.cstm32f7xx_hal_cortex.h

    代码 13 中断优先级分组库函数

    1 /**
     2   * 配置中断优先级分组:抢占优先级和子优先级
     3   * 形参如下:
     4   * @arg NVIC_PriorityGroup_0: 0bit for抢占优先级
     5   *                            4 bits for 子优先级
     6   * @arg NVIC_PriorityGroup_1: 1 bit for抢占优先级
     7   *                            3 bits for 子优先级
     8   * @arg NVIC_PriorityGroup_2: 2 bit for抢占优先级
     9   *                            2 bits for 子优先级
    10   * @arg NVIC_PriorityGroup_3: 3 bit for抢占优先级
    11   *                            1 bits for 子优先级
    12   * @arg NVIC_PriorityGroup_4: 4 bit for抢占优先级
    13   *                            0 bits for 子优先级
    14   * @注意 如果优先级分组为0,则抢占优先级就不存在,优先级就全部由子优先级控制
    15   */
    16 void NVIC_PriorityGroupConfig(uint32_t PriorityGroup)
    17 {
    18     // 检查参数
    18     assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
    18     // 设置优先级分组
    19     NVIC_SetPriorityGrouping(PriorityGroup);
    20 }

    表格 16 优先级分组真值表 

    优先级分组

    主优先级

    子优先级

    描述

    NVIC_PriorityGroup_0

    0

    0-15

    -0bit,子-4bit

    NVIC_PriorityGroup_1

    0-1

    0-7

    -1bit,子-3bit

    NVIC_PriorityGroup_2

    0-3

    0-3

    -2bit,子-2bit

    NVIC_PriorityGroup_3

    0-7

    0-1

    -3bit,子-1bit

    NVIC_PriorityGroup_4

    0-15

    0

    -4bit,子-0bit

    16.4  中断编程

    在配置每个中断的时候一般有3个编程要点:

    1、使用HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)函数配置中断优先级分组。一般默认是NVIC_PRIORITYGROUP_4分组4

    2、使用HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)函数配置具体外设中断通道的抢占优先级和子优先级。

    3、使用HAL_NVIC_EnableIRQ函数使能中断请求。

    代码 14 IRQn_Type中断源结构体

    1 typedef enum IRQn {
     2     //Cortex-M7 处理器异常编号
     3     NonMaskableInt_IRQn      = -14,
     4     MemoryManagement_IRQn    = -12,
     5     BusFault_IRQn            = -11,
     6     UsageFault_IRQn          = -10,
     7     SVCall_IRQn              = -5,
     8     DebugMonitor_IRQn        = -4,
     9     PendSV_IRQn              = -2,
    10     SysTick_IRQn             = -1,
    11     //STM32 外部中断编号
    12     WWDG_IRQn                = 0,
    13     PVD_IRQn                 = 1,
    14     TAMP_STAMP_IRQn          = 2,
    15 
    16     // 限于篇幅,中间部分代码省略,具体的可查看库文件stm32f767xx.h
    17 
    18     SDMMC2_IRQn              = 103,
    19     CAN3_TX_IRQn             = 104,
    20     CAN3_RX0_IRQn            = 105,
    21     CAN3_RX1_IRQn            = 106,
    22     CAN3_SCE_IRQn            = 107,
    23     JPEG_IRQn                = 108,
    24     MDIOS_IRQn               = 109
    25 } IRQn_Type; 

    1)PreemptPriority:抢占优先级,具体的值要根据优先级分组来确定,具体参考表格 16 优先级分组真值表 

    2)SubPriority:子优先级,具体的值要根据优先级分组来确定,具体参考表格 16 优先级分组真值表 

    4、编写中断服务函数

    在启动文件startup_STM32F767xx.s中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,中断服务函数我们统一写在stm32f7xx_it.c这个库文件中。

    关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限循环,实现不了中断。

  • 相关阅读:
    “家亡血史,原应叹息”
    SQLite初体验
    两张表数据同步用触发器
    openstack 后期维护(四)--- 删除僵尸卷
    Python3 装逼神器---词云(wordcloud)
    (三)FastDFS 高可用集群架构学习---Client 接口开发
    (四)FastDFS 高可用集群架构学习---后期运维--基础知识及常用命令
    (二)FastDFS 高可用集群架构学习---搭建
    (一)FastDFS 高可用集群架构学习---简介
    Python3使用Print输出彩色字体
  • 原文地址:https://www.cnblogs.com/firege/p/9287053.html
Copyright © 2011-2022 走看看