(6)代码重定位一(IRAM内部)

11 篇文章 0 订阅

一、背景
两个概念:运行地址和链接地址。
运行地址:程序当前所处的地址,就是程序被下载到的地址。
链接地址:程序运行时应该位于的运行地址。
对于 S5PV210 而言,启动时只会从 NAND Flash/sd 等启动设备中拷贝前 16K 的代码到 IRAM中,那么当我们的程序超过 16K 怎么办?那就需要我们在前 16K 的代码中将整个程序完完整整地拷贝到 DRAM 等其他更大存储空间,然后再跳转到 DRAM 中继续运行我们的代码,这个拷贝然后跳转的过程就叫重定位。
位置无关代码:运行地址与链接地址可以不同。
位置有关代码:运行地址与链接地址必须相同。
链接脚本:链接脚本就是程序链接时的参考文件,其主要目的是描述如何把输入文件中的(SECTION) 映射到输出文件中, 并控制输出文件的存储布局。 链接脚本的基本命令式 SECTIONS命令,一个SECTIONS 命令内部包含一个或多个段,段(SECTION)是链接脚本的基本单元,它表示输入文件中的某个段是如何放置的。
段:分为.text、.data、.bss、和用户自定义段。
.text段:代码段有叫文本段,用来存放代码。
.data段:数据段用来放初始化过的全局变量数据。
.bss段:用来存放程序中未初始化的全局变量的一块内存区域。

二、代码
1、start.S

/*
 *		代码:重定位代码到IRAM0xD0024000
 *		日期:2020.7.11
 *		作者:glass love
 *
 */
 
//要开icache就将 CONFIG_SYS_ICACHE_OFF写为1,关则写为0
#define CONFIG_SYS_ICACHE            1
 
.globl _start
_start:

/**********************关看门狗*******************************/
//通过查阅数据手册知道控制看门狗开关的寄存器是:
//Watchdog Timer Control Register (WTCON, R/W, Address =0xE2700000 ) 
//WTCON寄存器的bit[0]位是启用或禁用复位信号的看门狗定时器输出位
//1为启用,0为禁止
//因此只需要往WTCON中写入0x0即可
	ldr r0, =0x00000000
	ldr r1, =0xE2700000
	str r0, [r1]
	
/**********************开icache*********************************/
//打开icache可以提高运行速度
	//读出协处理器cp15的c1的值到r0中
	mrc p15, 0, r0, c1, c0, 0
#if	CONFIG_SYS_ICACHE
	//将cp15协处理器的bit[12]置一(开icache)
	orr r0, r0, #0x00001000
#else
	//将cp15协处理器的bit[12]清零(关icache)
	bic r0, r0, #0x00001000
#endif
	//将r0中的值写入到cp15协处理器的c1中
	mcr p15, 0, r0, c1, c0, 0
	
/***********************设置栈****************************/
//IROM 里的固定代码设置的 sp 就等于 0xD003_7D80,
//所以我们设置栈一般就指向0xD003_7D80,以调用c函数

	ldr sp, =0xD0037D80
	
/*************************重定位***************************/
//adr短加载,加载_start的地址,即_start的当前地址
	adr r0, _start
//ldr长加载,加载_start的链接地址
	ldr r1, =_start
//加载bss_start的链接地址
	ldr r2, =bss_start
//比较r0和r1是否相同
	cmp r0, r1
	beq clear_bss
	
//复制代码到链接地址
copy_loop:
	ldr r3, [r0], #4      //源代码
	str r3, [r1], #4      //目标代码
	cmp r1, r2			  //只用复制到bss_start处就可以了
	bne copy_loop
	
//清bss段
clear_bss:
	ldr r0, =bss_start
	ldr r1, =bss_end
	cmp r0, r1
	beq run_dram
	ldr r2, =0x0
clear_loop:
	str r2, [r0], #4
	cmp r0, r1
	bne clear_loop
	
//跳转到链接地址中的led函数处
run_dram:
	ldr pc, =led_blink

//汇编死循环	
	b .

2、link.lds

SECTIONS
{
	. = 0xD0024000;          /*指定链接地址*/
	
	.text : {
		start.o              /*表示start.o排在代码段的最开始*/
		* (.text)			 /*(.text)表示后面的顺序随意*/
	}
    		
	.data : {
		* (.data)
	}
	
	bss_start = .;          /*将bss段的起始地址赋给bss_start,以方便外部使用该地址*/
	.bss : {
		* (.bss)
	}
	
	bss_end  = .;	       /*bss_end同上*/
}

3、Makefile

led_link.bin: start.o led.o
	arm-linux-ld -Tlink.lds -o led_link.elf $^                 
	arm-linux-objcopy -O binary led_link.elf led_link.bin			  
	arm-linux-objdump -D led_link.elf > led_link_elf.dis   		  
	gcc mkv210_image.c -o mk210              		  
	./mk210 led_link.bin 210.bin 						  
	
%.o : %.S
	arm-linux-gcc -o $@ $< -c -nostdlib

%.o : %.c
	arm-linux-gcc -o $@ $< -c -nostdlib

clear:
	rm *.o *.elf *.bin *.dis mk210 -f

其余代码较上一节均为变化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值