在上節課的介紹里,我們引入了異常的概念和處理流程,以及知道中斷也是一種異常。
本節主要學習CPU的7種Mode、2種State和相關的寄存器及異常的處理流程。
1. ARM體系下的COU有 7 種工作模式(Mode):
usr : 用戶模式 -------> ARM處理器正常的程序執行狀態。 sys :系統模式 -------> 用於高速數據傳輸或通道處理。 ----und(Unddefined) :未定義指令中止模式 -------> 當未定義的指令執行時進入該模式,可用於支持硬件協處理器的軟件仿真 這5種 | src (Supervisor) : 管理模式 -------> 操作系統使用的保護模式 屬於 ----| abt (Abort) :數據訪問中止模式 -------> 當數據或指令預取中止時進入該模式,可用於虛擬存儲及存儲保護。 異常 | irq (IRQ) :中斷模式 -------> 用於通用的中斷處理 ----fiq (FIQ) :快速中斷模式 -------> 用於高速數據傳輸或通道處理
1.1 abt(數據訪問中止模式):(該類異常又分為兩類):
a. 指令預取中止:∵ CPU是以流水線方式來執行指令的,即執行當前指令時,同時在解析第二條指令並讀取第三條指令,在讀取第 3 條指令時稱為預取,可能會發生錯誤。
b. 比如 CPU 想要讀寫某個地址,可能這個過程中會出錯
1.2 除 usr 模式外,其他模式均屬於特權模式。
在這 6 種特權模式下,它們可以隨遍切換到其它任何模式。在用戶模式下,不能直接切換到其它模式。
大多數程序運行於用戶模式,進入特權模式是為了處理中斷、異常,或者訪問被保護的系統資源。
其中注意 usr模式 為什么不能直接進入其他模式?
用戶模式在有操作系統的情況下是給應用程序去使用的,寫應用程序的人水平千差萬別,不能保證程序是好是壞,
那么可以讓應用程序運行於 usr模式,限制應用程序的權限,防止它破壞整個系統。
1.3 CPSR (Current Program Status Register) 寄存器: 當前程序狀態寄存器。
CPSR 中一些位被用於標識各種狀態,一些位被用於標識當前處於什么工作模式。
1.4 為什么有那么多異常模式?
發生某些異常時會對應進入某種異常模式,在這種異常模式下,更容易來處理這種異常(更專業☺)。
1.5 每種異常模式下有哪些資源的差別呢?
實際上就是寄存器的差別。寄存器筆記在第3節。
2. 2 種State:
2.1 CPU 工作狀態
ARM state :此時處理器執行 32 位的字對齊的ARM指令。
Thumb state :此時處理器執行的 16 位的半字對齊的Thumb指令。
1 2 eg: 3 |------ ARM : 該指令編譯成 4 Byte機器碼 4 MOV R0, R1 ---| 5 |------ Thumb : 該指令編譯成 2 Byte機器碼 6 7 ===> 使用Thumb指令集,就是為了減小程序使用的空間
韋老師的程序幾乎都是在ARM狀態下運行,而CPU一上電就處於ARM狀態,所以無需關心CPU的工作狀態。
2.2 現在區分一下ARM指令集與Thumb指令集:
Thumb 指令可以看作是ARM指令壓縮形式的子集,是針對代碼密度的問題而提出的,它具有16位的代碼密度但是它不如ARM指令的效率高。
Thumb不是一個完整的體系結構,不能指望處理器只執行Thumb指令而不支持ARM指令集。因此,Thumb指令只需要支持通用功能,必要時可以借助
完善的ARM指令集,比如所有的異常自動進入ARM狀態。在編寫Thumb指令時先要使用偽指令CODE16聲明,而且在ARM指令中要使用BX指令跳轉
到Thumb指令,以切換處理器狀態,編寫ARM指令時,則可以使用偽指令CODE32聲明。
3. 寄存器:
3.1 通用寄存器
a. 畫灰色三角形代表該寄存器是該模式下特有的寄存器,這些寄存器稱為備份寄存器。
b. 每種工作模式有 16 個寄存器 + 1 個/ 2 個 (1個或2個取決於工作模式)程序狀態寄存器。
c. 31個通用寄存器 如下:
1 r0 -- r15 : -----> 16 個寄存器 (其中r0到r7,外加r15, 各個工作模式下都是一樣的) 2 r8_fiq -- r14_fiq : -----> 7 個寄存器 (FIQ快中斷模式獨有) 3 r13_svc-- r14_svc : -----> 2 個寄存器 (svc管理模式獨有) 4 r13_abt-- r14_abt : -----> 2 個寄存器 (abt數據訪問中止模式獨有) 5 r13_irq-- r14_irq : -----> 2 個寄存器 (irq中斷模式獨有) 6 r13_und-- r14_und : -----> 2 個寄存器 (und未定義指令中止模式獨有) 7 16 + 7 + 2 + 2 + 2 + 2 = 31 個通用的32位寄存器 8
eg:假設執行 MOV R0, R8 ,在System&User 模式與FIQ 模式下,R0是同一個寄存器(實際上任何一種模式下,R0都是同一個寄存器),
但在訪問R8時,FIQ模式下訪問的是其專有的 r8_fiq 寄存器。
1 |--- sys: MOV R0, R8 2 MOV R0, R8 ===>| 3 |--- fiq: MOV R0, R8_fiq
d. 5 種模式下至少會有各自的R13 和 R14專屬寄存器。
R13 稱為棧指針寄存器, 通常用於保存棧指針。
R14 稱為程序鏈接寄存器(subroutine Link Register),當執行 BL 子程序調用指令時,R14得到R15(程序計數器PC)中的備份。
而當發生中斷或異常時,對應的R14_svc、R14_irq、R14_fiq、R14_abt、R14_und 保存R15返回值,即保存發生異常時的指令地址,以后返回時,可以返回
R14所指示的地方。
||
|| |--- 保存現場: 保存被中斷模式的寄存器,其中FIQ快中斷模式有多個自己專屬的寄存器,本身就不會占用其他模式的寄存器,
\/ | 所以自然會省下保存其他模式下寄存器的時間,加快處理速度,但在Linux系統中,並不會使用FIQ模式
這里簡單復習一下中斷處理流程 ---| --- 處理 :
| --- 恢復 :
3.2 備份寄存器(banked register)
進入某個工作模式后就使用對應的那組寄存器。r8_fiq -- r14_fiq、r13_svc-- r14_svc、r13_abt-- r14_abt、r13_irq-- r14_irq、r13_und-- r14_und均屬於備份寄存器。
3.3 當前程序狀態寄存器(Current Program Status Register) : CPSR

