理解STM32的NVIC_PriorityGroupConfig函数

该函数的作用

用于设置NVIC优先级分组,分配抢占优先级响应优先级各自所占的比例。

 

优先级的基本定义

  • 在 Cortex-M3(CM3)中,优先级对于异常来说很关键的,它会影响一个异常是否能被响应,以及何时可以响应。
  • 优先级的数值越小,则优先级越高
  • CM3 支持中断嵌套,使得高优先级异常会抢占(preempt)低优先级异常。
  • 有 3 个系统异常:复位,NMI 以及硬 fault,它们有固定的优先级,并且它们的优先级号是负数,从而高于所有其它异常。
  • CM3 支持 3 个固定的高优先级和多达 256 级的可编程优先级,并且支持 128级抢占,但是绝大多数芯片在设计时会裁掉表达优先级的几个低端有效位,以达到减少优先级数的目的。

 

 

为什么要设置抢占优先级和响应优先级

为了使抢占机能变得更可控,CM3把 256 级优先级按位分成高低两段,即抢占优先级和亚优先级。     函数代码理解
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分组类型作为参数进入该函数,该参数在misc.h文件中有定义

理解STM32的NVIC_PriorityGroupConfig函数

理解STM32的NVIC_PriorityGroupConfig函数

可见共有4bit用于设置优先级分组,而不同的分组类型决定抢占优先级和响应优先级各自所占的bit比例。如果各占2bit,那么抢占优先级和响应优先级就各有2²=4的优先级值。

 

看回到函数第一行代码

assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));

 

该函数用于判断用户输入的参数是否有错。在misc.h文件中有一个带参宏定义。

#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))

如果参数正确则会返回true值。我们再看到以下代码

#ifdef  USE_FULL_ASSERT

/**
  * @brief  The assert_param macro is used for function's parameters check.
  * @param  expr: If expr is false, it calls assert_failed function which reports 
  *         the name of the source file and the source line number of the call 
  *         that failed. If expr is true, it returns no value.
  * @retval None
  */
  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
  void assert_failed(uint8_t* file, uint32_t line);
#else
  #define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */

#endif /* __STM32F10x_CONF_H */

可以看到当定义USE_FULL_ASSERT时,当此前函数返回的值为true,则函数不执行任何操作,如果返回的值为false,则assert_failed()会报告错误文件和错误行。但在代码中能够发现assert_failed()仅仅是个框架,因此需要开发者自己编写。

通常USE_FULL_ASSERT是没有被定义的,那么该函数往往不会执行任何操作。

 

看到原函数第二行代码

SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;

 

首先是执行了一次或运算,在头文件中有给出AIRCR_VECTKEY_MASK的值

#define AIRCR_VECTKEY_MASK    ((uint32_t)0x05FA0000)

该函数用于配置AIRCR寄存器(应用程序中断及复位控制寄存器)。根据规定,任何对该寄存器的写操作都要把0x05FA写入31:16位段,否则该操作会被忽略。

理解STM32的NVIC_PriorityGroupConfig函数

同时我们也可以看到共有3bit用于配置优先级分组,具体值在头文件中宏定义的NVIC优先级分组给出。

 

其中SCB只是个结构体,在core_cm3.h中给出,里面定义了一些寄存器的数据类型。

理解STM32的NVIC_PriorityGroupConfig函数

 

最终加*问钥匙后,我们把值写入AIRCR寄存器,完成优先级分组的配置。

 

参考资料

Cortex-M3权威指南(中文)

上一篇:SimpleDateFormat日期格式化顺延,setLenient关闭顺延


下一篇:关于VS编译通过,运行时报错的问题,c++ dlgdata.cpp 中ASSERT(FALSE)处发生异常