代码重定位 学习总结

重定位之前

请使用位置无关码

位置无关码,依赖于程序当前运行的PC值,进行相对的跳转,导致的结果就是,无论代码在哪,总能达到指令的正常目的,因此是位置无关的。
位置有关码,不依赖当前PC值,是绝对跳转,只有程序运行在链接地址处时,才能达到指令的正常目的,因此是位置有关系的。

以下是位置有关的,禁用

汇编
 ldr r0, =main/* 获取函数名的地址,位置有关 */
 ldr r0 ,=__bss_start /* 获取链接脚本里标号的地址,位置有关 */
c语言

1、全局变量是位置有关码
2、函数调用,通常是位置无关的,但有可能是位置有关的,因为如果两个函数相距32M的大小,无法用bl命令跳转
3、不要使用带初值的数组,这些初值是位置有关的
4、(这个是猜想,还没有验证) 字符串,const类型的字符串应该是存储在rodata区的,很有可能是位置有关的,所以重定位之前不要用串口打印参数

重定位的时候

Nand启动

Nandflash不可以简单的读取数据进行重定位,但是前4K代码被硬件复制到了片内4k的ram中。
所以如果重定位代码的大小小于4k,可以直接用以下代码,从片内ram拷贝代码到sdram中。
但是如果代码大小大于4K,就只能先初始化nandflash,然后从nandflash中读取代码拷贝到sdram中。

void copy2sdram(void)
{
	/* 要从lds文件中获得 __code_start, __bss_start
	 * 然后从0地址把数据复制到__code_start
	 */

	extern int __code_start, __bss_start;

	volatile unsigned int *dest = (volatile unsigned int *)&__code_start;
	volatile unsigned int *end = (volatile unsigned int *)&__bss_start;
	volatile unsigned int *src = (volatile unsigned int *)0;

	while (dest < end)
	{
		*dest++ = *src++;
	}
}

nor启动

norflash可以直接读取指令来运行,所以无论代码重定位多大,都可以直接从norflash读取数据拷贝到sdram中。

如何判断是nor启动还是nand启动

int isBootFromNorFlash(void)
{
	volatile int *p = (volatile int *)0;
	int val;

	val = *p;
	*p = 0x12345678;
	//因为nand启动的时候,硬件把前4k数据自动复制到片内ram中运行,所以可以直接改变ram中的数据
	if (*p == 0x12345678)  
	{
		/* 写成功, 是nand启动 */
		*p = val;
		return 0;
	}
	//但是norfalsh要写数据进去,需要很多命令和步骤,所以norflash启动的时候,在还未转移代码到sdram之前,只能读指令,不能写数据
	else
	{
		/* NOR不能像内存一样写 */
		return 1;
	}
}

重定位之后

重定位之后,跳转运行请使用位置有关码,否则无法跳转到sdram运行

	//bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */
	ldr pc, =main  /* 绝对跳转, 跳到SDRAM */

猜你喜欢

转载自blog.csdn.net/tiantangmoke/article/details/102793806
今日推荐