【嵌入式开发】ARM 异常向量表 ( 异常概念 | 异常处理流程 | 异常向量 | 汇编代码 )
生活随笔
收集整理的這篇文章主要介紹了
【嵌入式开发】ARM 异常向量表 ( 异常概念 | 异常处理流程 | 异常向量 | 汇编代码 )
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
- 一. 異常向量表
- 1. 異常相關概念
- (1) 異常
- (2) 異常類型簡介
- 2. 異常處理
- (1) 異常處理
- 1. 異常相關概念
- 二. 異常向量表代碼編寫
- 1. 初始化異常向量表模塊代碼
- 2. 鏈接器腳本
- 3. Makefile 編譯腳本
- 4. 編譯輸出可執行文件
本博客的參考文章及相關資料下載 :
- 1.ARM 架構參考手冊 ( ARM Architecture Reference Manual ) : https://download.csdn.net/download/han1202012/8324641
- 2.匯編參考手冊 : https://download.csdn.net/download/han1202012/8328375
- 3.本博客代碼下載 : https://download.csdn.net/download/han1202012/10392901
一. 異常向量表
參考手冊 :
- 1.異常向量表手冊位置 : ARM Architecture Reference Manual A2.6 ;
- 2.ARM Architecture Reference Manual 文檔下載地址 : http://download.csdn.net/detail/han1202012/8324641;
1. 異常相關概念
(1) 異常
異常定義 :
- 1.異常簡介 : 由于 內部或者外部的一些事件 , 導致 處理器停下正在處理的工作, 轉而去處理這些發生的事;
- 2.處理器狀態 : 當遇到異常的時候, 先將處理器狀態保存起來, 以便執行完異常處理程序后, 可以恢復處理器狀態, 繼續執行異常出現點下面的代碼;
- 3.異常同時出現 : 在一個時間點 可以出現 多個異常;
- 4.異常向量概念 : 當異常發生的時候, 程序被強行從一個固定的內存地址執行, 每個種類的異常都有對應的一固定內存地址, 這個內存地址就是異常向量 ;
(2) 異常類型簡介
異常類型 : ARM 架構 支持 七種類型的異常,
- 1.Reset : 處理器在工作時, 突然 按下重啟鍵, 就會觸發該異常;
- 2.Undefined instructions : 處理器無法識別指令的異常, 處理器執行的指令是有規范的, 如果 嘗試執行 不符合要求的指令, 就會進入到該異常指令對應的地址中;
- 3.Software interrupt (SWI) : 軟中斷, 軟件中需要去打斷處理器工作, 可以使用軟中斷來執行 ;
- 4.Prefetch Abort (instruction fetch memory abort) : 預取指令失敗, ARM 在執行指令的過程中, 要先去預取指令準備執行, 如果預取指令失敗, 就會產生該異常;
- 5.Data Abort (data access memory abort) : 讀取數據失敗;
- 6.IRQ (interrupt) : 普通中斷;
- 7.FIQ (fast interrupt) : 快速中斷, 快速中斷要比普通中斷響應速度要快一些;
2. 異常處理
(1) 異常處理
異常處理簡介 :
- 1.異常向量工作機制 : 異常發生時, ARM 處理器會跳轉到對應該異常的 固定地址 去執行異常處理程序, 這個 固定的地址 就是異常向量;
- 2.默認地址 和 高位地址 : 每個中斷類型對應兩個異常向量, 默認是 Normal address, 如果經過配置, 配置使用高位的異常向量, 就會使用 High vector address 異常向量; 使用 普通 向量 還是 高位向量, 可以使用 CP15 協處理器進行配置;
- 3.異常 與 地址 一一對應 : 每個異常都對應著一個地址, 出現指定類型的異常時, 就會跳轉到該異常對應的地址執行異常處理程序;
- 4.注意異常向量斷點 ( 保留位 ) : 普通向量 ( Normal Vector ) 地址 0x00000014 和 高位向量 ( High Vector ) 地址 0xFFFF0014 暫時沒有使用, 為今后的擴展保留;
二. 異常向量表代碼編寫
1. 初始化異常向量表模塊代碼
Start.S 匯編程序解析 :
- 1.匯編參考文章 : https://blog.csdn.net/shulianghan/article/details/42408137 ;
- 2.匯編參考手冊下載地址 : https://download.csdn.net/download/han1202012/8328375
- 3.指明匯編代碼段 : 使用 .text 宏 指明匯編代碼段;
- 4.標明程序入口標號 : 先使用 .global _start 將 _start 聲明成全局符號; 使用 _start: 標明程序的入口標號是 _start;
5.定義標號( 類似于函數名 ) : 定義自定義標號, 格式 標號:, 例如 irq:;
- ( 1 ) 定義標號執行的指令 : 標號下面定義要執行的指令, 如果想要執行標號下面的指令, 直接跳轉到對應標號即可;
- ( 2 ) 異常執行的代碼內容 : 在下面代碼的 27 ~ 49 行就是定義了 7 個異常執行操作的 標號 以及要執行的指令 nop; 這些都是異常發生的時候要處理的代碼;
- ( 3 ) 代碼示例 : 下面代碼定義了一個 irq 標號, 跳轉到該標號即開始執行標號下的代碼 nop, irq : nop;
6.空操作 : 如果在某個位置執行指令, 不想做任何操作, 可以使用 nop 表示 什么操作都不執行;
7.定義標號 ( 類似于變量 ) : 定義一個標號, 在標號中存放 32 位的值, 定義格式 標號: .word 存儲值的內容;
- ( 1 ) 示例 : _irq: .word irq, 定義 _irq 標號, .word 表示該標號存儲的是 32 位值, 這個值的大小就是 irq 地址;
8.分支指令 : 當異常發生的時候, 需要跳轉到對應的異常處理指令中;
- ( 1 ) 分支指令語法格式 : b{條件} 地址, 如果①滿足條件, 就跳轉到 地址 位置, 如果②不滿足條件, 就執行下面的語句, ③如果沒有條件, 就是 100% 執行;
- ( 2 ) 代碼示例 : b reset, 異常發生時, 直接跳轉到 reset 標號處執行代碼;
9.裝載指令 :
- ( 1 ) 裝載指令語法格式 : ldr 寄存器, 地址, 將 地址 中存放的數據 裝載 到 寄存器中;
- ( 2 ) 代碼示例 :
- a.定義標號 ( 函數 ) : 定義要執行的指令的標號 irq , 即跳轉到該標號處, 就開始執行標號下面的指令, irq : nop ;
- b.定義標號 ( 變量 ) : 定義一個標號 _irq , 用于存放一個 32 位的值, 這里用于存放 上面 定義的標號 地址, _irq .word irq
- c.裝載地址到 pc 寄存器 : ldr pc, _irq, 將 _irq 標號中存放的值, 這個值是 irq 標號的地址, 就是跳轉到該地址去執行指令;
- 10.完整匯編代碼示例 :
2. 鏈接器腳本
gboot.lds 鏈接器腳本 代碼解析 :
- 1.指明輸出格式 ( 處理器架構 ) : 使用 OUTPUT_ARCH(架構名稱) 指明輸出格式, 即處理器的架構, 這里是 arm 架構的, OUTPUT_ARCH(arm) ;
- 2.指明輸出程序的入口 : 設置編譯輸出的程序入口位置, 語法為 ENTRY(入口位置), 在上面的 Start.S 中設置的程序入口是 _start, 代碼為 ENTRY(_start) ;
- 3.設置代碼段 : 使用 .text : 設置代碼段;
- 4.設置數據段 : 使用 .data : 設置數據段;
- 5.設置 BSS 段 : 使用 .bss : 設置 BSS 段;
- ( 1 ) 記錄 BSS 段的起始地址 : bss_start = .; ;
- ( 2 ) 記錄 BSS 段的結束地址 : bss_end = .; ;
- 6.對齊 : 每個段都需要設置內存的對齊格式, 使用 . = ALIGN(4); 設置四字節對齊即可;
- 7.代碼示例 :
3. Makefile 編譯腳本
makefile 文件編寫 :
- 1.通用規則 ( 匯編文件編譯規則 ) : 匯編文件 編譯 成同名的 .o 文件, 文件名稱相同, 后綴不同, %.o : %.S, 產生過程是 arm-linux-gcc -g -c $^ , 其中 ^ 標識是所有的依賴文件, 在該規則下 start.S 會被變異成 start.o ;
- 2.通用規則 ( C 文件編譯規則 ) : C 代碼編譯成同名的 .o 文件, %.o : %.c , 產生過程是 arm-linux-gcc -g -c $^ ;
- 3.設置最終目標 : 使用 all: 設置最終編譯目標;
- ( 1 ) 依賴文件 : 產生最終目標需要依賴 start.o 文件, 使用 all: start.o 表示最終目標需要依賴該文件;
- ( 2 ) 鏈接過程 : arm-linux-ld -Tgboot.lds -o gboot.elf $^, 需要使用鏈接器腳本進行連接, ①鏈接工具是 arm-linux-ld 工具, ②使用 -Tgboot.lds 設置鏈接器腳本 是剛寫的 gboot.lds 鏈接器腳本, ③輸出文件是 gboot.elf 這是個中間文件, ④ 依賴文件是 $^ 代表所有的依賴;
- ( 3 ) 轉換成可執行二進制文件 : arm-linux-objcopy -O binary gboot.elf gboot.bin, 使用 -O binary 設置輸出二進制文件, 依賴文件是 gboot.elf, 輸出的可執行二進制文件 即 結果是 gboot.bin ;
- 4.makefile 文件內容 :
4. 編譯輸出可執行文件
編譯過程 :
- 1.文件準備 : 將 匯編代碼 ( start.S ) 鏈接器腳本 ( gboot.lds ) makefile 文件 拷貝到編譯目錄 ;
- 2.執行編譯命令 : make ;
- 3.編譯結果 : 可以看到 生成了 編譯目標文件 start.o, 鏈接文件 gboot.elf, 可執行的二進制文件 gboot.bin ;
本博客的參考文章及相關資料下載 :
- 1.ARM 架構參考手冊 ( ARM Architecture Reference Manual ) : https://download.csdn.net/download/han1202012/8324641
- 2.匯編參考手冊 : https://download.csdn.net/download/han1202012/8328375
- 3.本博客代碼下載 : https://download.csdn.net/download/han1202012/10392901
總結
以上是生活随笔為你收集整理的【嵌入式开发】ARM 异常向量表 ( 异常概念 | 异常处理流程 | 异常向量 | 汇编代码 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【 Markdown 】Markdown
- 下一篇: 【嵌入式开发】 ARM 关闭 MMU (