重定位的引入


本文是基于韦东山视频的学习笔记

汇总点这

引入

为什么要有重定位,什么是重定位?

我们知道,CPU可以从一些特定的芯片直接读写数据如SDRAM,Nor和网卡,但是不同于Nor,Nand是不可以直接和CPU交互滴。那既然这样,当程序烧写到Nand时,CPU是怎么运行程序的呢。在这里插入图片描述

其实啊,Nand启动时,Nand的前4k内存都会被复制到SRAM当中(通过硬件),CPU又是可以直接和SRAM读写数据的,那就理所当然可以运行程序了。

那么问题来了,如果程序大于4K呢?

对于这样的情况,我们可以运行程序全部复制到SDRAM,这就是重定位,重定位简单理解就是,把程序的地址重新定位

这是一种运用到重定位的情况,还有一种和Nor启动有关。由于防止运行程序轻易地被破坏,Nor在一般情况下都是只读,不能被写入。我们知道局部变量是放在SRAM中的,但是全局变量是烧写在bin文件,也就是会烧进Nor flash中的,当需要修改这些变量,就需要把他重定位了:把全局变量放到SDRAM。

再讲重定位之前,先说一下段。一般我们链接的程序会有四个“段”。

  • text 程序段
  • data 数据段,放全局变量的,局部变量放在栈里面的
  • rodata 只读数据段,放const 全局变量的
  • bss 这个段是存放初始值为零和没有定义初始值的全局变量
  • comment 注释段

链接脚本

先说Nor启动,上文说到要修改全局变量,就要把全局变量放到SDRAM中,而我们知道,SDRAM的地址是0x3000 0000,而程序又是从零地址开始(Nor启动)。也就是说,如果把全局变量放进去,程序代码会从零地址一直写到0x3000 0000(十进制805,306,368)地址,那bin文件就有800多m了!

没法玩啊。其实有两种方法解决

  • 要么把数据段顺着程序段放进 bin 文件,要到运行的时候再把数据段重定位到地址为0x3000 0000 的 SDRAM。
  • 要么把程序段数据段等等的都放进0x3000 0000的地址,再把全部把0x3000 0000放进 bin 文件,运行的时候,把全部程序都重定位到SDRAM 去运行。

由于单纯靠Makefile的简单链接指令已经满足不了重定位的需求了,所以必须引入链接脚本

先来试试第一个解决方法,在main.c 定义一个全局变量 g_char = ‘A’,在链接脚本这样写:

SECTIONS {
.text 	0: {*(.text)}	//指定代码段从零地址开始
.rodata  : {*(.rodata)}	//指定只读段从 原rodata的地址 开始,即不变
.data	0x30000000: AT(0x800) {*(.data)}	//意思是程序会从0x3000 0000运行,但是程序会放在0x800的地方,等下我们要手动把0x800的程序复制到0x3000 0000去(如果不指定为0x800,会默认从0x2xxx开始,bin文件就会很大)
.bss 	 : {*(.bss) *(.COMMET)}	//不变
}

start.S 这样写

	/* 重定位 
	* 把数据段0x800的内容复制到0x30000000
	*/
	mov r0, #0x800
	ldrb r1, [r0]
	mov r0, #0x30000000
	strb r1, [r0]

但是这样写,完全不具有普遍性,都需要指定地址,所以换一种写法:

SECTIONS {
.text 	0: {*(.text)}	
.rodata  : {*(.rodata)}	
.data	0x30000000: AT(0x800) 
{	
	data_load_addr = LOADADDR(.data);
	data_start = .;
	*(.data)
	data_end = .;
}
.bss 	 : {*(.bss) *(.COMMET)}	
}

	bl sdram_init	//要用到sdram,记得初始化
	
	/* 重定位 */
	ldr r1, =data_load_addr	//本例子是0x30000000
	ldr r2, =data_start		//本例子是0x800
	ldr r3, =data_end		//本例子是0x800+data
copy:	
	ldrb r0, [r1] 
	strb r0, [r2]
	add r1, r1, #1
	add r2, r2, #1
	cmp r2, r3
	bne  copy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值