NVIC_SetPriority()库函数分析及与寄存器的对应关系

在学习SysTick时使用库函数Systick_Config()中调用了NVIC_SetPriority(),当时没有做详细研究,现在就来学习一下吧。

在SysTick_config()中调用如下所示:

NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);/* set Priority for Cortex-M0 System Interrupts */

 SysTick_IRQn 为宏定义在stm32f10x.h,其值为-1;

__NVIC_PRIO_BITS同样为宏定义在stm32f10x.h,其值为4;上述函数可以改写为:

NVIC_SetPriority (-1, 16 - 1);

下面让我们来看看 NVIC_SetPriority()函数的定义,它IR的主要作用是设置中断的优先级,

它包含2个参数,IRQn 用来指定中断源,priority指定优先级。

当IRQn<0时,配置内核中断的优先级

当IRQn>=0时,配置的是外部中断的优先级

static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
  if(IRQn < 0) {
    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
  else {
    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */
}

当IRQn<0时,设置的是内核中断 ,0~15优先级可以设置,数字越小优先级越高,STM32F103共包含如下内核中断

  NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                             */
  MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M3 Memory Management Interrupt              */
  BusFault_IRQn               = -11,    /*!< 5 Cortex-M3 Bus Fault Interrupt                      */
  UsageFault_IRQn             = -10,    /*!< 6 Cortex-M3 Usage Fault Interrupt                    */
  SVCall_IRQn                 = -5,     /*!< 11 Cortex-M3 SV Call Interrupt                       */
  DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M3 Debug Monitor Interrupt                 */
  PendSV_IRQn                 = -2,     /*!< 14 Cortex-M3 Pend SV Interrupt                       */
  SysTick_IRQn                = -1,     /*!< 15 Cortex-M3 System Tick Interrupt   

由上可知 NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1)是将SysTick中断的优先级设置为15,即内核优先级中最低的。

接着让我们来看看库函数是怎么一步步与寄存器对应起来的,以加深印象。

内核中断优先级设置:

首先我们来看下SCB->SHPR这个寄存器

SHPR1-SHPR3寄存器都是32位的,用来设置内核中断的优先级(0-15),并且可以以字节形式进行读写,设置每个内核中断的优先级的字段虽然是8位的,但只有高4位(7:4)用来设置优先级,所以优先级只能是0-15,低4位(3:0)在被读取时为0,写入时忽略。

SHPR1

SHPR2

SHPR3

在core_cm3.h文件中的SCB结构体中包含一个uint8_t的数组 SHP[12],如下所示:

typedef struct
{
  __I  uint32_t CPUID;                        /*!< Offset: 0x00  CPU ID Base Register                                  */
  __IO uint32_t ICSR;                         /*!< Offset: 0x04  Interrupt Control State Register                      */
  __IO uint32_t VTOR;                         /*!< Offset: 0x08  Vector Table Offset Register                          */
  __IO uint32_t AIRCR;                        /*!< Offset: 0x0C  Application Interrupt / Reset Control Register        */
  __IO uint32_t SCR;                          /*!< Offset: 0x10  System Control Register                               */
  __IO uint32_t CCR;                          /*!< Offset: 0x14  Configuration Control Register                        */
  __IO uint8_t  SHP[12];                      /*!< Offset: 0x18  System Handlers Priority Registers (4-7, 8-11, 12-15) */
  __IO uint32_t SHCSR;                        /*!< Offset: 0x24  System Handler Control and State Register             */
  __IO uint32_t CFSR;                         /*!< Offset: 0x28  Configurable Fault Status Register                    */
  __IO uint32_t HFSR;                         /*!< Offset: 0x2C  Hard Fault Status Register                            */
  __IO uint32_t DFSR;                         /*!< Offset: 0x30  Debug Fault Status Register                           */
  __IO uint32_t MMFAR;                        /*!< Offset: 0x34  Mem Manage Address Register                           */
  __IO uint32_t BFAR;                         /*!< Offset: 0x38  Bus Fault Address Register                            */
  __IO uint32_t AFSR;                         /*!< Offset: 0x3C  Auxiliary Fault Status Register                       */
  __I  uint32_t PFR[2];                       /*!< Offset: 0x40  Processor Feature Register                            */
  __I  uint32_t DFR;                          /*!< Offset: 0x48  Debug Feature Register                                */
  __I  uint32_t ADR;                          /*!< Offset: 0x4C  Auxiliary Feature Register                            */
  __I  uint32_t MMFR[4];                      /*!< Offset: 0x50  Memory Model Feature Register                         */
  __I  uint32_t ISAR[5];                      /*!< Offset: 0x60  ISA Feature Register                                  */
} SCB_Type;  

 

SHP[0]-SHP[11]与SHPR1-SHPR3的每个字节是一一对应的,即SHP[0]对应SHPR1的低8位[7:0].

现在让我们来验证下上面结论是否正确, 

SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);

SysTick_IRQn对应值为-1,首先强制转化为uint32_t结果为0xffff ffff,与上0xf后结果为0xf,减去4结果为11,即SHP[11]对应SHPR3的 [31:24] 位,与实际相符。

BusFault_IRQn对应值为-11,首先强制转化为uint32_t结果为0xffff fff5,与上0xf后结果为0x5,减去4结果为1,即SHP[1]对应SHPR1的 [15:8] 位,与实际相符。

priority的设置

__NVIC_PRIO_BITS为宏定义值为4,由于设置优先级的寄存器是8位的但只有高4位有效,所以需要将priority的值左移4位。

外部中断优先级设置:

NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);

Coretex_m3 的 NVIC 用中断优先级寄存器(IPR)的 8 位字段映射到一个 8 位整数数组IP[240],数组条目 IP[n] 保存中断号为 n 的中断优先级。

例如:IP[0] 对应WWDG_IRQn的中断优先级

           IP[6]对应EXTI0_IRQn的中断优先级

Interrupt priority registers (NVIC_IPRx)中断优先级寄存器 

 

每个IPR寄存器包含4个优先级字段,每个字段占8个bit,可以用字节的方式读取或写入,但只有[7:4] bit用来表示优先级,读取字段的[3:0]bits时值为0,写[3:0]bits时将该值忽略。

所以在库函数中要将写入的优先级的值先左移4位。

IP[n]中的内容要根据NVIC分组的不同来确定,NVIC将外设优先级分为5组,默认分组为0,

/**
  * @brief  Configures the priority grouping: pre-emption priority and subpriority.
  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 
  *   This parameter can be one of the following values:
  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority    //不支持抢占优先级
  *                                4 bits for subpriority             //支持16个响应优先级
  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority    //支持2个抢占优先级
  *                                3 bits for subpriority           //支持8个响应优先级  
  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority    //支持4个抢占优先级
  *                                2 bits for subpriority             //支持4个响应优先级
  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority    //支持8个抢占优先级
  *                                1 bits for subpriority             //支持2个响应优先级
  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority    //支持16个抢占优先级
  *                                0 bits for subpriority             //不支持响应优先级
  * @note   When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. 
  *         The pending IRQ priority will be managed only by the subpriority. 
  * @retval None
  */
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)

 例如将NVIC 优先级分组设置为组2,外部中断EXTI0的抢占优先级设置为1,响应优先级设置为1,分组2表示[7:6]2bits表示抢占优先级,[5:4]2bits表示响应优先级,EXTI0的中断号为6,    IP[6]=0101 0000 ,则读取IP[6]的值为0x50。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值