本帖最后由 binoo7 于 2021-1-22 23:10 编辑
#申请原创#
现在又经过了几天的学习,再来说一下中断的事儿吧
首先HC32F460用的是Cortex-M4的内核,这个内核有16个异常,也就是ARM的M4自带的叫做异常
还有多达 256 级的可编程优先级,并且支持 128级抢占,这个就是芯片厂商负责的部分了,例如HC32F460 定义了144个中断向量
因为用的是Cortex-M4的内核,支持中断优先级分组,分组的方式见图片
根据HC32F460的例程给出的定义
#define __NVIC_PRIO_BITS 4 /*!< HC32F46X uses 4 Bits for the Priority Levels */
他们用了前4位来配置优先级分组
但是这个分组不知道能不能配置,因为例程里设置的是一个固定的分组 组0 也就是所有的中断都在同一个抢占优先级,而大家都在剩余的亚优先级内,举个例子比如
以下转自野火教程
中断向量具有两个属性,一个为抢占属性,另一个为响应属性,其属性编号越小,表明它的优先级别越高。
抢占,是指打断其他中断的属性,即因为具有这个属性会出现嵌套中断(在执行中断服务函数A 的过程中被中断B 打断,执行完中断服务函数B 再继续执行中断服务函数A) 中断向量 抢占优先级 亚优先级(响应优先级) A 0 0 B 1 0 C 1 1 若内核正在执行C 的中断服务函数,则它能被抢占优先级更高的中断A 打断, 由于B和C 的抢占优先级相同,所以C 不能被B 打断。 但如果B 和C 中断是同时到达的,内核就会首先响应响应优先级别更高的B 中断。
这样的解释大家应该都清楚了吧
SCB->AIRCR的配置,可以配置中断优先级分组,HC32F460的配置是这样的 <font color="rgb(77,77,77)"><font face="-apple-system,"><font size="3">__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
reg_value = SCB->AIRCR; /* read old register configuration */
reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
reg_value = (reg_value |
((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
(PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
SCB->AIRCR = reg_value;
}
</font></font></font>
但是这个函数并没有用到,而是在这个函数里配置了/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
__DSB(); /* Ensure completion of memory access */
for(;;) /* wait until reset */
{
__NOP();
}
}
解释一下华大用的这个配置函数,他将SCB->AIRCR寄存器&上了0x700,在权威指南里对于SCB->AIRCR优先级分组在复位后所有的数据都会是0,也就说在每次复位后,SCB->AIRCR寄存器&0x700=0,也就是将中断优先级分组配置成了组4
第04组: 所有4 位用来配置抢占优先级。
是不是大家有疑惑了,他才有16个抢占中断优先级,他的中断向量表不是有144个啊,这也不够用啊
别担心,这144个中断向量不是说每一个向量都要占一个中断优先级,可以几个中断向量占同一个中断优先级,谁先来,就先响应谁,等这个中断结束了,再依次响应其他优先级低的中断,如果优先级高的中断来了,就会响应高优先级的中断,这样就形成了中断的嵌套,这么说的话大家就清楚了吧。
可以根据自己的需要来修改#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */是7还是6/5/4/3 这样的话就可以得到响应的中断优先级分组了,还有可以调用
__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
reg_value = SCB->AIRCR; /* read old register configuration */
reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
reg_value = (reg_value |
((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
(PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
SCB->AIRCR = reg_value;
}
这个函数来改变中断优先级 。
在权威指南里还说了这样一句话大家要注意:
其实在绝大多数情况下,优先级的分组都要预先经过计算论证,并且在开机初始化时一次性地设置好,以后就再也不动它了。
只有在绝对需要且绝对有把握时,才小心地更改,并且要经过尽可能充分的测试。
另外,优先级组所在的寄存器 AIRCR也基本上是“一次成型”,只是需要手工产生复位时才写里面相应的位。
|