LINUX-I.MX6U從零開始之1.6--中斷

一,Cortex-A7 中斷系統

Cortex-A7 內核有 8 個異常中斷
在這裏插入圖片描述
復位中斷(Rest), CPU 復位以後就會進入復位中斷, 我們可以在復位中斷服務函數裏面做一些初始化工作,比如初始化 SP 指針、DDR 等等。
未定義指令中斷(Undefined Instruction),如果指令不能識別的話就會產生此中斷。
軟中斷(Software Interrupt,SWI),由 SWI 指令引起的中斷,Linux 的系統調用會用 SWI 指令來引起軟中斷,通過軟中斷來陷入到內核空間。
指令預取中止中斷(Prefetch Abort),預取指令的出錯的時候會產生此中斷。
數據訪問中止中斷(Data Abort),訪問數據出錯的時候會產生此中斷。
IRQ 中斷(IRQ Interrupt),外部中斷,前面已經說了,芯片內部的外設中斷都會引起此中斷的發生。
FIQ 中斷(FIQ Interrupt),快速中斷,如果需要快速處理中斷的話就可以使用此中。
我們常用的就是復位中斷和 IRQ 中斷,Cortex-A 內核 CPU 的所有外部中斷都屬於IQR 中斷。
在這裏插入圖片描述

二,中斷控制器GIC

2.1 GIC框架

GIC 有 4 個版本:V1~V4,V1 是最老的版本,已經被廢棄了。GIC V2 是給 ARMv7-A 架構使用的,比如 Cortex-A7、Cortex-A9、Cortex-A15 等,V3 和 V4 是給 ARMv8-A/R 架構使用的,也就是 64 位芯片使用的。
ARM 針對 GIC V2 開發出了 GIC400 這個中斷控制器 IP 核。當 GIC 接收到外部中斷信號以後就會報給 ARM 內核,但是ARM 內核只提供了四個信號給 GIC 來彙報中斷情況:
VFIQ:虛擬快速 FIQ。
VIRQ:虛擬快速 IRQ。
FIQ:快速中斷 IRQ。
IRQ:外部中斷 IRQ。
在這裏插入圖片描述
GICV2 的邏輯圖如圖所示:
在這裏插入圖片描述
左側部分就是中斷源,中間部分就是 GIC 控制器,最右側就是中斷控制器向處理器內核發送中斷信息。中間 GIC 部分將衆多的中斷源分爲分爲三類:
①、SPI(Shared Peripheral Interrupt),共享中斷,顧名思義,所有 Core 共享的中斷,這個是最
常見的,那些外部中斷都屬於 SPI 中斷(注意!不是 SPI 總線那個中斷) 。比如按鍵中斷、串口中斷等等,這些中斷所有的 Core 都可以處理,不限定特定 Core。
②、PPI(Private Peripheral Interrupt),私有中斷,我們說了 GIC 是支持多核的,每個核肯定有自己獨有的中斷。 這些獨有的中斷肯定是要指定的核心處理, 因此這些中斷就叫做私有中斷。
③、SGI(Software-generated Interrupt),軟件中斷,由軟件觸發引起的中斷,通過向寄存器GICD_SGIR 寫入數據來觸發,系統會使用 SGI 中斷來完成多核之間的通信。

2.2 中斷 ID

中斷源有很多,爲了區分這些不同的中斷源肯定要給他們分配一個唯一 ID,這些 ID 就是中斷 ID。每一個 CPU 最多支持 1020 箇中斷 ID,中斷 ID 號爲 ID0~ID1019。這 1020 個 ID 包含了 PPI、SPI 和 SGI.
ID0~ID15:這 16 個 ID 分配給 SGI。
ID16~ID31:這 16 個 ID 分配給 PPI。
ID32~ID1019:這 988 個 ID 分配給 SPI,像 GPIO 中斷、串口中斷等這些外部中斷。
I.MX6U 的總共使用了 128 箇中斷 ID,加上前面屬於 PPI 和 SGI 的 32 個 ID,I.MX6U 的中斷源共有 128+32=160個。
128 箇中斷 ID 對應的中斷在《I.MX6ULL 參考手冊》的“3.2 Cortex A7 interrupts”小節。
MCIMX6Y2C.h裏的枚舉類型 IRQn_Type,枚舉出了 I.MX6U 的所有中斷。

2.3 GID邏輯分塊

GIC 架構分爲了兩個邏輯塊: Distributor 和 CPU Interface, 也就是分發器端和 CPU 接口端。
例程“9_int”(原子LINUX),core_ca7.h 定義了 GIC 結構體。
結構體第 5 行是 GIC 的分發器端相關寄存器,其相對於 GIC 基地址偏移爲 0X1000,獲取到GIC 基地址以後只需要加上 0X1000 即可訪問 GIC 分發器端寄存器。
結構體第 51 行是 GIC 的 CPU 接口端相關寄存器,其相對於 GIC 基地址的偏移爲 0X2000,獲取到 GIC 基地址以後只需要加上 0X2000 即可訪問 GIC 的 CPU 接口段寄存器。

2.3.1 Distributor( 分發器端)

