作者: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 =.;
}
1240

被折叠的 条评论
为什么被折叠?



