ARM 通用中斷控制器GIC(Generic Interrupt Controller)
Zynq7000系列學習筆記
本文介紹分發器(Distributor)和CPU接口 (CPU Interface)的功能與協作,并提供C語言案例輔助理解。
總結來說,分發器設置中斷使能和中斷優先級,并將該中斷信號發送給CPU,CPU設置可接受的最低優先級,進行中斷處理和完成中斷通知。
一、分發器和CPU接口的功能
|
分發器Distributor |
CPU 接口 (CPU Interface) |
|
|
基地址 |
|
|
|
功能 |
全局中斷管理 |
CPU 核心的中斷交互 |
|
管理對象 |
所有中斷源 (SPI, PPI, SGI) |
連接到單個 CPU 核心的中斷 |
|
具體使用 |
中斷使能/禁用、優先級配置、路由到 CPU |
中斷確認、優先級屏蔽、中斷完成通知 |
|
可見性 |
全局唯一(CPU共享) |
每個CPU私有 |
二、工作原理與交互流程 (中斷生命周期)
- 中斷觸發(外設 → 分發器)
- 外設中斷源(如 GPIO / UART / Timer)觸發中斷信號。
- 分發器接收:
- 中斷信號到達分發器(
0xF8F01000) - 分發器檢查該中斷是否 已使能(
GICD_ISENABLERn) - 分發器讀取該中斷的 優先級(
GICD_IPRIORITYRn) - 分發器根據配置決定是否 轉發 給目標 CPU
- 中斷分發(分發器 → CPU 接口)
- 路由決策:
- 分發器檢查目標 CPU 接口的狀態(是否使能接收中斷)
- 比較 中斷優先級 與目標 CPU 當前的 運行優先級(通過 CPU 接口的 GICC_PMR 獲取)
- 若中斷優先級 > CPU 當前優先級,分發器將其掛起到目標 CPU 的待處理隊列。
- 信號通知:
- 分發器通過硬件信號線通知目標 CPU 的 CPU 接口:有高優先級中斷等待處理。
- CPU 響應 (CPU 接口 → CPU 核心)
- 中斷通知:
- CPU 接口 (
0xF8F00100)收到分發器通知。 - CPU 接口向 CPU 核心 發送 IRQ/FIQ 中斷請求。
- CPU 核心響應:
- CPU 核心暫停當前程序,跳轉到 中斷向量表 入口。
- 執行中斷服務程序 (ISR) 的 入口代碼。
- 中斷處理 (ISR 與 CPU 接口交互)
- 中斷確認:
- ISR 通過 CPU 接口的 Interrupt Acknowledge Register(GICC_IAR)讀取 中斷號(INTID)
- 讀取 GICC_IAR 的行為告知 GIC:“CPU 已開始處理此中斷”
- GIC 自動將該中斷狀態從 Pending 改為 Active
- 服務中斷:
- ISR 根據 INTID 執行具體的中斷服務邏輯(如讀取 UART 數據)
- 中斷完成:
- ISR 結束時,向 CPU 接口的 End of Interrupt Register(GICC_EOIR)寫入之前讀到的 INTID。
- 寫入 GICC_EOIR 告知 GIC:“此中斷處理已完成”
- GIC 將該中斷狀態從 Active 改為 Inactive,并允許分發器再次發送此中斷(若再次觸發)
- 中斷優先級與搶占
- 分發器 根據全局中斷優先級決定哪些中斷可發送給 CPU。
- CPU 接口 的 GICC_PMR 設置 CPU 可接受的最低優先級(低于此值的中斷被屏蔽)
- 若高優先級中斷到達,且當前中斷優先級較低,CPU 接口可觸發 中斷搶占(暫停當前 ISR,轉去處理更高優先級中斷)。
三、軟件編程詳細案例
- 分發器初始化代碼詳解
- 全局使能分發器
*(volatile uint32_t *)(GIC_DIST_BASE + 0x000) = 0x1; // GICD_CTLR
- 作用:啟用整個中斷分發系統,是整個 GIC 系統的總開關
- 寄存器:
GICD_CTLR(Distributor Control Register) - 地址計算:基地址
0xF8F01000+偏移量0x000 - 位設置:
Bit 0 = 1:使能中斷轉發到 CPU 接口Bit 1 = 0:禁用安全擴展
- 配置中斷優先級
*(volatile uint32_t *)(GIC_DIST_BASE + 0x400 + (84 * 4/4)) = 0xA0;
// GICD_IPRIORITYR[21]
- 作用:設置中斷號84的優先級(優先級范圍0~255,0最高)
- 寄存器:
GICD_IPRIORITYRn(Interrupt Priority Registers) - 地址計算:
- 優先級寄存器組基偏移:0x400
- 中斷號 84 的偏移:84 * 1(因為每個中斷占 1 字節)
- 實際地址:
0xF8F01000 + 0x400 + 84 = 0xF8F01454 - Zynq-7000 中:0-31是私有中斷(PPI)和軟件中斷(SGI);32-95是共享外設中斷(SPI)
- 路由到 CPU0
*(volatile uint32_t *)(GIC_DIST_BASE + 0x800 + (84 * 4/4)) = 0x01;
// GICD_ITARGETSR[21]
- 作用:指定中斷84發送到 CPU0
- 寄存器:
GICD_ITARGETSRn(Interrupt Processor Targets Registers) - 地址計算:
0xF8F01000 + 0x800 + 84 = 0xF8F01854 - 位掩碼:
0x01表示 CPU0
Bit 0 = 1:路由到 CPU0Bit 1 = 0:不路由到 CPU1
- 注:在雙核系統中,必須明確指定中斷發送到哪個核心。
- 注:PPI/SGI 不能配置路由,只有 SPI(32+)可配置
- 使能中斷號 84
*(volatile uint32_t *)(GIC_DIST_BASE + 0x100 + (84 / 32)*4) |= (1 << (84 % 32));
// GICD_ISENABLER
- 作用:啟用特定中斷源
- 寄存器:
GICD_ISENABLERn(Interrupt Set-Enable Registers) - 地址計算:
- 使能寄存器組基偏移:
0x100 - 寄存器索引:
84 / 32 = 2(第3個寄存器,管理中斷64-95) - 位位置:
84 % 32 = 20 - 實際地址:
0xF8F01000 + 0x100 + 2*4 = 0xF8F01008
- CPU 接口初始化代碼詳解
- 設置優先級屏蔽閾值
*(volatile uint32_t *)(GIC_CPU_BASE + 0x0004) = 0xA0; // GICC_PMR
- 作用:定義 CPU 處理中斷的最低優先級
- 寄存器:
GICC_PMR(Priority Mask Register) - 地址:
0xF8F00100 + 0x0004 = 0xF8F00104 - 值說明:0xA0(160)表示:
- 優先級高于 160 的中斷被屏蔽
- 優先級低于 160 的中斷可被處理
- 防止低優先級中斷打斷高優先級任務
- 使能 CPU 接口
*(volatile uint32_t *)(GIC_CPU_BASE + 0x0000) = 0x1; // GICC_CTLR
- 作用:啟用 CPU 與 GIC 的交互通道
- 寄存器:
GICC_CTLR(CPU Interface Control Register) - 地址:
0xF8F00100 + 0x0000 = 0xF8F00100 - 位設置:
Bit 0 = 1:使能中斷信號到 CPUBit 1 = 0:禁用 FIQ(通常用 IRQ)Bit 2 = 0:禁用 ACK 特殊處理
- 注:不使能CPU接口,即使分發器發送中斷,CPU 也不會響應
- 中斷服務程序 (ISR)
- 讀取中斷號
uint32_t intid = *(volatile uint32_t *)(GIC_CPU_BASE + 0x000C); // GICC_IAR
- 作用:獲取當前中斷 ID 并確認接收
- 寄存器:
GICC_IAR(Interrupt Acknowledge Register) - 地址:
0xF8F00100 + 0x000C = 0xF8F0010C - 讀取操作的意義:
- 獲取中斷號(低 10 位)
- 通知 GIC "CPU 已開始處理此中斷"
- 狀態轉換:GIC 將中斷狀態從 Pending 改為 Active
- 注:必須讀取此寄存器后才能安全處理中斷
- 注:返回值可能包含其他信息(如 CPU 號),通常
intid & 0x3FF提取 ID
- 執行中斷處理
handle_irq(intid); // 用戶定義的中斷處理函數
- 應避免阻塞其他中斷
- 不能調用可能阻塞的函數
- 清除外設中斷標志
- 通知中斷處理完成
*(volatile uint32_t *)(GIC_CPU_BASE + 0x0010) = intid; // GICC_EOIR
- 作用:告知 GIC 中斷處理已完成
- 寄存器:
GICC_EOIR(End of Interrupt Register) - 地址:
0xF8F00100 + 0x0010 = 0xF8F00110 - 注:必須寫入從
GICC_IAR讀取的原始值 - 必須在中斷處理完成后立即執行
- 此時中斷狀態從Active轉換為Inactive,才能允許相同的中斷再次觸發

浙公網安備 33010602011771號