s3c2440裸机-代码重定位、清bss的优化和位置无关码

发布时间:2023-08-09  

1.代码重定位的改进

用ldr、str代替ldrb, strb加快代码重定位的速度。


前面重定位时,我们使用的是ldrb命令从的Nor Flash读取1字节数据,再用strb命令将1字节数据写到SDRAM里面。

我们2440开发板的Nor Flash是16位,SDRAM是32位。 假设现在需要复制16byte数据。

不同的读写指令 cpu读取nor的次数 cpu写入sdram的次数
ldrb、strb 16 16
ldr、str 8 4

可以看出我们更换读写指令后读写次数变少了,提升了cpu的访问效率。


修改后的start.s代码如下图所示,这里我只简单的列出了重定位的实现:


 ...

 cpy:

 ldr r4, [r1]

 str r4, [r2]

 add r1, r1, #4 //r1加4

 add r2, r2, #4 //r2加4

 cmp r2, r3 //如果r2 =< r3继续拷贝

 ble cpy

 ...

用c语言实现重定位


添加如下链接脚本:


SECTIONS

{

. = 0x30000000;


__code_start = .;


. = ALIGN(4);

.text      :

{

  *(.text)

}


. = ALIGN(4);

.rodata : { *(.rodata) }


. = ALIGN(4);

.data : { *(.data) }


. = ALIGN(4);

__bss_start = .;

.bss : { *(.bss) *(.COMMON) }

_end = .;

}

在main.c中添加如下函数实现:


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++; //从0地址依次copy到__code_start(代码段的运行地址)

}

}

然后在start.s中设置栈指针sp后,即可执行bl copy2sdram进行重定位代码。如何设置栈指针请参考

时钟编程(二、配置时钟寄存器)中有实现,重复代码我就不贴上来了。


2.清bss的改进

用ldr、str代替ldrb, strb加快清bss的速度


和上面重定位类似,代码如下:


     ldr r1, =__bss_start

     ldr r2, =_end

     mov r3, #0

 clean:

     str r3, [r1]

     add r1, r1, #4

     cmp r1, r2

     ble clean


     bl main

 halt:

b halt

c语言实现清bss


和上面重定位的代码实现一样,就是往bss段全部写0. 执行完bl copy2sdram, 然后再bl clean_bss即可完成清除bss段。


 void clean_bss(void)

 {

 /* 从lds文件中获得 __bss_start, _end*/

 extern int _end, __bss_start;

 

 volatile unsigned int *start = (volatile unsigned int *)&__bss_start;

 volatile unsigned int *end = (volatile unsigned int *)&_end;

 

 while (start <= end)

 {

 *start++ = 0;

 }

 }

注意:汇编代码获取的是链接脚本中的变量的地址,而C语言代码中获取的是链接脚本中的变量的值,所以这里的用C语言改进重定位还是清bss都是要加取址符。


保证所有段的起始地址以4字节对齐


我们前面为了加快重定位和清bss的速度,用到了ldr,str这样以4字节为单位进行读写,但是还可能导致一个问题,假设现在链接脚本没有进行用ALIGN(4)让不同的段以4字节对齐,那么就会出现访问错乱的情况。


我举个例子:


 #include "s3c2440_soc.h"

 #include "uart.h"

 #include "init.h"

 

 char g_Char = 'A'; //.data

 char g_Char3 = 'a';

 const char g_Char2 = 'B'; //.rodata

 int g_A = 0; //bss

 int g_B; //bss

 

 int main(void)

 {

 uart0_init();

 

 puts("nrg_A = ");

 printHex(g_A);

 puts("nr");

 putchar(g_Char);

 return 0;

 }

将链接脚本中.data段和.bss之间的ALIGN(4)去掉。那么我们会发现程序执行的时候输出的g_A=0,为什么呢,我们明明初始化g_A=‘A’呀?


我们分析下反汇编看看:

我们的.bss段紧接着.data段后面,可知在对bss段进行清除的时候,由于我们是以4字节为单位操作的,所以我们清除g_A的时候,连带g_Char,g_Char的值也一起清除了。所以data段和数据段之间添加ALIGN(4)。修改后就会发现bss段的地址以0x30000248开始了,如下图:

3.位置无关码

我们对‘bl sdram_init’指令进行分析:

查看反汇编:(代码段的链接地址为0x3000,0000)

这里的bl 3000036c不是跳转到3000036c,这个时候sdram并未初始化,那么这个物理地址是无法访问的;

为了验证,我们做另一个实验,修改连接脚本sdram.lds, 链接地址改为0x3000,0800,编译,查看反汇编:

可以看到现在变成了bl 300003ec,但两个的机器码e1a0c00d都是一样的,机器码一样,执行的内容肯定都是一样的。 因此这里并不是跳转到显示的地址,而是跳转到: pc + offset,这个由链接器决定。


假设程序从0x30000000执行,当前指令地址:0x3000005c ,那么就是跳到0x3000036c;如果程序从0运行,当前指令地址:0x5c 调到:0x000003ec


跳转到某个地址并不是由bl指令所决定,而是由当前pc值决定。反汇编显示这个值只是为了方便读代码。


重点: 反汇编文件里, B或BL 某个值,只是起到方便查看的作用,并不是真的跳转。


怎么写位置无关码?


使用相对跳转命令 b或bl;

重定位之前,不可使用绝对地址,不可访问全局变量/静态变量,也不可访问有初始值的数组(因为初始值放在rodata里,使用绝对地址来访问);

重定位之后,使用ldr pc = xxx,跳转到/runtime地址;

写位置无关码,其实就是不使用绝对地址,判断有没有使用绝对地址,除了前面的几个规则,最根本的办法看反汇编。


因此,前面的例子程序使用bl命令相对跳转,程序仍在NOR/sram执行,要想让main函数在SDRAM执行,需要修改代码:


  //bl main  /*bl相对跳转,程序仍在NOR/sram执行*/

  ldr pc, =main/*绝对跳转,跳到SDRAM*/


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>