亮仔移植u-boot系列之-- S3c2440在最新版本U-boot-2015.10移植(支持SPL模式启动) -- 3

时间:2022-07-28 18:49:32

   这章讲解BL2阶段的代码重定位和串口功能的实现.

   在BL1阶段执行最后一句代码:

   ldr pc, =CONFIG_SYS_TEXT_BASE

  此时PC指针重新指向b reset命令,第二阶段无需重新做cpu,时钟之类的初始化,直接执行BL _main命令设置BL2模式下的sp.我将BL2模式下DDR的分布设置如下:

--------------------0x30000000 + 64M
u-boot.bin
--------------------0x30008000
.
.(not use)
--------------------0x30001000global data --------------------0x30001000 - 176GD 
--------------------0x30001000 - 176 - GD_SIZE.SP..---------------------0x30000000</span>

    设置完堆栈后执行

    BL  board_init_r,下面是详细分析这段函数的相关代码和注释:

gd->mon_len = (ulong)&__bss_end - (ulong)_start;//记录代码段起始地址到bss_end总大小


init_baud_rate();//设置串口波特率为115200


serial_init(); //设置uart时钟,新版的u-boot支持2440的时钟配置,只需将CONFIG_S3C2440 = 1;不用像u-boot-1.1.6那样重新写代码


get_current()->start();//相当于调用了serial_init_dev(0);函数,下面有分析


dev = default_serial_console();//我们需要调用serial_s3c24x0.c中的函数,查看MakeFile发现obj-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o
//<strong>因此需要在yl2440.h中定义CONFIG_S3C24X0_SERIAL</strong>

return &s3c24xx_serial0_device;//我们默认使用serial0,因此需要在yl2440.h中<strong>#define CONFIG_SERIAL1 1</strong>
而struct serial_device s3c24xx_serial0_device = INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0"); 将 INIT_S3C_SERIAL_STRUCTURE展开即
struct serial_device s3c24xx_serial0_device =
{
.name = "s3ser0", \
.start = s3serial0_init, \
.stop = NULL, \
.setbrg = s3serial0_setbrg, \
.getc = s3serial0_getc, \
.tstc = s3serial0_tstc, \
.putc = s3serial0_putc, \
.puts = s3serial0_puts, \ /* printf()--->>> dev->puts() */
}


gd->ram_size = PHYS_SDRAM_1_SIZE; //在yl2440.h中定义成64M


setup_dest_addr(); //首先将gd->relocaddr设置为0x30000000+0x4000000(64M)


gd->relocaddr = 0x30000000+0x4000000;


reserve_uboot


gd->relocaddr -= gd->mon_len; //relocaddr指向代码重定位的地址
gd->start_addr_sp = gd->relocaddr;


reserve_malloc()


gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN;


reserve_board


gd->start_addr_sp -= sizeof(bd_t);
gd->bd = gd->start_addr_sp;
将bd区域清0


reserve_global_data()


gd->start_addr_sp -= sizeof(gd_t);
gd->new_gd = gd->start_addr_sp ;


reserve_stacks()


gd->start_addr_sp -= 16;
gd->start_addr_sp &= ~0xf;


setup_reloc();


gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE;//gd->reloc_off = gd->relocaddr - 0x30008000;
memcpy(gd->new_gd, (char *)gd, sizeof(gd_t));// 0x30001000-176-GD_SIAZE ---->>>> gd->new_gd搬移

     需要说明的是在该函数调用的board_early_init_f()中将设置PLL相关部分全部注释掉,因为之前的时钟设置已经在BL1阶段设置好了.

     board_init_r退出重新设置新的sp指针:LDR SP [r9 #GD_START_ADDR_SP] /* sp = gd->start_addr_sp这个值已经之前设置好了 */

     从新的gd地址找到新的gd->relocaddr即代码重定位的地址,调用b  relocate_code后,此时新的DDR分布如下:

-------------0x304000000 sdram end(64M)
.
.
<strong>u-boot.bin + 动态链接库(不是很清楚,估计和相对地址有关)</strong>
.
-------------gd->relocaddr 0x304000000 - (gd->mon_len)
malloc lenth
-------------0x304000000 - (gd->mon_len + malloc_lenth)
bd(记录板子的信息,如bd->baudrate)
-------------0x304000000 - (gd->mon_len + malloc_lenth + bd)
gd(记录初始化参数,如gd->start_addr_sp)
-------------0x304000000 - (gd->mon_len + malloc_lenth + bd + gd)
16Byte
-------------gd->start_addr_sp 0x304000000 - (gd->mon_len + malloc_lenth + bd + gd + 16)
sp
-------------
.
.(not use)
-------------
kernel(2M)
-------------0x30800000
.
.boot param
-------------0x30000100
(not use)
-------------0x30000000

    由于在4K IRAM内的中断向量表是BL1阶段的向量表,因而需要执行搬移BL2的向量表到4K IRAM内

    bl relocate_vectors

    最后执行

    ldr pc, =board_init_r

    进入板子的第二阶段初始化工作,此时在串口已经可以显示U-BOOT2015.10的信息了.串口功能调试完毕.

    总结:

    U-Boot第二阶段(BL2)最开始将位于用户定义的代码链接地址从0x30008000重定位到SDRAM顶端,并生成了一个动态链接库rel_dyn_start到rel_dyn_end.并重新设置sp,拷贝就得bd数据到新的bd区域,重定位向量表,最终执行第二阶段的板卡初始化.

    这个阶段代码重定位完毕,串口已经可以跑起来了.

    我们知道U-boot终极目的是引导内核,因此我们还需要以下功能:

    功能1:u-boot支持tftp下载内核到DDR中,因此需要配置DM9000网卡

    功能2:u-boot需要支持Nand读写,将内核及环境变量写到Nand Flash的相关位置,上电后将镜像读到DDR

    功能3:u-boot能将位于DDR的内核进行引导,最终U-boot寿命结束,控制权交给内核


    本章结束,下一章将介绍如何配置DM9000,实现网卡的下载功能.


    遗留问题:动态链接库、中断重定位的细节