此邏輯塊負責處理各個中斷事件的分發問題,也就是中斷事件應該發送到哪個 CPU Interface 上去。分發器收集所有的中斷源,可以控制每個中斷的優先級, 它總是將優先級最高的中斷事件發送到 CPU 接口端。 分發器端要做的主要工作如下:
①、全局中斷使能控制。
②、控制每一箇中斷的使能或者關閉。
③、設置每個中斷的優先級。
④、設置每個中斷的目標處理器列表。
⑤、設置每個外部中斷的觸發模式:電平觸發或邊沿觸發。
⑥、設置每個中斷屬於組 0 還是組 1。

2.3.2 CPU Interface(CPU 接口端)

CPU 接口端聽名字就知道是和 CPU Core 相連接的,因此每個 CPU Core 都可以在 GIC 中找到一個與之對應的 CPU Interface。CPU 接口端就是分發器和 CPU Core 之間的橋樑,CPU 接口端主要工作如下:
①、使能或者關閉發送到 CPU Core 的中斷請求信號。
②、應答中斷。
③、通知中斷處理完成。
④、設置優先級掩碼,通過掩碼來設置哪些中斷不需要上報給 CPU Core。
⑤、定義搶佔策略。
⑥、當多箇中斷到來的時候,選擇優先級最高的中斷通知給 CPU Core。

2.4 CP15 協處理器

關於 CP15 協處理器和其相關寄存器的詳細內容請參考下面兩份文檔:
《ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf》第 1469 頁“B3.17
Oranization of the CP15 registers in a VMSA implementation” 。
《Cortex-A7 Technical ReferenceManua.pdf》第 55 頁“Capter 4 System Control” 。
CP15 協處理器一般用於存儲系統管理,但是在中斷中也會使用到,CP15 協處理器一共有
16 個 32 位寄存器。CP15 協處理器的訪問通過指令完成
在這裏插入圖片描述

三,中斷使能

3.1 IRQ 和 FIQ 總中斷使能

寄存器 CPSR 的 I=1 禁止 IRQ,當 I=0 使能 IRQ;F=1 禁止 FIQ,F=0 使能 FIQ。
我們還有更簡單的指令來完成 IRQ 或者 FIQ 的使能和禁止.
在這裏插入圖片描述

3.2 ID0~ID1019 中斷使能和禁止

GIC 寄存器 GICD_ISENABLERn 和 GICD_ ICENABLERn 用來完成外部中斷的使能和禁止,對於 Cortex-A7 內核來說中斷 ID 只使用了 512 個。一個 bit 控制一箇中斷 ID 的使能,那麼就需要 512/32=16 個 GICD_ISENABLER 寄存器來完成中斷的使能。同理,也需要 16 個GICD_ICENABLER 寄存器來完成中斷的禁止。其中 GICD_ISENABLER0 的 bit[15:0]對應ID15-0 的 SGI 中斷,GICD_ISENABLER0 的 bit[31:16]對應 ID31-16 的 PPI 中斷。剩下的GICD_ISENABLER1–GICD_ISENABLER15 就是控制 SPI 中斷的。

四,中斷優先級設置

4.1 優先級數

Cortex-A7 最多可以支持 256 個優先級,數字越小,優先級越高!I.MX6U 選擇了 32 個優先級。在使用中斷的時候需要初始化 GICC_PMR 寄存器,此寄存器用來決定使用幾級優先級。
GICC_PMR 寄存器只有低 8 位有效,這 8 位最多可以設置 256 個優先級。
I.MX6U 支持 32 個優先級,所以 GICC_PMR 要設置爲 0b11111000。

4.2 搶佔優先級和子優先級位數設置

搶佔優先級和子優先級各佔多少位是由寄存器 GICC_BPR 來決定的。
寄存器GICC_BPR只有低3位有效, 其值不同, 搶佔優先級和子優先級佔用的位數也不同。
在這裏插入圖片描述
爲了簡單起見,一般將所有的中斷優先級位都配置爲搶佔優先級,比如 I.MX6U 的優先級位數爲 5(32 個優先級), 所以可以設置 Binary point 爲 2, 表示 5 個優先級位全部爲搶佔優先級。

4.3 優先級設置

前面已經設置好了 I.MX6U 一共有 32 個搶佔優先級,數字越小優先級越高。具體要使用某個中斷的時候就可以設置其優先級爲 0~31。某個中斷 ID 的中斷優先級設置由寄存器D_IPRIORITYR 來完成,前面說了 Cortex-A7 使用了 512 箇中斷 ID,每個中斷 ID 配有一個優先級寄存器,所以一共有 512 個 D_IPRIORITYR 寄存器。如果優先級個數爲 32 的話,使用寄存器 D_IPRIORITYR 的 bit7:4 來設置優先級,也就是說實際的優先級要左移 3 位。比如要設置ID40 中斷的優先級爲 5,示例代碼如下:

GICD_IPRIORITYR[40] = 5 << 3;

五,core_ca7.h

core_ca7.h中關於中斷主要有10個函數:

個人理解(如有錯誤,還望留言指正)

I.MX6U 有很多中斷,這裏主要說的是IRQ總中斷,串口中斷啥的都在裏面,有中斷就有中斷源,中斷源由中斷ID配置。GID邏輯分塊是配置中斷模式和中斷優先級的,而中斷模式地址是由 CP15 協處理器獲得。
設置 GICC_PMR,配置優先級個數, I.MX6U 支持 32 級優先級。
設置搶佔優先級和子優先級位數,將所有的位數都設置爲搶佔優先級。
設置指定中斷 ID 的優先級,也就是設置外設優先級。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章