• s3c2440裸机-代码重定位(1.重定位的引入,为什么要代码重定位)


    1.重定位的引入(为什么要代码重定位)

    我们知道s3c2440的cpu从0地址开始取指令执行,当从nor启动时,0地址对应nor,nor可以像内存一样读,但不能像内存一样写。我们能够从nor上取指令执行。

    例子1:当nand启动的时候,我们nand中的前4K指令会变自动加载到sram中去,这时的0地址对应sram。

    那么我们的程序如果大于4K,要从nand启动,sram只拷贝了nand中的前4K代码,那么如何解决这个问题呢?
    那么就需要重定位代码到sdram中去,sdram的容量较大,又可以直接被cpu访问。

    例子2:我们知道,程序含有:

    代码段(.text)
    数据段(.data):存放初始值不为0的全局变量/静态变量
    rodata段(.rodata):const修饰的全局变量或静态变量
    bss段(.bss):存放初始值为0或者未初始化的全局变量/静态变量
    commen段(.commen):注释
    

    假设有如下代码编译成一个bin文件。

    #include "s3c2440_soc.h"
    #include "uart.h"
    #include "init.h"
    
    int g_Char = 'A'; //.data
    int g_CharB = 'B'; //.data
    int g_CharC = 'C'; //.data
    int g_CharD = 'D'; //.data
    
    
    const int g_roval = 'C'; //.rodata
    int g_A = 0; //bss
    int g_B; //bss
    
    int main(void)
    {
    	uart0_init();
    	while (1)
    	{
    		putchar(g_Char);
    		g_Char++;         /* nor启动时, 此代码无效,由于nor启动,nor上不可写 */
    		delay(1000000);
    	}
    	return 0;
    }
    

    我们把它分别烧录到nand和nor看看有什么不一样?

    1.烧录到nor: 我们发现程序一直输出‘AAAAAAA’。

    2.烧录到nand: 我们发现程序无任何输出。

    我们发现nor启动时, 对g_Char++无效,nand启动程序无任何输出,为什么呢?
    我们对程序反汇编看看:

    我们发现程序的.text段是从0地址开始的,那么cpu从0地址取指令进行译码、执行。
    当从nor启动时,0地址对应nor;当从nand启动时,0地址对应sram,所以无论从nand还是从nor启动cpu都能取指令执行。

    但是,我们在来看下.data段,发现.data段的起始地址是0x8474(即g_Char变量的地址为0x8474)。
    那么:

    1)当把程序烧录进nor, .data段在nor上的某一段区域,由于nor能像内存一样读,
    但不能像内存一样直接写,所以对 'g_Char'修改无效。

    2)当把程序烧录进nand, .data段在nand的某一区域,nand启动时硬件会自动把nand上的前4K数据copy到SRAM,然后cpu从sram取指令执行。但是.data段的起始地址0x8474>0x1000,超过了4K,cpu没法把.data段也copy到SRAM,所以当访问'g_Char'时,发生了异常(abt数据访问终止,这个异常后面我会在“异常与中断”里面专门讲解)。

    那我们再仔细看看反汇编,发现.rodata段和.text段是连续的,但是.rodata段和.data段中间有一段"空洞"。用图形表示更形象,bin文件的内容分布如下所示:

    那么我们怎么去掉空洞,让.data段了紧接着.rodata段呢?

    用链接脚本(这个下节会讲),但现在直接在编译的时候用 "-Tdata 0x800",这样指定.data段基地址为0x800,这样nand启动时.data就能自动copy到SRAM了。再看下反汇编的.data段:

    这时我们烧录程序到nand,从nand启动,发现能输出‘ABCDEFG’...

    有人说为什么不吧.data段指向到sdram呢,这样不就能对对全局变量写了?
    我做了这个尝试,编译时用"-Tdata 0x30000000", 发现编译出来的bin文件有800多M,为什么有这么大呢?由于我们指定.data段存放在0x30000000(sdram的基地址),这时bin文件的内部结构如下所示:

    这个时候根本无法烧录。

    通过上面2个例子,现在总结下为什么要代码重定位:
    1.nand启动,前4K代码被自动copy到sram,当程序大于4K的时候需要重定位代码到sdram。
    2.nor启动, 全局变量在nor上,不能像内存一样直接写该全局变量,那么也需要重定位到sdram。

  • 相关阅读:
    【程序25】
    【程序24】
    【程序23】
    【程序22】
    【程序21】
    【程序20】
    【程序19】
    【程序18】
    string用法总结
    快速排序
  • 原文地址:https://www.cnblogs.com/fuzidage/p/12038514.html
Copyright © 2020-2023  润新知