回顾一下u-boot启动其一阶段做了哪些事:
第一:设置CPU为SVC模式
第二:关闭看门狗
第三:关中断和子中断
第四:设置时钟
第五:MMU关闭,清除cache和TLB,使能地址对齐检查等
第六:初始化SDRAM
在我前面的分析里,第一阶段的最后,通过bl _main,跳到了arch/arm/lib/crt0.S里面去了,从这里开始时第二阶段的入口,下面从这里开始分析。
文件:crt0.S
先看看该文件对_main的描述,在第18行,有一个_main execution sequence is:下面有五步,其实就是对_main的执行流程的一个介绍,我翻译一下:
1.设置初始环境准备调用board_init_f()。提供一个堆栈或者地址来存储全局数据结构gd。
2.调用board_init_f()。该函数是为了准备执行的硬件环境,因为RAM可能还不能使用,board_init_f()必须使用当前的GD来存储必须在稍后的阶段传递的任何数据。这些数据包括搬迁目的地,未来堆栈,以及未来GD位置。
3.设置中间环境。使用board_init_f()在RAM中分配空间给gd和堆栈,但是bss和非常量数据仍然无法使用。
4.调用重定向代码。此功能重新定位U-Boot从当前位置到由board_init_f计算的重定向后的地址。
5.建立最终环境调用board_init_r()。包括在RAM中对BSS清零,初始化变量和堆栈,gd保留通过board_init_f()设定的值。
6.跳转到board_init_r()执行。
函数:_main
ENTRY(_main)
/*
* Set up initial C runtime environment andcall board_init_f(0).
*/
#ifdefined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldr sp,=(CONFIG_SPL_STACK)
#else
ldr sp,=(CONFIG_SYS_INIT_SP_ADDR)
#endif
bic sp,sp, #7 /* 8-byte alignment for ABI compliance*/
sub sp,sp, #GD_SIZE /* allocate one GD aboveSP */
bic sp,sp, #7 /* 8-byte alignment for ABIcompliance */
mov r9,sp /* GD is above SP */
初始化栈指针,为board_init_f准备调用环境。最后r9寄存器中的地址就是gd结构体的首地址。
#if 1
__TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
mov r0, #0
ldr r1, __TEXT_BASE
ldr r2, __TEXT_BASE
ldr r3, =__bss_end
sub r2, r3, r2
bl copy_code_to_sdram
bl clear_bss
ldr pc, =call_board_init_f
.word的意思是在__TEXT_BASE地址处放置CONFIG_SYS_TEXT_BASE的值,还有一种就是.globl,这是告诉编译器紧跟着后面的的符号要被编译器用到。
给r0清零,r1和r2都给__TEXT_BASE地址,r3给bss段的结束地址。结束地址和TEXT_BASE的差值给r2,然后跳转到copy_code_to_sdram,切过去:
void copy_code_to_sdram(unsigned char*src, unsigned char *dest, unsigned int len)
{
int i = 0;
/* 如果是 NOR 启动 */
if (isBootFromNorFlash())
{
while (i < len)
{
dest[i] = src[i];
i++;
}
}
else
{
nand_init_b();
nand_read_b((unsigned int)src, dest,len);
}
}
先判断是从nand还是从nor启动,然后将代码拷贝到sdram中去。接着,请bss段,然后ldr pc, =call_board_init_f,跳转到
call_board_init_f:
mov r0, #0
bl board_init_f
函数:board_init_f
gd->mon_len = (ulong)&__bss_end -(ulong)_start;
指定代码的大小,为bss段的尾地址减去_start地址。
for (init_fnc_ptr = init_sequence;*init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
遍历了init_sequence中的函数,init_sequence函数如下:
init_fnc_t *init_sequence[]= {
arch_cpu_init, /* basic arch cpu dependent setup */
mark_bootstage,
#ifdefCONFIG_OF_CONTROL
fdtdec_check_fdt,
#endif
#ifdefined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
timer_init, /* initialize timer */
#ifdef CONFIG_BOARD_POSTCLK_INIT
board_postclk_init,
#endif
#ifdefCONFIG_FSL_ESDHC
get_clocks,
#endif
env_init, /*initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
print_cpuinfo, /* display cpu info (and speed) */
#ifdefined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
#ifdefined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
init_func_i2c,
#endif
dram_init, /* configure available RAM banks */
NULL,
};
这里有很多重要的初始化函数,例如init_baudrate,serial_init,,console_init_f,等等,就不一一切过去看了,只要知道每个函数名是干嘛的就可以了。
addr = CONFIG_SYS_SDRAM_BASE +get_effective_memsize();
这里地址等于BASE+有效地址,也就是整个sdram的可用部分。在下面:
#if !(defined(CONFIG_SYS_ICACHE_OFF) &&defined(CONFIG_SYS_DCACHE_OFF))
/* reserveTLB table */
gd->arch.tlb_size= PGTABLE_SIZE;
addr -=gd->arch.tlb_size;
/* rounddown to next 64 kB limit */
addr&= ~(0x10000 - 1);
gd->arch.tlb_addr= addr;
debug("TLBtable from %08lx to %08lxn", addr, addr + gd->arch.tlb_size);
#endif
/* rounddown to next 4 kB limit */
addr&= ~(4096 - 1);
debug("Topof RAM usable for U-Boot at: %08lxn", addr);
这里是说如果没有定义关闭icache以及dcache关闭,就把PGTABLE_SIZE给gd,同时addr要减去gd这部分的大小,最后addr的值其实就是tlb的地址,并且要4Kb对齐。
addr=CONFIG_SYS_TEXT_BASE;
这里的CONFIG_SYS_TEXT_BASE;代码u-boot代码在内存中的起始地址。
addr_sp = addr - TOTAL_MALLOC_LEN;
debug("Reserving %dk for malloc()at: %08lxn",
TOTAL_MALLOC_LEN >>10, addr_sp);
/*
*(permanently) allocate a Board Info struct
*and a permanent copy of the "global" data
*/
addr_sp -= sizeof (bd_t);
bd = (bd_t *) addr_sp;
gd->bd = bd;
debug("Reserving %zu Bytes for BoardInfo at: %08lxn",
sizeof (bd_t), addr_sp);
#ifdef CONFIG_MACH_TYPE
gd->bd->bi_arch_number= CONFIG_MACH_TYPE; /* board id for Linux */
#endif
addr_sp-= sizeof (gd_t);
id= (gd_t *) addr_sp;
debug("Reserving%zu Bytes for Global Data at: %08lxn",
sizeof(gd_t), addr_sp);
首先预留malloclen,一般为0x400000,为bd,gd做一个永久的拷贝,因为这时候环境已经准备的差不多了。留出了全局信息bd_t结构体的空间,首地址存在gd->bd。留出gd_t结构体的空间。首地址存在id中。将此地址保存在gd->irq_sp中作为异常栈指针。
addr_sp += 128; /*leave 32 words for abort-stack */
gd->irq_sp= addr_sp;
这里是为异常留的堆栈部分。
gd->bd->bi_baudrate = gd->baudrate;
/* Ram istboard specific, so move it to board code ... */
dram_init_banksize();
display_dram_config(); /* and display it */
首先将gd->baudrate赋给gd->bd->bi_baudrate,然后对板上的BANKS进行一个初始化。
gd->relocaddr = addr;
gd->start_addr_sp = addr_sp;
gd->reloc_off = addr - (ulong)&_start;
debug("relocation Offset is:%08lxn", gd->reloc_off);
if (new_fdt) {
memcpy(new_fdt, gd->fdt_blob,fdt_size);
gd->fdt_blob = new_fdt;
}
memcpy(id, (void *)gd, sizeof(gd_t));
return (unsigned int)id;
三个地址的幅值,主要是重定向的起始结束以及sp的起始地址。最后将gd结构体拷贝到新的地址上。board_init_f结束。
ldr sp, [r9, #GD_START_ADDR_SP] /* sp =gd->start_addr_sp */
bic sp, sp, #7 /* 8-byte alignment forABI compliance */
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is belowbd */
ldr r1, __TEXT_BASE
bl board_init_r
执行这一段,更新sp,更新gd地址,跳转到board_init_r。
函数:board_init_r
void board_init_r(gd_t *id, ulongdest_addr)
{
ulong malloc_start;
#if!defined(CONFIG_SYS_NO_FLASH)
ulong flash_size;
#endif
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R,"board_init_r");
monitor_flash_len =(ulong)&__rel_dyn_end - (ulong)_start;
上一篇:U-boot-2014.04移植到MINI2440(9) nor flash启动和nand flash 启动
下一篇:U-boot-2014.04移植到MINI2440(10) 移植nand flash保存环境变量、添加分区
推荐阅读最新更新时间:2024-11-10 09:18
设计资源 培训 开发板 精华推荐
- LTC3808EDE,一款 750kHz、同步单节锂离子电池至 1.8V/2A 转换器
- STEVAL-ILL060V1,基于 STAP16DPPS05 和 STM8A 高亮度 LED 阵列驱动器的评估板,具有汽车应用诊断功能
- FEBFL7733A_L50U008A,基于 FL7733A 8.4W LED 驱动器的通用线路评估板
- LTC2263-12、12 位、25Msps 低功耗双通道 ADC 的典型应用
- L7815A 具有短路保护的高输出电流的典型应用
- 海拔压力实验设计板
- 使用 Analog Devices 的 LT124XMJ8 的参考设计
- 105675-HMC434,基于 HMC434 0.2 至 8 GHz、GaAs、HBT MMIC、8 分频预分频器的评估板
- #第五届立创电子设计大赛#PCM1754 USB-DAC
- 基于C2800系列的DSP开发板