嵌入式與裸機

NVIC(巢狀向量中斷控制器)

/ EN-vick /

當數十件事可能同時要求處理器關注時——一個計時器、三個序列埠、兩個按鈕、一個網路封包——總得有東西當交通警察:決定哪個中斷能通行、以什麼順序,以及一個緊急的能否插隊到一個正在進行、較不緊急的之前。在 ARM Cortex-M 晶片上,那位交通警察是一塊專用硬體,叫做 NVIC,巢狀向量中斷控制器。

把名字拆開看,因為它正好描述了它做什麼。「向量化」(vectored)指它直接與向量表配合:中斷被接受時,NVIC 提供處理常式位址,讓 CPU 不必軟體查表就直接跳到正確的 ISR。「巢狀」(nested)指它支援優先順序與搶占:每個中斷來源都被指派一個優先順序編號(在 Cortex-M 上數字越小=優先順序越高),若一個較高優先的中斷在較低優先的 ISR 執行中觸發,NVIC 可搶占正在跑的處理常式、跑那個緊急的,然後再恢復前一個——中斷巢狀在中斷之內。NVIC 透過系統區段(約 0xE000E000)的暫存器設定:你啟用某個特定中斷(set-enable 暫存器)、設它的優先順序,也能在軟體裡讓它待處理(pend)或清除。在許多 Cortex-M 零件上,優先順序欄位被切成搶占位元與次優先位元,搶占決定誰能打斷誰,次優先只用來在同時待處理且搶占層級相同的中斷間決勝。

它之所以重要,是因為它讓你能建構一個反應靈敏的系統,使關鍵事件(馬達故障)總是勝過例行事件(狀態 LED),而由硬體做這份記帳。誠實的提醒:優先順序編號和直覺相反(越小「越」緊急)、可用的優先位元數因晶片而異(所以 0x10 這個值在不同零件上可能意義不同),而深層巢狀會用掉更多堆疊——每次搶占都堆上另一個堆疊框。此外,NVIC 控制週邊中斷;最底層的幾個例外如重置與 HardFault 有固定優先順序,NVIC 不讓你更改。

// 透過 NVIC 設定一個週邊中斷(CMSIS API): NVIC_SetPriority(USART2_IRQn, 2); // 數字越小 = 優先順序越高 NVIC_EnableIRQ(USART2_IRQn); // 允許此中斷觸發 // 若一個優先順序 0 的中斷在優先順序 2 的 ISR 執行中到來, // NVIC 會搶占它(巢狀),之後再恢復那個優先順序 2 的 ISR。

設好優先順序並啟用中斷;NVIC 接著讓較高優先(編號較小)的中斷搶占較低優先的。

在 Cortex-M 上,優先順序數字「越小」代表「越」緊急——與多數人的直覺相反。而優先順序欄位只實作了最高的幾個位元(因晶片而異),所以同一個數值在不同零件上可能對應不同的有效優先順序。

又稱
nested vectored interrupt controllerinterrupt controller巢狀向量中斷控制器中斷控制器