現在的位置: 首頁 > 綜合 > 正文

關於arm處理器remap的理解和實現[轉]

2018年03月16日 ⁄ 綜合 ⁄ 共 6459字 ⁄ 字型大小 評論關閉

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
   存儲器地址重映射是當前很多先進控制器所具有的功能。在上一節中已經提
到了0 地址處存儲器重映射的例子,簡而言之,地址重映射就是可以通過軟體配
置來改變一塊存儲器物理地址的一種機制或方法。
當一段程序對運行自己的存儲器進行重映射的時候,需要特別注意保證程序
執行流程在重映射前後的承接關係。下面是一種典型的存儲器地址重映射情況:


系統上電後的預設狀態是0 地址上放有ROM,這塊ROM 有兩個地址:從0
起始和從0x10000 起始,裡面存儲了初始化代碼。當進行地址remap 以後,從0
起始的地址被定向到了RAM 上,ROM 則只保留有唯一的從0x10000 起始的地
址了。
如果存儲在ROM 里的Reset_Handler 一直在0 – 0x4000 的地址上運行,則
當執行完remap 以後,下面的指令將從RAM 里預取,必然會導致程序執行流程
的中斷。根據系統特點,可以用下面的辦法來解決這個問題:
(1) 上電後系統從0 地址開始自動執行,設計跳轉指令在remap 發生前使PC指針指向0x10000 開始的ROM 地址中去,因為不同地址指向的是同一塊ROM,所以程序能夠順利執行。
(2) 這時候0 - 0x4000 的地址空間空閑,不被程序引用,執行remap 後把RAM
引進。因為程序一直在0x10000 起始的ROM 空間里運行,remap 對運行流程沒有任何影響。
(3) 通過在ROM 里運行的程序,對RAM 進行相應的代碼和數據拷貝,完成應用程序運行的初始化。
下面是一段實現上述步驟的常式:

ENTRY
;啟動時,從0 開始,設法跳轉到「真」的ROM 地址(0x10000 開始的空間里)
LDR pc, =start
;insert vector table here

Start ;Begin of Reset_Handler
; 進行remap 設置
LDR r1, =Ctrl_reg ;假定控制remap 的寄存器
LDR r0, [r1]
ORR r0, r0, #Remap_bit ;假定對控制寄存器進行remap 設置
STR r0, [r1]
;接下去可以進行從ROM 到RAM 的代碼和數據拷貝

除此之外,還有另外一種常見的remap 方式,如下圖:

原來RAM 和ROM 各有自己的地址,進行重映射以後RAM 和ROM 的地址
都發生了變化,這種情況下,可以採用以下的方案:
(1) 上電後,從0 地址的ROM 開始往下執行。
(2) 根據映射前的地址,對RAM 進行必要的代碼和數據拷貝。
(3) 拷貝完成後,進行remap 操作。
(4) 因為RAM 在remap 前準備好了內容,使得PC 指針能繼續在RAM 里取
到正確的指令。
不同的系統可能會有多種靈活的remap 方案,根據上面提到的兩個例子,可以總結出最根本的考慮是:要使程序指針在remap 以後能繼續往下得到正確的指令。

實例分析:基於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

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

抱歉!評論已關閉.