ARM remap與重定位摘抄

(一)關於ARM處理器Remap的理解
0.什麼是Remap
    我的理解是:在ROM從0x0用幾句指令引導系統之後,把RAM映射到0x0就是Remap。
1.Remap的作用
    當ARM處理器上電或者Reset之後,處理器從0x0取指。因此,必須保證系統上電時,0x0處有指令可以執行。所以,上電的時候,0x0地址處必定是ROM或者Flash(NOR)。
    但是,爲了加快啓動的速度,也方便可以更改異常向量表,加快中斷響應速度,往往把異常向量表映射到更快、更寬(32bit/16bit)的RAM中。但是異常向量表的開始地址是由ARM架構決定的,必須位於0x0處,因此,必須把RAM映射到0x0。
2.Remap的配置
    Remap的實現和ARM處理器的實現相關。
    1)如果處理器有專門的寄存器可以完成Remap。那麼Remap是通過Remap寄存器的相應bit置1完成的。如Atmel AT91xx
    2)如果處理器沒有專門的寄存器,但是memory的bank控制寄存器可以用來配置bank的起始地址,那麼只要把RAM的起始地址編程爲0x0,也可以完成remap。如samsung s3c4510
    3)如果上面兩種機制都沒有,那麼Remap就不要做了。因爲處理器實現決定了SDRAM對應的bank地址是不能改變的。如Samsung S3c2410.
3.Remap配置前後要做的工作
    Remap前後,不同之處就是RAM的位置變了。爲了達到Remap的目的,就是加快啓動的速度和異常處理速度,一定要初始化異常堆棧和建立異常向量表的。
4.如果象2410那樣不能Remap的話怎麼辦?
    2410不是不能Remap嗎?爲了加快啓動速度,可以這樣做
    1)使用它的NAND boot模式。爲什麼NAND boot會比較快,那是因爲2410裏面有塊小石頭——"SteppingStone",一塊 4KB SRAM,它是映射在0x0的。啓動程序會自動被copy到這個石頭裏面。自然異常向量的入口放到這個地方,一樣可以達到比NOR boot快的啓動、異常響應速度。
    2)如果你對NOR Boot情有獨衷,那麼你只好把你的異常向量的入口copy到SDRAM裏面,實現所謂的High Vector

對重定位我的理解:

關於重定位,基於NOR BOOT的情況下,需計算出代碼搬移後的偏移量,需要將全局變量地址加上這個偏移量,全局變量又分初始化的和未初始化的全局變量,RO,RW,BSS

