当前位置: 移动技术网 > IT编程>网络>音视频 > (6)代码重定位一(IRAM内部)

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

2020年07月13日  | 移动技术网IT编程  | 我要评论

一、背景
两个概念:运行地址和链接地址。
运行地址:程序当前所处的地址,就是程序被下载到的地址。
链接地址:程序运行时应该位于的运行地址。
对于 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

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

本文地址:https://blog.csdn.net/weixin_47123600/article/details/107286634

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网