文章目錄
示例代碼下載
1.兩種流程處理
- 1.查詢方式
- 特點:簡單、但佔用較多資源
- 2.中斷方式
- 特點:負責、但佔用資源少
- 常見的中斷有(中斷也是異常的一種):
- 按鍵(外部中斷)、定時器中斷、網絡數據
- 常見的異常有
- 指令異常、數據訪問出錯、Reset
2.中斷處理過程
2.1 硬件初始化
- 設置中斷源
- 設置中斷控制器(屏蔽、優先級)
- 設置CPU總開關(使能中斷)
2.2 執行程序
2.3 產生中斷
- eg:
- CPU每執行完一條指令,都會檢查有誤異常(中斷)產生
- 發現異常(中斷)產生,開始處理
- 對於不同的異常,會跳去不同的地址(異常向量)執行程序
- 這些地址上,只是一條跳轉指令(跳去執行其他函數)
2.4 執行中斷
- 1.保存現場(各類寄存器)
- 2.中斷處理
- 3.恢復現場
3.ARM的7種模式(Mode)
- 正常模式
- User (usr): The normal ARM program execution state
- 用戶模式(不可以直接進入其他模式)
- System (sys): A privileged user mode for the operating system
- 系統模式
- User (usr): The normal ARM program execution state
-
異常模式
- FIQ (fiq): Designed to support a data transfer or channel process
- 快中斷模式
- IRQ (irq): Used for general-purpose interrupt handling
- 中斷模式
- Supervisor (svc): Protected mode for the operating system
- 管理模式
- Abort mode (abt): Entered after a data or instruction prefetch abort
- 中止模式
- Undefined (und): Entered when an undefined instruction is executed
- 未定義指令模式
- FIQ (fiq): Designed to support a data transfer or channel process
-
除了用戶模式以外的6中模式 成爲特權模式(Privileged Mode),可以編程操作
CPSR
(當前程序狀態寄存器)直接進入其他模式 -
不同模式是爲了更好的應對所對應的異常(差別在於:寄存器的資源)
banker register 爲備份寄存器,可以成爲專屬寄存器,R13(SP棧指針)、R14(LR返回地址)
SPSR(保存程序狀態寄存器):用來保存“被中斷模式的CPSR”,相當於CPSR的備份寄存器,eg:當正處於User Mode
,發生中斷,進入IRQ Mode
,SPSR_irq就保存了User Mode那一時刻的CPSR
3.1 異常向量表
4.ARM的2種狀態(State)
-
ARM State:
- 使用ARM指令集,佔據4個字節
-
Thumb State:
- 使用Thumb指令集,佔據2個字節
-
M0~M4:模式位 Mode bit (7種模式)
-
T:狀態位 State bits(ARM or Thumb)
5.異常的處理流程
5.1 進入異常
- 進入異常時的動作(硬件部分實現)
- 1.異常模式下的LR存放 [被中斷模式的下一條指令的地址](PC+4/PC+8)
- 2.異常模式下的SPSR = CPSR
- 3.修改CPSR的[M4~M0],進入異常模式
- 4.跳到向量表
5.2 退出異常
- 退出異常時的動作(硬件部分實現)
- 1.PC = 異常模式下的LR - Offest(offest根據下表來確定)\
- 2.CPSR = 異常模式下的SPSR(恢復CPSR)
- 3.清除中斷標誌位
6.程序以thumb指令集運行
6.1 gcc以thumb編譯
- thumb指令集編譯、使得代碼以thunb狀態運行,在makefile中的gcc編譯加上
-mthunb
arm-linux-gcc -mthumb -c -o $@ $<
6.2 如何從arm切換至thumb
- [x]在start.S中需要使用ARM指令集的用
.code 32
指定,用thumb指令集的用.code 16
指定
- 使用
BX
指令(其是ARM指令系統中的帶狀態切換跳轉指令),BX
命令後面的那個值如果最低位爲1的話,則切換到thumb指令
.code 32
/*..............*/
/* 從ARM State 切換到Thumb State*/
adr r0,thumb_func
add r0,r0,#1 /*bit0 = 1時,bx就會切換CPU狀態至thumb state*/
bx r0
.code 16
thumb_func:
/*..............*/
6.3 注意
- 對於thumb指令,不能向PC直接賦值
- eg:
ldr pc, =main
(這樣不行),需要先把值賦值寄存器,再把寄存器賦值給PC
- eg:
gcc disable built-in memcpy
- 當使用thumb編譯時,gcc會調用memcy,我們可以把變量改成static(存放在data段),這樣就不會讓gcc去調用了