(STM32) NVIC (Nested vectored interrupt controller) 學習
NVIC 是 ARM Cortex-M 處理器的一部分。負責處理例外和中斷相關程序。
- 允許巢狀中斷,在中斷時,還可以被中斷
- Interrupt 可以自由設定,按照應用自己分配資源
- 可以中斷遮罩,也就是可以停用某些中斷
優先權
在Cortex-M來說,數值越小代表優先權越高。
- group priority (preempt priority)
- subpriority
規則就是一個exception handler正在執行,其他例外發生時,如果group priority優先權比你高就可以插隊執行,如果跟你一樣或者比你低,就得乖乖等。
如果有多個相同優先權的例外處理正在 等待執行(Pending) ,那麼先比較subpriority,優先權較高的排在前面,如果還是一樣 Exception Nmber小的優先。
STM32中斷優先等級暫存器 (Interrupt Priority Registers)
STM32每個Interrupt Channel都擁有屬於自己的interrupt priority register, STM32中每個priority register是4個bit,這4-bits可以依據功能分成下面五組
NVIC_PriorityGroup_0 => 0 bits for pre-emption priority, 4 bits for subpriority
NVIC_PriorityGroup_1 => 1 bits for pre-emption priority, 3 bits for subpriority
NVIC_PriorityGroup_2 => 2 bits for pre-emption priority, 2 bits for subpriority
NVIC_PriorityGroup_3 => 3 bits for pre-emption priority, 1 bits for subpriority
NVIC_PriorityGroup_4 => 4 bits for pre-emption priority, 0 bits for subpriority
NVIC_PriorityGroup
|
Preemption Priority
|
Subpriority
|
NVIC_PriorityGroup_0
|
0 (1 種設定)
|
0~15(16 種設定)
|
NVIC_PriorityGroup_1
|
0,1(2 種設定)
|
0~7(8 種設定)
|
NVIC_PriorityGroup_2
|
0,1,2,3 (4 種設定)
|
0,1,2,3(4 種設定)
|
NVIC_PriorityGroup_3
|
0,1,2,3,4,5,6,7 (8 種設定)
|
0,1(2 種設定)
|
NVIC_PriorityGroup_4
|
0~15(16 種設定)
|
0(1 種設定)
|
當我們在使用STM32的NVIC中斷時會發現,中斷的優先等級分成了preemption priority 與subpriority 兩種而這兩優先等級有甚麼不一樣:
1. Preemption Priority
當中斷發生時,擁有較高Preemption priority=0的interrupt channel可以將較低preemptrion priority=1,2,3的interrupt chnannel中斷優先被處理。假如兩個interrupt channel擁有相同peemption priority,後到的interrupt event必須等到現有的中斷被處理完畢後才能被處理。
2. Subpriority
在兩個interrupt channel的preemption priority相同的前提下,如果兩個subpriority不同的interrupt event同時發生,則subpriority高的interrupt會先被處理,但是如果低優先等級的interrupt channel event 已經在執行,則不能被打斷,高subpriority的event必須等到現有的event被處理完才能被處理。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x04; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x03; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct);
以上範例如果先執行 EXTI0 在觸發 EXTI15_10,會優先執行 EXTI15_10
但如果 EXTI0 優先權比 EXTI15_10 高但是也觸發了,會等EXTI0執行完畢再執行EXTI15_10。