(二)如何正確使用ads(axd) 
1、ads是由arm公司提供的編譯和調試環境,非常好,不容質疑!搞arm開發的人員,不能不用ads,例如要開發一個驅動,首先是在ads中編譯、調試通過,纔會加入操作系統中,這是開發過程。 2、Ads中codewarria是編譯環境,在這個環境中,應正確設置程序工作或調試的地址,這兩個地址不一定同址,每次只能設置一種,除非它們相同。設置是通過菜單項edit->target setting完成的。編譯環境中的這個地址是由鏈結器標記在程序上的(暫且這樣說吧,因爲這部分實際涉及的是編譯原理中的鏈接定位問題,它主要涉及的是程序中的跳轉地址,這是與軟件相關的)。這兩個地址都必須與硬件地址配合,程序才能正常工作。因爲mcu(arm)是硬件尋址的,比如4510在正常初始化後,flash被定位在0x0地址,這時如果mcu有一條指令是跳轉到0x0地址,那麼mcu一定會將PC指向flash的0x0地址,mcu卻是由軟件控制的。如果這時remap了,flash被定位在0x1000000地址,但寫在flash中的程序仍然控制mcu跳轉到0x0地址,那麼PC就指向了sdram的0x0地址,那裏寫着什麼是你的事情了。 
3、工作地址是指編譯好的程序(一般是*.bin文件)寫入flash的地址,如軟件程序工作地址從0x0開始,flash也應該定位在0x0地址開始,軟件與硬件地址要相同,才能正常工作。當然,如果做remap,把程序拷貝到新的0x0地址處,也就是sdram中,程序也可以正常工作的。 
4、如果用axd調試,則是另外一種情況:程序必須寫在sdram中,而不是flash中。Sdram的地址在那裏呢?4510上電後,一般設置在0x1000000,而把flash設置在0x0地址。如果codewarria編譯時把程序設置在0x0地址,調試時就會把軟件加載在一個“虛”位置,這個位置(地址)是flash的地址,mcu是無法把程序寫入flash中,程序就成爲空中飄蕩的幽靈,這時如果用反彙編,可以看到有些內容已經變質了,不是你的程序了,明白是爲什麼嗎?而執行的話,mcu讀取flash中的內容,它們並非你的程序,結果是跑飛了。解決辦法是remap(對4510。如是44b0,請在codewarria編譯環境中把程序定位在 sdram段,如需中斷,請在flash中0x0地址先寫入相關中斷向量,並跳轉到sdram中),把sdram設置在0x0地址,再加載程序。 5、Remap時,請用axd中的命令行方式,程序是實現不了的。即:system view->command line interface。只有先把硬件地址設置的與程序相同了、程序段可以被裝入sdram中時,纔可加載程序。 
6、切記這兩點:調試程序一定要放在sdram中、sdram地址與程序地址一定要相同。 
7、0x8000這個地址是怎麼來的呢?原來:0x0地址是中斷向量地址,這要佔用幾十個字節,有些操作系統利用中斷向量之後、0x8000地址之前的部分做點事情,Linux就是其一。所以,編程人員默認的把0x8000這個地址作爲一般程序的開始地址。調試程序時,可以把程序起始地址定在0x8000,這個地址一定要是sdram覆蓋的地址(我再強調一次吧),mcu執行時,仍然是從0x0開始的,是誰把PC挪到0x8000的,是ads在編譯的時候,連接器加進的代碼實現的。如果不是調試程序,是工作程序,要寫入flash的,程序應該定位在0x0地址,而不是0x8000。 
8、有一本書“ARM應用開發系統祥解--S3C4510B”寫的非常好,我讀過有7、8遍了。但有一點是錯的。書中寫到:“針對本書所介紹的目標板,就可以使用這個默認地址值(0x8000)。”實際上,只要是4510的板子,不做remap,0x8000地址就是flash,是不能加載程序的。 
9、在axd中,注意菜單options->configure processor選項,如果不會用,就把它們都關了。帶中斷的程序和有跳轉到0x0地址的程序執行不了,多是由這項引起的。其實它們非常有用,不提了。 
10、所有我以上提到的,均是有程序重定位和跳轉情況的,象簡單的跑馬燈實驗,不需要中斷、跳轉的,把程序直接定位在高位sdram中,remap也不用做,就可以跑的不錯了。 
11、順便提一下banyan的接口包非常好,支持ads,不用懷疑它。

(三)基於S3C4510B系統的啓動流程及REMAP

1    S3C4510B簡介

S3C4510B,基於以太網,16/32位RISC微處理器。芯片部集成了8KB的Cache/SRAM和Ethernet控制器,片外可擴展ROM、Flash、SDRAM等存儲芯片。

S3C4510B芯片內部沒有程序存儲器,所有程序都被存儲在片外擴展的ROM和Flash中。開始啓動時,存有啓動代碼的ROM或Flash將被映射爲0x00地址,系統從此開始運行。但在實際應用中,爲提高系統的實時性,加快代碼的執行速度,系統啓動後程序往往要被搬移到RAM中,因爲RAM的存取速度要比ROM快得多,這樣大大提升系統的性能。由於S3C4510B芯片中的異常中斷入口地址被固定在0x00開始的8個字中,系統只能將地址空間重新分配,把RAM映射到0x00地址處,這正是Remap的原因所在。

S3C4510B內部有幾個特殊寄存器,用於實現地址空間和芯片內外存儲介質的映射。這幾個寄存器的簡介如下:

SYSCFG:設置特殊寄存器的起始地址和片內SRAM的起始地址。

EXTDBWTH:設置各Bank寄存器所映射芯片的數據線寬度。

ROMCON0~ROMCON5:設置系統內片擴展ROM和Flash的起始和終止地址。

DRAMCON0~DRAMCON3:設置系統內片外擴展RAM的起始和終止地址。

S3C4510B芯片內特殊寄存器段的物理地址爲0x3ff0000,各特殊寄存器的偏移地址詳見S3C4510B的技術手冊。

2S3C4510B系統中Remap的實現

地址空間的重新分配,與處理器的硬件結構緊密相關。總體來說,32位系統中的地址重映射機制可以分爲兩種情況:一類是處理器內部專門的寄存器可以完成Remap,這樣只需將Remap寄存器的相應位置1,由硬件邏輯來完成地址的重新映射,如AtmelAT91xx系列;另一類沒有專門的Remap控制寄存器,需要重新改寫處理器內部用於控制Memory起止地址的Bank寄存器,來實現Remap過程。S3C4510B屬於第二種情況。