CPSR中各位意義如下:
(1) T 位: 置位時,CPU處於Thumb狀態;否則處於ARM狀態。
(2) 中斷禁止位:I 位和 F位屬於中斷禁止位。他們被置位時,IRQ中斷,FIQ中斷分別被禁止。
(3) 工作模式位:表明CPU當前處於什么工作模式。可以編寫這些位,使CPU進入指定的工作模式。
(4) 條件標志位:Z 位
1 eg: 2 CMP R0, R1 ; 如果R0 = R1 的話,Zero位置1 3 4 beq xxx ; 這條指令會判斷一下這個寄存器里面的 Z 位,如果這一位等於1的話,它就會跳轉; 若等於0的話,就不跳轉。
3.4 CPSR 的備份寄存器: SPSR(Saved Program States Register)
SPSR(Saved Program States Register):不同模式下,有SPSR_fiq、SPSR_svc、SPSR_abt、SPSR_irq、SPSR_und 5 個不同的寄存器。
每種模式下的SPSR寄存器用來保存被中斷模式下的CPSR的值
4. 異常的處理流程:
4.1 異常發生時,將切換進入相應的工作模式,ARM920t的CPU核硬件自動完成如下操作:
(1) 對於通用寄存器,在異常工作模式的連接寄存器R14(即對應的R14_svc、R14_irq、R14_fiq、R14_abt、R14_und)中保存前一個工作模式的下一條指令地址。
對於ARM狀態,對應連接寄存器保存的值 = 當前PC值 +4 或 +8(參考下表)。

(2) 對於程序狀態寄存器,異常模式的 SPSR = 上個模式的CPSR。
(3) 將CPSR寄存器的工作模式位(M0--M4)設置為這個異常對應的工作模式, 進入異常模式。
(4) 令PC值等於這個異常模式在異常向量表中的地址,即跳轉去執行異常向量表中的相應指令。
打開u-boot\cpu\arm920t 目錄下的start.S,異常向量表如下圖所示:
1 b reset ;復位異常 0x0 2 ldr pc, _undefined_instruction ;未定義的指令異常 0x4 遇到沒有定義的指令 3 ldr pc, _software_interrupt ; 軟件中斷異常 0x8 4 ldr pc, _prefetch_abort ;內存操作異常 0xc 5 ldr pc, _data_abort ; 數據異常 0x10 6 ldr pc, _not_used ; 未使用 0x14 7 ldr pc, _irq ; 中斷IRQ異常 0x18 這里也證明中斷是一種異常 8 ldr pc, _fiq ; 快速中斷FIQ異常 0x1c
4.2 從異常工作模式退出回到之前的工作模式,這需要通過軟件完成如下操作:
(1) 對於通用寄存器,前面進入異常工作模式時,連接寄存器R14中保存了前一工作模式的一個指令地址 ,將它減去一個適當的值(參考上表)后賦給PC寄存器。
即 PC = R14 - 某個值。
(2) 對於程序狀態寄存器,退回的工作模式的CPSR = 異常模式下SPSR的值。
(3) 如果發生的是中斷的話(其他異常模式不用管這一步),清除中斷
