韦东山嵌入式第一期学习笔记DAY_12——13_6重定位_清除BSS段的C函数实现

作者:GWD 时间:2019.7.13

一、课程内容
摘要:本节课用汇编传参和符号表传参两种方式各写了一个代码实现用C实现代码重定位与bss段清0;讲解了符号表的原理及引用方式。
1、问:符号表是什么?
2、符号表怎么使用
二、学习要点:
1、问:C函数怎么使用lds文件中的变量abc?
答:
1)、在C函数中声明改变量为extern类型, 比如:extern int abc;
2、使用时, 要取址, 比如:int *p = &abc; // p的值即为lds文件中abc的值。
2)、问:使用链接脚本中的变量时为什么加&符号?
答:这是编译器的一种机制,引入了符号表,lds中的变量是不保存在程序中的,符号表再怎么大也不会影响程序,在引用时候去符号表中找。节省了程序的内存。
在这里插入图片描述

三、代码
(一)、使用汇编函数传递参数的方法;
1、更改start.S
在这里插入图片描述
2、写copy2sdram函数
在这里插入图片描述
3、写clean_bss函数
在这里插入图片描述
4、实验现象
在这里插入图片描述
5、代码

void copy2sdram(volatile unsigned int *src,volatile unsigned int *dest,volatile unsigned int len)
{
	unsigned int i=0;
	while(i < len)
	{
		*dest++ = *src++;
		i+=4;
	}	
}	

void clean_bss(volatile unsigned int *start,volatile unsigned int *end)
{
	while(start < end)
	{
		*start++ = 0;
	}	
}	


.text
.global _start

_start:

	/* 关闭看门狗 */
	ldr r0, =0x53000000
	ldr r1, =0
	str r1, [r0]

	/* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
	/* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
	ldr r0, =0x4C000000
	ldr r1, =0xFFFFFFFF
	str r1, [r0]

	/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */
	ldr r0, =0x4C000014
	ldr r1, =0x5
	str r1, [r0]

	/* 设置CPU工作于异步模式 */
	mrc p15,0,r0,c1,c0,0
	orr r0,r0,#0xc0000000   //R1_nF:OR:R1_iA
	mcr p15,0,r0,c1,c0,0

	/* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0) 
	 *  m = MDIV+8 = 92+8=100
	 *  p = PDIV+2 = 1+2 = 3
	 *  s = SDIV = 1
	 *  FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
	 */
	ldr r0, =0x4C000004
	ldr r1, =(92<<12)|(1<<4)|(1<<0)
	str r1, [r0]

	/* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
	 * 然后CPU工作于新的频率FCLK
	 */
	
	/* 设置内存: sp 栈 */
	/* 分辨是nor/nand启动
	 * 写0到0地址, 再读出来
	 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
	 * 否则就是nor启动
	 */
	mov r1, #0
	ldr r0, [r1] /* 读出原来的值备份 */
	str r1, [r1] /* 0->[0] */ 
	ldr r2, [r1] /* r2=[0] */
	cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
	ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
	moveq sp, #4096  /* nand启动 */
	streq r0, [r1]   /* 恢复原来的值 */

	bl sdram_init
	
	/*重定位data段*/
	mov r0,#0
	ldr r1, = _start
	ldr r2, = bss_start
	sub r2,r2,r1
	bl copy2sdram
	
	/*清除bss段*/
	ldr r0,= bss_start
	ldr r1,= end
	bl clean_bss

	ldr pc,=main
halt:
	b halt

(二)、这样也不完美,有没有办法在C中获取start,end,len的值呢?这就是第二种方式,符号表。
1、修改链接脚本,定义代码开始位置变量
在这里插入图片描述
2、修改start.S
在这里插入图片描述
3、写两个函数
在这里插入图片描述
4、代码

void copy2sdram(void)
{
	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++;
	}
}	

void clean_bss(void)
{
	extern int bss_end,bss_start;
	volatile unsigned int *start= (volatile unsigned int *)&bss_start;
	volatile unsigned int *end = (volatile unsigned int *)&bss_end;
	while(start <= end)
	{
		*start++ = 0;
	}	
}	


SECTIONS
{ 
    . = 0x30000000;
	code_start = .;
	. = ALIGN(4);
  .text		: 
  	{ 
		*(.text)
	}
  . = ALIGN(4);
  .rodata	: { *(.rodata) }
  . = ALIGN(4);
  .data	 :
  { 
  	*(.data)
  }
  . = ALIGN(4);
  bss_start = .;
  .bss	: { *(.bss) *(.COMMON) }
  bss_end =.;
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值