uboot中位置无关代码的程序设计
时间:11-09
来源:互联网
点击:
arm)
ENTRY(_start)
SECTIONS {
. = BOOTADDR;/*Bootloader的起始地址*/
__boot_start = .;
.textALIGN(4): {/*代码段.text*/
*(.text)
}
.dataALIGN(4): {/*数据段.data*/
*(.data)
}
.gotALIGN(4): {/*全局偏移量表.got段*/
*(.got)
}
__boot_end = .;/*Bootloader映像文件的结束地址*/
.bssALIGN(16): {/*堆栈段.bss*/
__bss_start = .;
*(.bss)
__bss_end =.;
}
}
这里不再介绍链接脚本的语法。需要指出的是,链接脚本中所描述的输出段地址为虚拟地址VMA(Virtual Memory Address)。这里的“虚拟地址”仅指映像文件执行时,各输出段所重定位到相应的存储地址空间,与内存管理无关。因此,上面的链接脚本实际上指定了 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进行地址重映射。
利用ARM的基于位置无关的程序设计可以解决上述问题。只需在程序链接时,将BOOTADDR设置为SDRAM空间的地址(一般情况 下利用 SDRAM中最高的1 MB存储空间作为起始地址),这样ARM处理器上电复位后Bootloader仍然可以从地址0开始执行,并将自身拷贝到指定的__boot_start 起始的SDRAM中运行。实现上述功能的链接脚本所对应的启动代码架构如下:
.section .text
.globl _start
_start:
Breset/*复位异常*/
/*其他异常处理代码*/
reset:
/*复位处理程序*/
copy_boot:/*拷贝Bootloader到SDRAM*/
LDRR0, =0x0LDRR1, =__boot_start
LDRR2, =__boot_end
1:LDRMIA R0!, { R3-R10 }
STRMIA R1!, { R3-R10 }
CMPR1, R2
BLT1b
clear_bss:
/*清零.bss段*/
BL
init_Stack/*初始化堆栈*/
LDRPC, = main/*跳转到阶段2的C程序入口*/
.end
程序入口为_start,即复位异常,所有其他异常向量都使用相对跳转指令B来实现,以保证位置无关特性。在完成基本的硬件初始化后,利用链接脚本传递 过来__boot_start和__boot_end的参数,将Bootloader映像整个拷贝到指定的SDRAM空间,并清零.bss段,初始化堆栈 后,程序将main函数入口的绝对地址赋给PC,进而跳转到SDRAM中继续运行。程序在跳转到main函数之前,所有的代码都在ROM中运行,因而必须 要保证代码的位置无关性,所以在调用初始化GPIO、存储系统和堆栈等子程序时,都使用相对跳转指令来完成。
使用位置无关设计Bootloader程序有如下优点:
① 简化设计,方便实现系统的快速引导。位置无关代码可以避免在引导时进行地址映射,并方便地跳转到SDRAM中实现快速引导。
② 实现复位处理智能化。由于位置无关代码可以被加载到任意地址空间运行,因此其运行时的当前地址与链接时所指派的地址并不一定相同。利用这一特性,可以在复 位处理程序中使处理器进入SVC模式并关闭中断后加入如下代码,便可根据当前运行时的地址进行不同的复位处理:
ADRR0, _start/*读取当前PC附近的_start标号所在指令地址*/
LDRR1,=__boot_start/*读取Bootloader在SDRAM的起始地址*/
CMPR0,R1
BEQclear_bss
上述代码中的ADR指令读取的_start标号地址由指令的执行地址决定。若是从SDRAM中的Bootloader启动,则上述比较结果相等,程序直 接跳转到clear_bss标号地址处执行,这样可以避免存储系统的重新初始化和Bootloader的拷贝过程;若是上电或硬件复位,程序从 ROM启动,则上述比较结果不等,程序便进行包括系统初始化和Bootloader拷贝等过程的全面复位处理操作。
③ 便于调试。Bootloader的调试通常也是一个繁琐的过程,使用位置无关代码,则可以将映像文件加载到SDRAM中进行调试,这既能真实地反映程序从ROM中进行系统引导的情况,又可以避免频繁烧写程序存储器。
3 结论
ENTRY(_start)
SECTIONS {
. = BOOTADDR;/*Bootloader的起始地址*/
__boot_start = .;
.textALIGN(4): {/*代码段.text*/
*(.text)
}
.dataALIGN(4): {/*数据段.data*/
*(.data)
}
.gotALIGN(4): {/*全局偏移量表.got段*/
*(.got)
}
__boot_end = .;/*Bootloader映像文件的结束地址*/
.bssALIGN(16): {/*堆栈段.bss*/
__bss_start = .;
*(.bss)
__bss_end =.;
}
}
这里不再介绍链接脚本的语法。需要指出的是,链接脚本中所描述的输出段地址为虚拟地址VMA(Virtual Memory Address)。这里的“虚拟地址”仅指映像文件执行时,各输出段所重定位到相应的存储地址空间,与内存管理无关。因此,上面的链接脚本实际上指定了 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进行地址重映射。
利用ARM的基于位置无关的程序设计可以解决上述问题。只需在程序链接时,将BOOTADDR设置为SDRAM空间的地址(一般情况 下利用 SDRAM中最高的1 MB存储空间作为起始地址),这样ARM处理器上电复位后Bootloader仍然可以从地址0开始执行,并将自身拷贝到指定的__boot_start 起始的SDRAM中运行。实现上述功能的链接脚本所对应的启动代码架构如下:
.section .text
.globl _start
_start:
Breset/*复位异常*/
/*其他异常处理代码*/
reset:
/*复位处理程序*/
copy_boot:/*拷贝Bootloader到SDRAM*/
LDRR0, =0x0LDRR1, =__boot_start
LDRR2, =__boot_end
1:LDRMIA R0!, { R3-R10 }
STRMIA R1!, { R3-R10 }
CMPR1, R2
BLT1b
clear_bss:
/*清零.bss段*/
BL
init_Stack/*初始化堆栈*/
LDRPC, = main/*跳转到阶段2的C程序入口*/
.end
程序入口为_start,即复位异常,所有其他异常向量都使用相对跳转指令B来实现,以保证位置无关特性。在完成基本的硬件初始化后,利用链接脚本传递 过来__boot_start和__boot_end的参数,将Bootloader映像整个拷贝到指定的SDRAM空间,并清零.bss段,初始化堆栈 后,程序将main函数入口的绝对地址赋给PC,进而跳转到SDRAM中继续运行。程序在跳转到main函数之前,所有的代码都在ROM中运行,因而必须 要保证代码的位置无关性,所以在调用初始化GPIO、存储系统和堆栈等子程序时,都使用相对跳转指令来完成。
使用位置无关设计Bootloader程序有如下优点:
① 简化设计,方便实现系统的快速引导。位置无关代码可以避免在引导时进行地址映射,并方便地跳转到SDRAM中实现快速引导。
② 实现复位处理智能化。由于位置无关代码可以被加载到任意地址空间运行,因此其运行时的当前地址与链接时所指派的地址并不一定相同。利用这一特性,可以在复 位处理程序中使处理器进入SVC模式并关闭中断后加入如下代码,便可根据当前运行时的地址进行不同的复位处理:
ADRR0, _start/*读取当前PC附近的_start标号所在指令地址*/
LDRR1,=__boot_start/*读取Bootloader在SDRAM的起始地址*/
CMPR0,R1
BEQclear_bss
上述代码中的ADR指令读取的_start标号地址由指令的执行地址决定。若是从SDRAM中的Bootloader启动,则上述比较结果相等,程序直 接跳转到clear_bss标号地址处执行,这样可以避免存储系统的重新初始化和Bootloader的拷贝过程;若是上电或硬件复位,程序从 ROM启动,则上述比较结果不等,程序便进行包括系统初始化和Bootloader拷贝等过程的全面复位处理操作。
③ 便于调试。Bootloader的调试通常也是一个繁琐的过程,使用位置无关代码,则可以将映像文件加载到SDRAM中进行调试,这既能真实地反映程序从ROM中进行系统引导的情况,又可以避免频繁烧写程序存储器。
3 结论
本文所介绍的基于位置无关的程序设计是通过基于PC或基址寄存器的符号引用规范来实现的。这种方法在实际系统开发中应用广泛,既能用于引导程序的设计, 也可用于一般的应用程序或嵌入
uboot位置无关代 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)