初级会员

- 积分
- 111
- 金钱
- 111
- 注册时间
- 2016-3-15
- 在线时间
- 66 小时
|

楼主 |
发表于 2018-4-11 15:00:52
|
显示全部楼层
终于搞懂了,记录一下,方便以后查看。
首先看CM3的内容:
CM3支持中断嵌套,高优先级异常可以抢占低优先级异常,原则上,CM3最少支持3个固定优先级和256级可编程优先级(CM3优先级分组规定,子优先级最少要占一位,所以实际可配置的抢占优先级只剩128级了,但是不晓得为什么stm32没有这个规定,最低可以用0位子优先级),这个优先级分组是靠着AIRCR寄存器决定的,这是一个8bit的寄存器,优先级以MSB对齐(便于跨器件的移植,后面会讲到),所以CM3最少支持8级可编程的优先级。
而stm32使用了4位中断优先级,这样就一共有16个可编程的优先等级(最低0位子优先级,这样抢占最多可以达到16级)。这时候,片上一共68个可屏蔽的中断通道加上内核的16个中断线(不包含RESET,NMI和硬fault,这三个是固定的,可以跨越所有的其他异常)都可以由你来指定到底这些中断要划分为几个层次,,这里用到了两个寄存器,AIRCR寄存器和IP寄存器(中断优先级控制寄存器)来决定的(AIRCR寄存器参考CM3),IP寄存器是一个8bit的寄存器组,stm32只用到了前68个组,其中这8bit并没有被全部使用,而是又被分成了高4位和低4位。实际只使用了高4位,这4位又被分成了抢占优先级和子优先级,具体抢占和子优先级各占几位,要由AIRCR寄存器决定,也就是一旦你设置好了优先级分组,你就知道你的中断被划分成了多少个等级了。
抢占优先级和子优先级共同决定了优先级的编号[mw_shl_code=c,true] /* 2 bit for pre-emption priority, 2 bits for subpriority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the USART2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);[/mw_shl_code]
这样设置的话,USART2_IRQn的优先级编号就是15。可以用NVIC_GetPriority()验证一下。
回到我一开始问的问题[mw_shl_code=c,true] * Set the priority for the specified interrupt. The interrupt
* number can be positive to specify an external (device specific)
* interrupt, or negative to specify an internal (core) interrupt.
*
* Note: The priority cannot be set for every core interrupt.
*/
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 */
}[/mw_shl_code]
这个函数为什么允许传入负数,我自己试了一下,其实不试也能猜出来,因为用get获取中断优先级编号的时候返回的是一个无符号的整数,而AIRCR寄存器是高字节对齐的,顶多就是你想配置最高级别的中断,结果配成了最低的呗,但是这个函数注释比较令人疑惑,传入负数指定一个core中断,应该不是内核中断的意思吧 |
|