嵌入式與裸機

中斷向量表(interrupt vector table)

想像旅館櫃台有一小排按鈕,每種緊急狀況一個:火災、醫療、保全。按下某個按鈕,櫃台立刻查出該打給誰並撥號。中斷向量表正是處理器的那排電話號碼:一份位址清單,每個中斷或例外各一筆,告訴 CPU 在該事件發生的瞬間要跳到哪個函式。

當硬體需要關注時——計時器跳動、序列埠收到一個位元組、按鈕被按下——它就發出一個中斷。處理器必須停下手邊的事,去跑正確的處理常式。但它怎麼知道是哪個處理常式?它用索引:每個中斷來源都有一個編號,向量表是以那個編號為索引的陣列,每個欄位放著對應中斷服務常式的位址。在 Cortex-M 晶片上,向量表位於快閃起始處,格式漂亮且規律:第 0 格是初始堆疊指標、第 1 格是重置向量,接著是系統例外(NMI、HardFault、SysTick 等),再來是每個週邊中斷各一格(IRQ0、IRQ1……)。當中斷編號 N 觸發時,硬體讀取第 N 格、把那個位址載入程式計數器,你的處理常式就執行了。這張表就是放在已知位址上、由若干個函式指標大小的字組構成的陣列;在 Cortex-M 上那個位址本身可透過一個叫 VTOR(向量表偏移暫存器)的暫存器設定,讓開機載入程式與應用程式各自擁有自己的表。

它之所以重要,是因為它正是把「硬體發生了某事」變成「這個特定函式執行」的機制,不需輪詢、幾乎沒有延遲。誠實的提醒:表必須位於硬體預期的位址(由連結器指令稿放置)、每個用到的欄位都要指向真實且正確的處理常式,而你忘了填的欄位通常指向一個預設的「永遠卡住」處理常式——所以在空的無窮迴圈裡神秘卡死,往往是某個未處理的中斷落到了預設向量。此外,項目的順序由晶片固定,你無法重排。

// Cortex-M 向量表布局(每格 = 一個 32 位元位址): // [0] 初始堆疊指標 // [1] Reset_Handler // [2] NMI_Handler // [3] HardFault_Handler // ... // [15] SysTick_Handler // [16] 外部 IRQ 0 (例如 WWDG) // [17] 外部 IRQ 1 ... // 當 IRQ 編號 N 觸發時,硬體做:PC <- table[16 + N]。

一個以中斷編號為索引的處理常式位址陣列。事件 N 觸發時 CPU 跳到 table[N]——不需輪詢。

常見臭蟲:你啟用了某個中斷卻沒提供處理常式,它就落到預設的「無窮迴圈」向量,於是裝置就這樣卡死。沒有當機卻神秘凍結,往往是未處理的向量,而非邏輯迴圈。

又称
IVTexception vector tablevector table中斷向量表例外向量表