2.1硬件系統結構及地址分配

假設系統是以Samsung公司給出的測試板爲參考建立的,其中ROM的容量爲512KB,8位數據總線,Remap前的地址範圍爲0x0000000~0x0100000,Remap後的地址範圍爲0x1000000~0x1100000;RAM的容量爲16MB,32位數據總線,Remap前的地址範圍爲0x0100000~0x100000,Remap後的地址範圍爲0x0000000~0x1000000;Flash的容量爲2MB,16位數據總線,Remap前後地址不變,均爲0x1100000~0x1300000。Remap前後的地址映射關係如圖2所示。

2.2系統啓動過程及Remap實現

系統的地址重映射應該在系統的啓動中完成,以下是S3C4510B的Remap啓動過程。

①系統特殊寄存器的設置。主要是配置如上所述的用於實現地址空間和芯片內外存儲介質映射的寄存器,在本系統中配置如下:

SYSCFG=0x87ffff90

EXTDBWTH=0x3001

ROMCON0=0x01000060

ROMCON1=0x13044060

DRAMCON0=0x11004060

②初始化系統堆棧。在ARM7的體系結構中共有七種工作模式,不同的模式有不同堆棧指針,互不干擾。各模式對應於不同異常中斷,至於哪些模式的堆棧需要初始化取決於用戶使用了哪些中斷,以及系統需要處理些異常類型。一般來說,管理者(SVC)堆棧必須設置,如果使用了IRQ中斷,則IRQ堆棧也必須設置。有一點需要注意的是,爲保證Remap後程序運行正常,所有堆棧應設置在RAM的高端地址中。

③初始化I/O口、UART、定時器、中斷控制器以及系統中所用到的其它資源。在初始化異常向量表或修改異常向量表中的入口地址前,要關掉所有中斷。

   ④異常向量表的初始化。將民常中煌怛處理程序的入口地址寫入RAM中相應的異常向量。必須保證的是,異常向量表絕對不會被從ROM搬移到RAM中的代碼和數據所覆蓋,爲此,異常向量表一般被定義在RAM中的高端地址中。

⑤程序代碼及數據的搬移。Remap後,RAM被映射到0x0000的地址空間,ROM則被移到高端地址上。爲保證Remap後程序能夠瞠運行,ROM中的代碼和數據必須地址不變地被移到RAM中。這是Remap成功的關鍵。兩種途徑可以實現搬移。

一種是不管實際的代碼空間有多大,直接將ROM地址空間整個搬移到RAM中。當然,這種方法並不適合在真正的啓動代碼中使用,但在做初步的Remap測試時,可以用來檢驗堆棧及異常中斷的設置是否合理。

另一種方法較複雜,它使用了SDT鏈接器ARMLink產生的定位信息,僅把RO風吹草動的有效代碼和數據段到RAM中。ARMLink將編譯後的程序鏈接成ELF文件。映像文件內部共有三種輸出段:RO段、RW段和ZI段。這三種輸出段分別包含了只讀代碼及包含在代碼段中的少量數據、可讀寫的數據、初始化爲0的數據,ARMLink同時還產生了這三種輸出段的起始和終止定位信息:Image$$RO$$Base、Image$$RO$$Limit、Image$$RW$$Base、Image$$Limit、Image$$Linit和Image$$ZI$$Limit。可以在程序中使用這些定位信息。將ROM中的代碼和數據搬移到RAM中,其實現代碼如下:

數據定義:

BaseOfROMDCD|Image$$RO$$Base|

TopOfROMDCD|Image$$RO$$Limit|

BaseOfBSSDCD|Image$$RW$$Base|

BaseOfZeroDCD|Image$$ZI$$Base|

EndOfBSSDCD|Image$$ZI$$Limit|

源程序:

;將ROM中的程序搬移到RAM中,重映射後的地址不變

adrr0,ResetEntry;ROM中程序起始地址

movr3,#(RamBaseAddr<<16);RamBaseAddr=0x100

Idrr1,BaseOfROM

Idrr2,TopOfROM

Addr1,r1,r3

Addr2,r2,r3

0

Idmiar0!,{r4-r11}

Stmiar1!,{r4-r11}

Cmpr1,r2

Bcc%B0

;將RW段中預初始化的變量搬移到RAM中

subr1,r1,r2

