【嵌入式開發】ARM 異常向量表 ( 異常概念 | 異常處理流程 | 異常向量 | 匯編代碼 )

      網友投稿 1936 2025-04-01

      一. 異常向量表

      1. 異常相關概念

      (1) 異常

      (2) 異常類型簡介

      2. 異常處理

      (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.完整匯編代碼示例 :

      @**************************** @File:start.S @ @異常處理框架 @**************************** .text @ 宏 指明代碼段 .global _start @ 偽指令聲明全局開始符號 _start: @ 程序入口標志 b reset @ reset 復位異常 ldr pc, _undefined_instruction @ 未定義異常, 將 _undefined_instruction 值裝載到 pc 指針中 ldr pc, _software_interrupt @ 軟中斷異常 ldr pc, _prefetch_abort @ 預取指令異常 ldr pc, _data_abort @ 數據讀取異常 ldr pc, _not_used @ 占用 0x00000014 地址 ldr pc, _irq @ 普通中斷異常 ldr pc, _fiq @ 軟中斷異常 _undefined_instruction: .word undefined_instruction @ _undefined_instruction 標號存放了一個值, 該值是 32 位地址 undefined_instruction, undefined_instruction 是一個地址 _software_interrupt: .word software_interrupt @ 軟中斷異常 _prefetch_abort: .word prefetch_abort @ 預取指令異常 處理 _data_abort: .word data_abort @ 數據讀取異常 _not_used: .word not_used @ 空位處理 _irq: .word irq @ 普通中斷處理 _fiq: .word fiq @ 快速中斷處理 undefined_instruction: @ undefined_instruction 地址存放要執行的內容 nop software_interrupt: @ software_interrupt 地址存放要執行的內容 nop prefetch_abort: @ prefetch_abort 地址存放要執行的內容 nop data_abort: @ data_abort 地址存放要執行的內容 nop not_used: @ not_used 地址存放要執行的內容 nop irq: @ irq 地址存放要執行的內容 nop fiq: @ fiq 地址存放要執行的內容 nop reset: @ reset 地址存放要執行的內容 nop

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      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.代碼示例 :

      OUTPUT_ARCH(arm) /*指明處理器結構*/ ENTRY(_start) /*指明程序入口 在 _start 標號處*/ SECTIONS { . = 0x50008000; /*整個程序鏈接的起始位置, 根據開發板確定, 不同開發板地址不一致*/ . = ALIGN(4); /*對齊處理, 每段開始之前進行 4 字節對齊*/ .text : /*代碼段*/ { start.o (.text) /*start.S 轉化來的代碼段*/ *(.text) /*其它代碼段*/ } . = ALIGN(4); /*對齊處理, 每段開始之前進行 4 字節對齊*/ .data : /*數據段*/ { *(.data) } . = ALIGN(4); /*對齊處理, 每段開始之前進行 4 字節對齊*/ bss_start = .; /*記錄 bss 段起始位置*/ .bss : /*bss 段*/ { *(.bss) } bss_end = .; /*記錄 bss 段結束位置*/ }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      【嵌入式開發】ARM 異常向量表 ( 異常概念 | 異常處理流程 | 異常向量 | 匯編代碼 )

      18

      19

      20

      21

      22

      23

      24

      25

      26

      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 文件內容 :

      all: start.o #依賴于 start.o arm-linux-ld -Tgboot.lds -o gboot.elf $^ #使用鏈接器腳本, 將 start.o 轉為 gboot.elf arm-linux-objcopy -O binary gboot.elf gboot.bin #將 gboot.elf 轉化為可以直接在板子上執行的 gboot.bin 文件 %.o : %.S #通用規則, 如 start.o 是由 start.S 編譯來的, -c 是只編譯不鏈接 arm-linux-gcc -g -c $^ %.o : %.c #通用規則, 如 start.o 是由 start.c 編譯來的, -c 是只編譯不鏈接 arm-linux-gcc -g -c $^ .PHONY: clean clean: #清除編譯信息 rm *.o *.elf *.bin

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      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 嵌入式 匯編語言

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:如何用WPS排版
      下一篇:excel錯誤提示怎么關閉
      相關文章
      亚洲A∨无码一区二区三区| 亚洲一区无码精品色| 亚洲国产成人高清在线观看| 亚洲国产精品视频| 国产成人高清亚洲一区91| 日韩亚洲翔田千里在线| 亚洲高清一区二区三区电影| 亚洲欧美成人av在线观看| 亚洲欧美日韩综合久久久久| 亚洲中文字幕无码mv| 亚洲熟妇无码AV| 亚洲国产欧美日韩精品一区二区三区 | 亚洲国产综合专区电影在线 | 亚洲久悠悠色悠在线播放| 国产成人亚洲精品| 亚洲日韩国产二区无码| 亚洲精品又粗又大又爽A片| 青草久久精品亚洲综合专区| 亚洲国产成人精品无码久久久久久综合| 亚洲AV无码乱码在线观看性色扶| www.亚洲色图.com| 久久亚洲精品无码播放| 国产亚洲成归v人片在线观看| 亚洲日韩aⅴ在线视频| 久久久久亚洲AV成人无码 | 精品国产日韩亚洲一区91| 亚洲v国产v天堂a无码久久| 国产亚洲精品a在线观看 | 亚洲线精品一区二区三区影音先锋 | 国产aⅴ无码专区亚洲av| 亚洲国产精品国自产电影| 亚洲理论在线观看| 久久亚洲国产成人影院| 国产成人精品久久亚洲高清不卡| 亚洲av日韩av欧v在线天堂| 国产亚洲日韩一区二区三区| 国产亚洲一区二区三区在线观看| 亚洲一区精品中文字幕| 亚洲三级视频在线| 亚洲av第一网站久章草| 2048亚洲精品国产|