利用cache缓存初始化内存

系统内存的初始化涉及到内存控制器的配置,需要读取DRAM条上EEPROM存储的各种配置参数,动态配置内存控制器。用汇编语言实现稍显复杂,当前的启动引导程序(如uboot)采用C语言实现这部分功能。

然而,问题是在内存未初始化之前,系统是在FLASH设备中运行的汇编,C程序不能运行(原因是C语言函数的栈操作不能在FLASH中进行,FLASH的写操作需要首先擦除再写入)。要想运行C程序就需要找到一块在内存初始化之前就可用的其它内存,这就是系统的数据d-cache缓存了。cache是一块高速内存,其与内存具有相同的属性,不同点在于cache中的内容有可能被换出到内存中,MIPS处理器有指令可以锁定cache,防止cache中内容被换出,所以可当做一块ram使用。

cache的size一般都是非常小的,好在C语言实现的ram检查以及动态配置程序不大,看一下在uboot中整个过程的实现。

前提条件

由于内存初始化程序是单独编译成一个可执行的C程序,在uboot中这部分程序称为boot1_5,需要在编译过程中将其嵌入到uboot整体镜像中。为了方便嵌入,将Uboot分成3个单独的程序:boot1、boot1_5和boot2。boot1为加电之后首先运行的汇编程序,它会加载boot1_5的C程序初始化内存;完成后,返回到boot1继续执行以及加载boot2执行。

以上流程如能正常执行,需满足以下条件:

1)boot1需要知道boot1_5程序的执行入口地址(BOOT1_5_ENTRY)和数据段起始地址BOOT1_5_FDATA。
2)boot1需要把boot1_5的数据段从flash中拷贝到d-cache中。

3)boot1要告知boot1_5在内存初始化完成之后,如何调回boot1程序中。


编译过程


在uboot编译过程中需要解决以上的第一个条件。关键在于两次编译boot1程序。在第一次编译时,使用如下参数:

-DBOOT1_5_ENTRY=0xdeadbeef  -DBOOT1_5_FDATA=0xdeadbeef

因为此时boot1_5程序还没有编译,不可能知道它的入口和数据段地址,首次编译时为boot1指定一个伪地址(0xdeadbeef)。在boot1编译完成链接的时候,为ld程序指定链接脚本ld.script:

$(LD) -Tld.script $(OBJS) -o boot1.first

在此链接脚本中,自定义一个.boot1_5的段,在其编译完成后,将其链接在boot1的这个位置,如下:

   __boot1_5_start = .       ; 
   .boot1_5 : {
     *(.boot1_5)
   }
   . = ALIGN(8)          ;
   __boot1_5_end = .     ;


接下来编译boot1_5,其使用上一步确定下来的__boot1_5_start地址作为自身的数据段的起始地址(入口地址),例如__boot1_5_start=0x9fc04800。在boot1_5编译时,指定宏变量-DLOADADDR=__boot1_5_start,其链接文件的头如下,使用LOADADDR为起始地址:


SECTIONS
{
  . = LOADADDR;
  _loadaddr = . ; 
  .text : {
    _ftext = . ;
  }
}


编译完成后,可得到boot1的真实的入口起始地址和数据段起始地址,加入分别为0x9fc04804与0x9fc1b920:

$(NM) boot1_5 | grep -w _start |cut -f1 -d' '
$(NM) boot1_5 | grep -w _fdata |cut -f1 -d' '


使用objcopy工具将boot1_5转为二进制文件,之后使用ld在次链接boot1_5。这样做的目的主要是将整个boot1_5程序链接到一个.boot1_5的段内,在boot1的链接文件中已经为此预留了位置,当第二次编译boot1之时,将二者链接成一个文件:

objcopy -S -O binary -R .note -R .comment  boot1_5  boot1_5_bin

@echo "OUTPUT_ARCH(mips) SECTIONS { .boot1_5 : { *(.data) }   }" > ld.script.boot1_5
$(LD) -T ld.script.boot1_5 -b binary -o $@ boot1_5_bin



其次编译boot2完成后,再次编译boot1,此时就不需要伪地址0xdeadbeef了,替换为真实地址在此编译:

-DBOOT1_5_ENTRY=0x9fc04804  -DBOOT1_5_FDATA=0x9fc1b920


执行流程

在程序执行时,boot1完成锁定d-cache和拷贝boot1_5数据段的工作。另外boot1会在处理器中找到一个闲置的寄存器,把返回地址写入此寄存器,boot1_5就可根据此地址跳转回boot1继续执行。


完。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值