亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ARM的啟動代碼(3):異常向量

發布時間:2020-07-28 02:45:12 來源:網絡 閱讀:563 作者:coolbacon 欄目:開發技術


ARM的啟動代碼是非常重要的代碼,直接關系到系統的穩定性和可靠性(這里主要討論arm7, arm9cortex系列的會在后續的文章中討論)。上次我們通過兩則文章討論了ARM啟動代碼的過程,

ARM的啟動代碼(1):介紹

ARM的啟動代碼(2):AT91SAM9260啟動詳解



這次我們聊聊ARM的代碼的具體編寫。那么什么樣的代碼會涉及到這些問題呢?

1.Bootloader或者位于啟動序列上進行加載其他應用程序的程序;

2.單獨的二進制鏡像,直接可以在ARM處理器上直接執行。


這兩種代碼都需要對 ARM 的啟動過程有深入理解。說深入理解,其實只有一條,鬧鬧記住,ARM7,ARM9的異常向量表從地址0開始。這是鐵打不能改變的事實。這樣一來,所有的程序都要用0地址存儲自己的向量表,這豈不是成了稀缺資源。所以不同家的ARM芯片都提供了一些辦法解決這種問題。


對于arm7,很多芯片使用片內的flash。如at91sam7x256。為了方便,經常需要bootloader + 應用程序的方式。At91sam7x256提供了一個叫boot Memory的地址,1Mbytes, 0x0~0x000F FFFF。可以映射成為內部的Flash和內部的SRAM。這個映射是:

Boot Memory: 0x0~0x000F FFFF, 1Mbytes

Internal Flash: 0x0010 0000~0x001F FFFF, 1Mbytes

Internal SRAM:0x0020 0000~0x002F FFFF, 1Mbytes

Boot Memory映射成Internal Flashflash的地址仍然從0x0010 0000開始,但是從0x0訪問,等同于訪問0x0010 0000;當映射成為 Internal SRAMSRAM地址不變,訪問0x0地址,等同于訪問0x0020 0000。其實硬件做起來很簡單,就是將地址線用邏輯電路稍微處理一下。


由于代碼都要存放在FLASH里,否則,沒電以后,啥都沒有了,也無法再次啟動。所以,異常向量要從0x0開始,那么自然也要把向量放在這個位置,7x256上電以后默認boot memory 映射從flash開始。也就是說,把向量放在0x0010 0000即可解決這樣的問題。


0x0010 0000被占用以后,bootloader 的向量問題解決了,那用戶代碼的中斷向量怎么辦呢?不可能把bootloader的向量擦了,把用戶自己的向量寫入,那豈不是bootloader也完了?這里有個小技巧,如果用戶程序從0x0010 1000開始,向量依然從這個位置開始。只不過,在打開中斷,向量真正起作用前,將0x0010 1000這個地方向量復制到SRAM的首地址上,然后切換Boot Memory映射SRAM。那么向量依然從0x0開始。這樣的話,無論多少級boot代碼,都可以完美的解決該問題。


ARM9除了以上的方法,還有個終極的利器,那就是MMU,你高興放哪就放哪,在向量起作用之前,用MMU將其地址變換為0即可。一點技術含量都沒有。


道理總是簡單的,實現起來總是有點點彎彎繞。我們看看實際的實現吧。這是7x256的向量代碼:


__vector:

LDR PC, [PC,#24] ; Absolute jump can reach 4 GByte

LDR PC, [PC,#24] ; Branch to undef_handler

LDR PC, [PC,#24] ; Branch to swi_handler

LDR PC, [PC,#24] ; Branch to prefetch_handler

LDR PC, [PC,#24] ; Branch to data_handler

DC32 0 ; Reserved

LDR PC, [PC,#24]; Branch to irq_handler

LDR PC, [PC,#24]; Branch to fiq_handler



DC32 _program_start

DC32 ARM_ExceptUndefInstrHndlr

DC32 ARM_ExceptSwiHndlr

DC32 ARM_ExceptPrefetchAbortHndlr

DC32 ARM_ExceptDataAbortHndlr

DC32 0

DC32 ARM_ExceptIrqHndlr

DC32 ARM_ExceptFiqHndlr


這里相對比較簡單,對這個指令做一下解釋。LDR PC, [PC,#24]是將當前PC+24的地址的值載入到PC寄存器中。由于ARM流水線的問題,當前執行的指令,地址已經是后面兩條了。所以,是+24并不是+32。也就是把_program_start加載入PC指針里。這段代碼已經消除了指令當前位置對跳轉位置的影響,可以隨意的拷貝到任意的地方去執行。這段代碼放在0x20 0000地方,可以正常執行;放在0x10 0000地方也可以正常執行。


RTEMSARM9(CSB337)啟動向量:

vector_block:

ldr pc, Reset_Handler

ldr pc, Undefined_Handler

ldr pc, SWI_Handler

ldr pc, Prefetch_Handler

ldr pc, Abort_Handler

nop

ldr pc, IRQ_Handler

ldr pc, FIQ_Handler


Reset_Handler: b bsp_reset

Undefined_Handler: b Undefined_Handler

SWI_Handler: b SWI_Handler

Prefetch_Handler: b Prefetch_Handler

Abort_Handler: b Abort_Handler

nop

IRQ_Handler: b IRQ_Handler

FIQ_Handler: b FIQ_Handler

Rtems是個復雜的操作系統,在匯編代碼里安裝的只是一個簡單的復位向量。其它向量都只是簡單的死循環。操作系統運行起來以后,還要再次安裝向量的。向量指向操作系統的復雜的處理函數。但不管這些,向量存儲的地址是沒有改變的。Link腳本上可以看到向量被放在內部的SRAM的首地址上。(CSB337)


SECTIONS

{

.base :

{

_sram_base = .;


/* reserve room for the vectors and function pointers */

arm_exception_table = .;

. += 64;

連接器雖然把位置空出來了,但連接器依然不知道將vector_block放到什么位置。怎么辦?這里的代碼解釋了一切。


/*

* Initialize the MMU. After we return, the MMU is enabled,

* and memory may be remapped. I hope we don't remap this

* memory away.

*/

ldr r0, =mem_map

bl mmu_init


/*

* Initialize the exception vectors. This includes the

* exceptions vectors (0x00000000-0x0000001c), and the

* pointers to the exception handlers (0x00000020-0x0000003c).

*/

mov r0, #0

adr r1, vector_block

ldmia r1!, {r2-r9}

stmia r0!, {r2-r9}

ldmia r1!, {r2-r9}

stmia r0!, {r2-r9}


Gnu的工具鏈并不針對某一個具體的平臺。所以解決方案從某種意義上說,更具有普遍意義。先調用mmu_init,這是干什么,實際上是將MMU初始化,將我們定義的.base地址放到0x0位置去。然后緊接著下面的幾行代碼,是將上面的中斷向量復制到0x0位置去。一共64個字節,實現4GB內的地址絕對跳轉。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

冷水江市| 乐清市| 固原市| 保山市| 山丹县| 同德县| 施秉县| 陆河县| 兴化市| 台南县| 合川市| 巴林左旗| 大洼县| 黔东| 河间市| 永昌县| 兴义市| 鄂伦春自治旗| 颍上县| 泸溪县| 买车| 阜城县| 来凤县| 东乡族自治县| 新邵县| 宝丰县| 合作市| 柯坪县| 那坡县| 东兴市| 苍山县| 抚松县| 扬州市| 双江| 石河子市| 石渠县| 凌海市| 堆龙德庆县| 巴彦淖尔市| 广平县| 天峨县|