subr0,r0,r1;將r0指向RO段的結束,即RW段的開始

ldrr1,BaseOfBSS

Idrr2,BaseOfZero

Addr1,r1,3

Addr2,r2,r3

1;基於局部標號的相對跳轉,PC+偏移地址,產生與位置無關的代碼

cmpr1,r2

ldrccr4,[r0],#4

strccr4,[r1],#4

bcc%B1

;接着把ZI段搬移到RAM中,並其將初始化爲0

movr0,#0

Idrr2,EndOfBSS

Addr2,r2,r3

2

cmpr1,2

strccr0,[r1],#4

bcc%B2

⑥地址的重新映射。S3C4510B中的Remap過程其實很簡單,只需重新設置ROMCON0~ROMCON5和DRAMCON0~DRAMCON3。在本系統中只需重新設置ROMCON0和DRAMCON0。

源代碼:

;/*內存控制寄存器重新設置-存儲空間重新映射地址空間*/

EXPORTRemapMemory

RemapMemory

movr12,r14

adrr0,RemapMem

ldmiar0,{r1-r11}

ldrr0,=ROMCON0;ROMCON0爲Bank寄存器的起始地址

stmiar0,{r1-r11}

blExceptionTalbeInit;中斷向量表重新初始化

movpc,r12

RemapMem

DCD&11040060;/*ROMCON00x1000000~0x1100000*/

DCD&10000398;/*DRACON00x0~0x1000000*/

⑦進入C代碼空間,開始主程序的運行。此時代碼應該運行於RAM中。

   上面的步驟可以根據實際需要進行適當的添加或刪節。值得注意的是:彙編生成的代碼應該是與位置無關的代碼,即代碼在運行期間可以被映射到不同的地址空間,其中的跳轉指令都是基於PC寄存器的相對跳轉指令。基於PC的標號是位於目標指令前或者程序中數據定義僞操作前的標號,這種符號在彙編時將被處理成PC值加上或減去一個數字常量。

3異常中斷的處理

在Remap的啓動代碼中,需要特別注意的是異常中斷的處理。在S3C4510B中,異常中斷的入口地址是固定的,按表1次序排列。

表1

異常類型 工作模式 正常地址 復位 管理 0x00000000 未定義指令 未定義 0x00000004 軟件中斷(SWI) 管理 0x00000008 預取中止 中止 0x0000000 數據中止 中止 0x00000010 預留 - 0x00000014 IRQ(中斷) IRQ 0x00000018 FIQ(快速中斷) FIQ 0x0000001 地址重新映射之後,入口地址被映射到RAM中,中斷處理代碼也被搬移到RAM地址空是。此時,中斷響應和中斷處理的速度都將大大加快,這將有利於提高整個系統的實時性。異常中斷向量表的設計結構如圖3所示。

下面是各部分的源代碼(以IRQ異常中斷爲例)。

異常向量表的定義:(系統初始化時,將異常處理代碼入口地址寫入異常中的向量表)

_RAM_END_ADDREQU0x01000000;重映射後RAM的終止地址

MAP(_RAM_END_ADDR-0x100)

SYS_RST_VECTOR#4

UDF_INS_VECTOR#4

SWI_SVC_VECTOR#4

INS_ABT_VECTOR#4

DAT_ABT_VECTOR#4

RESERVED_VECTOR#4

IRQ_SVC_VECTOR#4

FIQ_SVC_VECTOR#4

異常初始化代碼:

bIRQ_SVC_HANDLER;0x18

IRQ_SVC_HANDLER

SUBsp,sp,#4;滿遞減堆棧

STMFDsp!,{r0}

LDRr0,=IRQ_SVC_VECTOR;讀取中斷向量,

;IRQ_SVC_VECTOR=SystemrqHandle

LDRr0,[r0]

STRr0,[sp,#4]

LDMFDsp!,{r0,pc};跳轉到異常中斷處理代碼入口

異常處理入口代碼:

SystemIrqHandler

IMPORTISR_IrqHandler

STMFDsp!,{r0-r12,lr}

BLISR_IrqHandler;跳轉到C代碼中異常中斷處理程序ISR_IrqHandler

LDMFDsp!,{r0-r12,lr}

SUBSpc,lr,#4

在如上的結構中,不管系統是否進行了地址的重映射,異常中斷向量都可以在運行時動態改變,大大提高了中斷處理中的靈活性。中斷向量可以在運行時指向不同的異常處理代碼入口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章