代码重定位

重定位

NOR与NAND:

上电时(2440为例):

  • nandflash不能本地运行,需要将前4K内容复制到2440的片内sdram

    若程序超过4k时,则前4k需要把全部程序重定位到整个SDRAM上。

    所以需要写时(全局变量,静态变量),需要重定位到SDRAM中才能修改其值。

  • norflash则可以直接在本地运行(cpu可以直接读flash的值,但是不能直接写,需要一定的写序列才能写)

为了让在norflash启动时,能够修改数据段,所以需要把数据段重定位到SDRAM地址上,查看原理图和手册,可以知道SDRAM的基地址是0x30000000

原始方法:在链接时,指定data段链接在0x3000 0000地址上

原始方法有个很大的弊端,就是编译出来的bin文件特别大,以至于flash不够放,所以需要更改策略。

重定位两种策略
  1. 代码段链接地址从0开始,将代码段和数据段靠在一起,然后烧写值norflash,在运行时,将数据段复制到sdram(0x3000 0000),这样就是减少编译出来的bin文件大小,在运行代码是重定位。
  2. 代码段链接地址从0x3000 0000(sdram基地址)开始,然后烧写至norflash(0地址)上,运行代码时,将整个代码(代码段+数据段)重定位到sdram(0x3000 0000)上。

为什么在flash运行时能够从0开始运行,而与链接地址无关?因为用了位置无关码。

位置无关程序:

  1. 使用相对跳转指令,例b、bl汇编代码,是相对跳转,即使用偏移地址。
  2. 重定位之前,不可使用绝对地址,不可访问全局变量/静态变量/有初始值的数组(会使用绝对地址访问,会访问sdram,此时sdram并未重定位值过去)。

使用bl命令时,程序仍然在nor/sram执行,当需要跳到sdram地址时,需要用到绝对地址pc绝对跳转。

重定位过程
  1. 链接时根据链接脚本确定内存各段在二进制文本中的位置。
    如:
SECTIONS {
   .text   0  : { *(.text) }
   .rodata  : { *(.rodata) }
   .data 0x30000000 : AT(0x800) //0x30000000表示该段链接的位置,0x800表示处于二进制文本的位置
   { 
      data_load_addr = LOADADDR(.data);
      data_start = . ;
      *(.data) 
      data_end = . ;
   }
   .bss  : { *(.bss) *(.COMMON) }
}

上述连接脚本表示文本段在二进制文本的0地址上,然后以此排放只读数据段(.rodata)、数据段(.data),bss段不放在二进制文本中,内存分布如下图。

memory

  1. 编译出来的二进制可执行文件下载到Flash上,然后可以根据需要重定位某个段或者重定位整个程序,如:
_TEXT_BASE:
	.word	CONFIG_SYS_TEXT_BASE

relocate:				/* relocate U-Boot to RAM	    */
	adr	r0, > _start		/* r0 <- current position of code   */
	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
	cmp     r0, r1                  /* don't reloc during debug         */
	beq     clear_bss
	
	ldr	r2, _armboot_start
	ldr	r3, _bss_start
	sub	r2, r3, r2		/* r2 <- size of armboot            */

	bl  CopyCode2Ram	/* r0: source, r1: dest, r2: size */

其中, _start是程序运行时的位置,即下载代码到flash的位置,一般都是0,_TEXT_BASE则是定义的链接地址,对应宏CONFIG_SYS_TEXT_BASE,这个宏一般在include/configs/xx.h或在board/xx/config.ms里定义。

所以cpu先判断当前地址_start和链接地址_TEXT_BASE是否相同,不相同则将程序复制到链接地址上,从而完成重定位。

通过链接程序(.lds)来分析程序内存分布,确定各段链接地址,然后在Flash运行代码时根据链接地址将代码重定位到SDRAM。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值