基于ARM9上linux系统的bootloader设计
3.2 拷贝Stage2至RAM
习惯上把stage2拷贝到RAM地址的最顶部1MB开始的空间,RAM的起始地址为0x30000000。实现代码如下所示:
/*计算stage2在flash中的位置,假设该映像不超过64K,自行可修改该值*/
Adr r0,_start
Add r2,r0,#(64*1024)
Add r0,ro,#0x1000
Ldr r1 ,BLOB_START
/*开始复制stage2到RAM,R0=源起始地址,R1=目的地址,r2源结束地址*/
copy_loop:
ldmia r0!,{r3-r10}
stmia r1!, {r3-r10}
cmp r0,r2
ble copy_loop
ldr r0,BLOB_START //复制完跳转到RAM执行由此入口进入stage2
3.3.设置堆栈指针
系统堆栈初始化取决于用户使用了哪些中断,以及系统需要处理哪些错误类型。一般情况下,管理者堆栈必须设置,如果使用了IRQ中断,则IRQ堆栈也必须设置,下面以IRQ堆栈为例进行设置。
IRQMode 堆栈
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1; IRQMode
ldr sp,IRQStack
4. stage2设计
4.1.可执行映像stage2的入口
由于在编译和链接Bootloader这样的c程序时不能使用glibc库支持的函数,所以直接把main()函数的起始地址作为第二阶段的入口点是最直接的想法。可以用汇编编写一段trampoline(弹簧床)小程序用CPU跳转指令跳到main()函数去执行,当mian()函数返回时会再次回到trampoline程序,具体汇编代码如下:
@get read to call c functions
ldr sp DW_STACK_START @ setup stack pointer
mov fp ,#0 @ no previous frame,so fp=0
mov a2, #0 @set argv to NULL
bl main @call main
mov pc,#FLASH_BASE @otherwise,reboot
如果正常不出错就不会再回到trampoline程序,否则就会回到最后一条语句重起系统。
4.2 内存影射
一般s3c2410上配置的SDRSAM大小为64M,该SDRAM的物理地址范围是0x3000 0000~0x33FF FFFF(属于Bank 6),由于1个Section的大小是1M,所以该物理空间可以被分成64个物理段(页框)。
由于bootloader没有对MMU的管理代码,处理器在运行时直接访问物理地址。同时,因为ARM体系结构中数据缓冲(Dcache)必须通过 MMU开启,所以bootloader效率比较低,可通过平板映射(flat,既虚拟地址和物理地址相同)方式开启MMU,从而使用内存空间的 Dcache,提高bootloader的运行速度。
如图1所示:
图1虚拟地址到物理地址映射
评论