微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于cortex-A8的Bootloader设计

基于cortex-A8的Bootloader设计

时间:09-12 来源:互联网 点击:

)mem_setup.S(board\samsung\smdkv210)

该源文件包含对内存进行初始化的汇编源码。

(4)board.c(arch\arm\lib\board.c)

该源文件是用C编写的,主要实现了U-Boot第二阶段启动过程。包括初始化环境变量,串口控制台,Flash和打印调试信息等,最后调用main_loop()函数。

(5)smdkv210.h(include\configs\Smdkv210.h)

s5pv210平台的配置文件,该源文件定义了一些与CPU或者外设相关的参数,这些参数都是用宏来定义的。

2.3 U-Boot启动的一般流程

2.3.1 第一阶段初始化

U-Boot的启动过程分为两个阶段,第一个阶段主要由汇编代码实现,负责对CPU及底层硬件资源的初始化。第二阶段用C实现,负责使能Flash,网卡和引导操作系统等。其第一阶段流程如下图所示:

图2  U-Boot第一阶段启动流程

图2 U-Boot第一阶段启动流程

U-Boot上电后首先会设置cpu为管理模式,禁用L1缓存,关闭MMU和清除caches。之后会调用底层初始化函数lowlevel_init()。该函数实现如下:

.globl lowlevel_init

lowlevel_init:

push {lr}

#if defined(CONFIG_SPL_BUILD)

/* 初始化时钟 */

bl system_clock_init

/* 初始化内存 */

bl mem_ctrl_asm_init

/* 初始化串口 */

bl uart_asm_init

#endif

pop {pc}

上述代码中system_clock_init(), mem_ctrl_asm_init(),uart_asm_init()这三个函数需要开发者结合具体硬件环境进行修改和实现。

初始化完成之后,U-Boot会调用一个拷贝函数将BL2拷贝到内存地址为0x3FF00000处,然后跳转到该位置执行BL2。在U-Boot中,BL1 和BL2是基于相同的一些源文件编译生成的。开发者在编写代码时需要使用预编译宏CONFIG_SPL_BUILD来实现BL1和BL2不同的功能。其拷贝函数实现如下:

void copy_code_2_sdram_and_run(void)

{

unsigned long ch;

void (*u_boot)(void);

ch = *(volatile unsigned int *)(0xD0037488); /* 根据该地址的值判断传输通道 */

/* copy_bl2()函数不需要开发者去实现,s5pv210在出厂时已经固化在了0xD0037F98地址处 */

copy_sd_mmc_to_mem copy_bl2 = (copy_sd_mmc_to_mem) (*(unsigned int *) (0xD0037F98));

unsigned int ret;

if (ch == 0xEB000000) { /* CONFIG_SYS_TEXT_BASE = 0x3FF00000 */

ret = copy_bl2(0, 49, 1024,(unsigned int *)CONFIG_SYS_TEXT_BASE, 0);

} else if (ch == 0xEB200000) {

ret = copy_bl2(2, 49, 1024,(unsigned int *)CONFIG_SYS_TEXT_BASE, 0);

} else {

return;

}

u_boot = (void *)CONFIG_SYS_TEXT_BASE;

(*u_boot)(); /* 跳转到该地址执行 */

}

值得注意的是以上代码中,copy_bl2()函数不需要开发者去实现,s5pv210在出厂时已经将该函数固化在了0xD0037F98地址处。其函数原型如下:

u32 (*copy_sd_mmc_to_mem)(u32 channel, u32 start_block, u16 block_size, u32 *trg, u32 init);

/*

参数介绍:

channel:通道数2或0,该值通过读取0xD0037488地址上的值判断。

start_block:从第几个扇区开始拷贝,一个扇区为512byte。

block_size:拷贝多少个扇区,这里拷贝512K

trg:目的地址:0x3FF00000, 即离内存顶部1M的位置

init:是否需要初始化sd卡,写0即可。

*/

2.3.2 第二阶段初始化

U-Boot进入第二阶段后会首先声明一个gd_t结构体类型的指针指向内存地址(0x40000000 - GD_SIZE)处。0x40000000为内存结束地址,GD_SIZE为结构体gd_t的大小。这样相当于在内存最顶端分配了一段空间用于存放一个临时结构体gd_t。该结构体在global_data.h中被定义,U-Boot用它来存储所有的全局变量。之后U-Boot会调用 board_init_f()和board_init_r()两个函数进一步对底板进行初始化。

(1)board_init_f()

进入board_init_f()之后,U-Boot首先设置之前分配的临时结构体,然后开始划分内存空间,其内存分配示意图如下:

图3  U-Boot内存分配状态

图3 U-Boot内存分配状态

从内存分配状态图中我们可以看到,gd指针指向的临时结构体存放在内存的最顶部。BL2代码存放在内存地址0x3ff00000处,即距离内存顶部1M空间的位置。接下来依次分配malloc空间,bd_t结构体空间和gd_t结构体空间,并且重新设置栈。最后将临时结构体拷贝到id指针所指向的位置。 board_init_f()实现过程大致如下:

unsigned int board_init_f(ulong bootflag)

{

memset((void *)gd, 0, sizeof(gd_t));

...

设置gd结构体;

...

addr = CONFIG_SYS_TEXT_BASE; /* CONFIG_SYS_TEXT_BASE = 0x3ff00000000 */

addr_sp = addr - TOTAL_MALLOC_LEN;

addr_sp -= sizeof (bd_t);

bd = (bd_t *) addr_sp;

gd->bd = bd;

addr_sp -= sizeof (gd_t);

id = (gd_t *) addr_sp;

...

memcpy(id, (void *)gd, sizeof(gd_t));

base_sp = a

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top