__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
//当外设号大于0时设置外设中断优先级
//原理为priority << (8U - __NVIC_PRIO_BITS左移, __NVIC_PRIO_BITS在F103系列中为4,因为在优先
级寄存器中(Interrupt priority registers (NVIC_IPRx))只有高四位有用,故需要将设定优先级
priority的值左移四位;
if ((int32_t)(IRQn) >= 0)
{
NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
//当IRQn号小于0时执行下方指令
else
{
SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
}
本文主要说明IRQn小于0时,代码运行原理:
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 */
PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */
上述代码为系统硬件的IRQn,可以发现均小于0,
在第一部分代码中有一个强制转换(uint32_t)IRQn,因为中断号为负数,在计算机中负数用补码存储,以-5为例,8位二进制表示为1000 0101 ,反码为1111 1010 ,补码为1111 1011,将其转为无符号32位其为11111111 11111111 11111111 11111011;
(((uint32_t)IRQn) & 0xFUL)-4UL 表示将IRQn的末四位取出并且减去4,当IRQn=-5时,该代码运行结果为1011即为11减去4,最终结果为7;该处8代表了 SCB->SHP[8]中此处的数组中的元素,表明SHP中的第9个元素为SVCall的优先级。