ARM remap与重定位
转载:http://www.voidcn.com/article/p-njvnayef-gg.html
(一)关于ARM处理器Remap的理解 对重定位我的理解: 关于重定位,基于NOR?BOOT的情况下,需计算出代码搬移后的偏移量,需要将全局变量地址加上这个偏移量,全局变量又分初始化的和未初始化的全局变量,RO,RW,BSS (二)如何正确使用ads(axd)? (三)基于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,r2 subr0,r0,r1;将r0指向RO段的结束,即RW段的开始 ldrr1,BaSEOfBSS Idrr2,BaSEOfZero Addr1,3 Addr2,r3 1;基于局部标号的相对跳转,PC+偏移地址,产生与位置无关的代码 cmpr1,r2 ldrccr4,[r0],#4 strccr4,[r1],#4 bcc%B1 ;接着把ZI段搬移到RAM中,并其将初始化为0 movr0,#0 Idrr2,EndOfBSS Addr2,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!,lr} SUBSpc,lr,#4 … 在如上的结构中,不管系统是否进行了地址的重映射,异常中断向量都可以在运行时动态改变,大大提高了中断处理中的灵活性。中断向量可以在运行时指向不同的异常处理代码入口。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |