您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 其它办公文档 > ARM的位置在Bootloader中的应用
www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构引言1位置无关代码及程序设计方法1.1基本概念与实现原理1.2arm处理器的位置无关程序设计要点(1)程序设计规范(2)程序设计规范22位置无关代码在Bootloader设计中的应用使用位置无关设计Bootloader程序有如下优点:3结论www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构arm处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运行,其设计方法在嵌入式应用系统开发中具有重要的作用。本文首先介绍位置无关代码的基本概念和实现原理,然后阐述基于arm汇编位置无关的程序设计方法和实现过程,最后以嵌入式Bootloader程序设计为例,介绍位置无关程序设计在Bootloader程序设计中的作用。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构基于位置无关代码PIC(PositionIndependentCode)的程序设计在嵌入式应用系统开发中具有重要的作用,尤其在裸机状态下开发Bootloader程序及进行内核初始化设计;利用位置无关的程序设计方法还可以在具体应用中用于构建高效率动态链接库,因而深入理解和熟练掌握位置无关的程序设计方法,有助于开发人员设计出结构简单、清晰的应用程序。本文首先介绍位置无关代码的基本概念和实现原理,然后阐述基于arm汇编位置无关的程序设计方法和实现过程,最后以Bootloader程序设计为例,介绍了位置无关程序设计在Bootloader程序设计中的作用。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构1.1基本概念与实现原理应用程序必须经过编译、汇编和链接后才变成可执行文件,在链接时,要对所有目标文件进行重定位(relocation),建立符号引用规则,同时为变量、函数等分配运行地址。当程序执行时,系统必须把代码加载到链接时所指定的地址空间,以保证程序在执行过程中对变量、函数等符号的正确引用,使程序正常运行。在具有操作系统的系统中,重定位过程由操作系统自动完成。在设计Bootloader程序时,必须在裸机环境中进行,这时Bootloader映像文件的运行地址必须由程序员设定。通常情况下,将Bootloader程序下载到ROM的0x0地址进行启动,而在大多数应用系统中,为了快速启动,首先将Bootloader程序拷贝到SDRAM中再运行。一般情况下,这两者的地址并不相同,程序在SDRAM中的地址重定位过程必须由程序员完成。实际上,由于Bootloader是系统上电后要执行的第一段程序,Bootloader程序的拷贝和在这之前的所有工作都必须由其自身来完成,而这些指令都是在ROM中执行的。也就是说,这些代码即使不在链接时所指定的运行时地址空间,也可以正确执行。这就是位置无关代码,它是一段加载到任意地址空间都能正常执行的特殊代码。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构◆程序在运行期间动态加载到内存;◆程序在不同场合与不同程序组合后加载到内存(如共享的动态链接库);◆在运行期间不同地址相互之间的映射(如Bootloader程序)。虽然在用GCC编译时,使用-fPIC选项可为C语言产生位置无关代码,但这并不能修正程序设计中固有的位置相关性缺陷。特别是汇编语言代码,必须由程序员遵循一定的程序设计准则,才能保证程序的位置无关性。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构arm程序的位置无关可执行文件PIE(PositionIndependentExecutable)包括位置无关代码PIC和位置无关数据PID(PositionIndependentData)两部分。PID主要针对可读写数据段(.data段),其中保存已赋初值的全局变量。为实现其位置无关性,通常使用寄存器R9作为静态基址寄存器,使其指向该可读写段的首地址,并使用相对于基址寄存器的偏移量来对该段的变量进行寻址。这种方法常用于为可重入程序的多个实例产生多个独立的数据段。在程序设计中,一般不必考虑可读写段的位置无关性,这主要是因为可读写数据主要分配在SDRAM中。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构PIC包括程序中的代码和只读数据(.text段),为保证程序能在ROM和SDRAM空间都能正确运行(如裸机状态下的Bootloader程序),必须采用位置无关代码程序设计。下面重点介绍PIC的程序设计要点。PIC遵循只读段位置无关ROPI(ReadOnlyPositionIndependence)的ATPCS(armThumbProcedureCallStandard)的程序设计规范:www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构引用同一ROPI段或相对位置固定的另一ROPI段中的符号时,必须是基于PC的符号引用,即使用相对于当前PC的偏移量来实现跳转或进行常量访问。①位置无关的程序跳转。在arm汇编程序中,使用相对跳转指令B/BL实现程序跳转。指令中所跳转的目标地址用基于当前PC的偏移量来表示,与链接时分配给地址标号的绝对地址值无关,因而代码可以在任何位置进行跳转,实现位置无关性。另外,还可使用ADR或ADRL伪指令将地址标号值读取到PC中实现程序跳转。这是因为ADR或ADRL等伪指令会被编译器替换为对基于PC的地址值进行操作,但这种方式所能读取的地址范围较小,并且会因地址值是否为字对齐而异。但在arm程序中,使用LDR等指令直接将地址标号值读取到PC中实现程序跳转不是位置无关的。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构例如:LDRPC,=main上面的LDR汇编伪指令编译后的结果为:LDRPC,[PC,OFFSET_TO_LPOOL]LPOOLDCDmain可见,虽然LDR是把基于PC的一个存储单元LPOOL的内容加载到PC中,但该存储单元中保存的却是链接时所决定的main函数入口的绝对地址,所以main函数实际所在的段不是位置无关。②位置无关的常量访问。在应用程序中,经常要读写相关寄存器以完成必要的硬件初始化。为增强程序的可读性,利用EQU伪指令对一些常量进行赋值,但在访问过程中,必须实现位置无关性。下面以PXA270的GPIO初始化介绍位置无关的常量访问方法。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构GPIO_BASEEQU0x40e00000;GPIO基址寄存器地址GPDR0EQU0x00c;相对于GPIO基址寄存器的偏移量init_GPDR0EQU0xfffbfe00;寄存器GPDR0初值LDRR1,=GPIO_BASELDRR0,=init_GPDR0STRR0,[R1,#GPDR0]上述汇编代码段经编译后的结果为:LDRR1,[PC,OFFSET_TO_GPIO_BASE]LDRR0,[PC,OFFSET_TO_init_GPDR0]STRR0,[R1,#0xc]GPIO_BASEDCD0x40e00000GPDR0DCD0x00cinit_GPDR0DCD0xfffbfe00www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构可见,LDR伪指令实际上使用基于PC的偏移量来对符号常量GPIO_BASE和init_GPDR0进行引用,因而是位置无关的。由此可以得出如下结论:使用LDR伪指令将一个常量读取到非PC的其他通用寄存器中可实现位置无关的常量访问;但将一个地址值读取到PC中进行程序跳转时,跳转目标则是位置相关的。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构其他被ROPI段中的代码引用的必须是绝对地址,或者是基于可读写位置无关(RWPI)段的静态基址寄存器的可写数据。使用绝对地址只能引用被重定位到特定位置的代码段中的符号,通过在位置无关代码中引入绝对地址,可以让程序跳转到指定位置。例如,假设Bootloader的阶段1将其自身代码拷贝到链接时所指定的SDRAM地址空间后,当要跳转到阶段2的C程序入口时,可以使用指令“LDRPC,=main”跳转到程序在SDRAM中的main函数入口地址开始执行。这是因为程序在编译链接时给main函数分派绝对地址,系统通过将main函数的绝对地址直接赋给PC实现程序跳转。如果使用相对跳转指令“Bmain”,那么只会跳转到启动ROM内部的main函数入口。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构在使用GNU工具开发Bootloader时,程序在链接时会通过一个链接脚本(linkerscript)来设定映像文件的内存映射。一个简单的链接脚本结构如下:OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{.=BOOTADDR;/*Bootloader的起始地址*/__boot_start=.;.textALIGN(4):{/*代码段.text*/*(.text)}www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构.dataALIGN(4):{/*数据段.data*/*(.data)}.gotALIGN(4):{/*全局偏移量表.got段*/*(.got)}__boot_end=.;/*Bootloader映像文件的结束地址*/.bssALIGN(16):{/*堆栈段.bss*/__bss_start=.;*(.bss)__bss_end=.;}}www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构这里不再介绍链接脚本的语法。需要指出的是,链接脚本中所描述的输出段地址为虚拟地址VMA(VirtualMemoryAddress)。这里的“虚拟地址”仅指映像文件执行时,各输出段所重定位到相应的存储地址空间,与内存管理无关。因此,上面的链接脚本实际上指定了Bootloader映像在执行时,将被重定位到BOOTADDR开始的存储地址空间,以保证在相关位置对符号进行正确引用,使程序正常运行。arm处理器复位后总是从0x0地址取第1条指令,因此只需把BOOTADDR设置为0,再把编译后生成的可执行二进制文件下载到ROM的0x0地址开始的存储空间,程序便可正常引导;但是,一旦在链接时指定映像文件从0x0地址开始,那么Bootloader就只能在0x0地址开始的ROM空间内运行,而无法拷贝到SDRAM空间运行实现快速引导。当然,对PXA270等具有MMU功能的微处理器来说,虽然可以先将Bootloader映像整个拷贝到SDRAM中,再使用MMU功能将SDRAM空间映射到0x0地址,进而继续在SDRAM中运行;但这样一方面会使得Bootloader的设计与实现复杂化,另一方面在一些必须屏蔽MMU功能的应用中(例如引导armlinux系统),无法使用MMU进行地址重映射。www.embedtrain.orgwww.mobiletrain.org千锋嵌入式学院最专业的嵌入式培训机构利用ARM的基于位置无关的程序设计可以解决上述问题。只需在程序链
本文标题:ARM的位置在Bootloader中的应用
链接地址:https://www.777doc.com/doc-8254 .html