stm32f407
+ -

STM32F407ZG NVIC中断配置

2022-01-03 19 0

NVIC中断

前面提到TM32F407ZG的82个外部中断优先级可以分为16个等级(因为使用了4位的中断优先级配置)。配置中断优先级的4位位于其各自中断的IP寄存器的bit[7:4]位中。这4位的中断优先级按照AIRCR[10:8]寄存器的配置,将这四位分为两种中断优先级,分别为中断抢占优先级和中断响应优先级。

IP:中断优先级控制寄存器

根据AIRCR[10:8]寄存器的配置,IP寄存器的bit[7:4]位中的中断抢占优先级和中断响应优先级配置如下表所示:

AIRCR[10:8] IP bit[7:4]分配情况 分配结果
0 111 0:4 0位抢占优先级,4位响应优先级
1 110 1:3 1位抢占优先级,3位响应优先级
2 101 2:2 2位抢占优先级,2位响应优先级
3 100 3:1 3位抢占优先级,1位响应优先级
4 011 4:0 4位抢占优先级,0位响应优先级
  • AIRCR[10:8]寄存器的配置在系统初始化时只能配置一次,不能动态配置,否则会引起中断优先级的混乱。
  • 由于 AIRCR[10:8]寄存器的配置在系统初始化时只能配置一次,所以系统中需要配置的各外部中断抢占优先级和中断响应优先级所占的位数是固定的,所有外部中断必须按照这个规定进行配置。

中断抢占优先级和中断响应优先级

  • 抢占先级级和中断响应优先级配置的数字越小,其优先级越高。
  • 高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
  • 抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
  • 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
  • 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;

如系统中配置了3个中断:

  • 中断1配置的中断抢占优先级为2,响应优先级为3
  • 中断2配置的中断抢占优先级为2,响应优先级为2
  • 中断3配置的中断抢占优先级为1,响应优先级为3

  • 中断先级别为:中断3>中断2>中断1
  • 中断3可以打断正在执行的中断2和中断。
  • 如果中断1正在执行,中断2不可以打断中断2的执行,需要等待中断2执行完成后方可再执行。
  • 如果中断1和中断2同时响应,则中断2优先响应。

NVIC中断寄存器

NVIC的中断寄存器主要分为以下几个寄存器:

  • __IO uint8_t IP[240]; //中断优先级控制的寄存器组
  • __IO uint32_t ISER[8]; //中断使能寄存器组,用于中断的使能
  • __IO uint32_t ICER[8]; //中断失能寄存器组,用于中断失能
  • __IO uint32_t ISPR[8]; //中断挂起寄存器组,用于挂起中断
  • __IO uint32_t ICPR[8]; //中断解挂寄存器组,用于挂解中断
  • __IO uint32_t IABR[8]; //中断激活标志位寄存器组,只读,通过它可以知道当前在执行的中断是哪一个如果对应位为1,说明该中断正在执行。

IP中断优先寄存器为240个,代表着M4支持的240个外部中断,实际STM32F407ZG 只支持82个外部中断,故只使用了前82个。
其余寄存器如ISER、ICER等总共8个32位的长度,这样会有8*32=256,每一位代表一个中断响量的相应的位能。如ISER[0]代表中断的0~31,ISER[1]代表着中断32~63,依次类推。

中断寄存器及基地址

Address Register CMSIS-Core Symbol Function
0xE000E100 - 0xE000E11C Interrupt Set Enable Registers NVIC->ISER [0] - [7] Write 1 to set enable
0xE000E180 - 0xE000E19C Interrupt Clear Enable Registers NVIC->ICER [0] [7] Write 1 to clear enable
0xE000E200 - 0xE000E21C Interrupt Set Pending Registers NVIC->ISPR [0] [7] Write 1 to set pending status
0xE000E280 - 0xE000E29C Interrupt Clear Pending Registers NVIC->ICPR [0]-[7] Write 1 to clear pending status
0xE000E300 - 0xE000E31C Interrupt Active Bit Registers NVIC->IABR [0]-[7] Active status bit.Read only.
0xE000E400 - 0xE000E4EF Interrupt-Priority Registers NVIC->IP [0]-[239] Interrupt-Priority Level (8-bit wide) for each interrupt
0xE000EF00 Software Trigger Interrupt Register NVIC->STIR Write an interrupt number to set its pending status
#define SCS_BASE   (0xE000E000UL)             /*!< System Control Space Base Address  */
#define NVIC_BASE   (SCS_BASE +  0x0100UL)     /*!< NVIC Base Address                  */
#define NVIC       ((NVIC_Type*)NVIC_BASE)    /*!< NVIC configuration struct          */

0xE000E000 + 0x0100=0xE000 E100

IP中断优先级

每个中断的IP中断优先级占1个字节,且该中断只使用了高4位,而低4位未用。
IP中断优先级

注意上图显示的是M4核的IP,而M3的核只使用了高3位,低5位未使用。这有一点区别的。

寄存器相的函数

中断配置函数NVIC_PriorityGroupConfig

#define NVIC_PriorityGroup_0         ((uint32_t)0x700) 
#define NVIC_PriorityGroup_1         ((uint32_t)0x600) 
#define NVIC_PriorityGroup_2         ((uint32_t)0x500) 
#define NVIC_PriorityGroup_3         ((uint32_t)0x400) 
#define NVIC_PriorityGroup_4         ((uint32_t)0x300) 


void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));

  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

中断初始化函数NVIC_Init

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
  uint8_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;

  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  
  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));

  if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
  {
    /* Compute the Corresponding IRQ Priority --------------------------------*/    
    tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
    tmppre = (0x4 - tmppriority);
    tmpsub = tmpsub >> tmppriority;

    tmppriority = NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
    tmppriority |=  (uint8_t)(NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub);

    tmppriority = tmppriority << 0x04;

    NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;

    /* Enable the Selected IRQ Channels --------------------------------------*/
    NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
  else
  {
    /* Disable the Selected IRQ Channels -------------------------------------*/
    NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
}

注意,这里右移5位相当于除为32,这个取得第几个32位的。再通过与上(1 << ((uint32_t)(IRQn) & 0x1F))取得相应的BIT。

当前活跃中断:

__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
{
  return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */
}

中断优先级设置步骤

  • 系统运行后先设置中断优先级分组。调用函数:void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); 整个系统执行过程中,只设置一次中断分组。
  • 针对每个中断,设置对应的抢占优先级和响应优先级:void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
  • 如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。

每个中断初始化时使用的结构体:

typedef struct
{
  uint8_t NVIC_IRQChannel; //设置中断通道
  uint8_t NVIC_IRQChannelPreemptionPriority;//设置响应优先级
  uint8_t NVIC_IRQChannelSubPriority; //设置抢占优先级
  FunctionalState NVIC_IRQChannelCmd; //使能/使能
} NVIC_InitTypeDef;

初始化代码

NVIC_InitTypeDef   NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分且为2即2位抢占优先级,2位响应优先级

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
NVIC_Init(&NVIC_InitStructure);    //根据上面指定的参数初始化NVIC寄存器

0 篇笔记 写笔记

PCIE的资源-IO资源、内存资源和中断资源
在PCIe系统中,对于每一个PCIe设备,都具有三种类型的资源。具有了资源,PCIe设备才具有了被访问、被使用的基本能力。这三种资源分别是:IO资源仅适用于X86架构中内存资源即设备具备哪些可以提供给外部或内部使用的内存。中断资源中断资资可以为INT中断,MSI中断和MSI-X中断。如我们在......
STM32F407ZG NVIC中断向量表
NVIC是嵌入嵌套向量中断控制器的英文Nested vectored interrupt controller的缩写。STM32 CORTEX M4的核支持256个中断,其中包括了16个内核中断和240个外部中断。这256个中断中断编号是固定是,但是其中断优先级是可以设置的。STM32F407......
STM32F407ZG NVIC中断配置
前面提到TM32F407ZG的82个外部中断优先级可以分为16个等级(因为使用了4位的中断优先级配置)。配置中断优先级的4位位于其各自中断的IP寄存器的bit[7:4]位中。这4位的中断优先级按照AIRCR[10:8]寄存器的配置,将这四位分为两种中断优先级,分别为中断抢占优先级和中断响应优先级。......
作者信息
我爱开发
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!