略过没有定义的部分
- CFG_NO_FLASH(NandFlash和NorFlash都是Flash,但是一般NandFlash会简称为Nand而不是Flash,一般讲Flash都是指的NorFlash。这里这里的代码是NorFlash相关的),我们硬件中并没有。
- CONFIG_VFD
- CONFIG_LCD
mem_malloc_init
static void mem_malloc_init (ulong dest_addr)
{
mem_malloc_start = dest_addr;
mem_malloc_end = dest_addr + CFG_MALLOC_LEN;
mem_malloc_brk = mem_malloc_start;
memset ((void *) mem_malloc_start, 0,
mem_malloc_end - mem_malloc_start);
}
- 初始化堆管理器
- 传入值为
CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE
,则是0xc3e00000 + 2*1024*1024 - (0x4000 + 896*1024) - 512*1024
,最终结果为0xc3e9c000
- 从代码可以看到堆的大小为896K
- 这个地址在u-boot之start_armboot分析(一)中的
内存分布
一节中画出了大概位置
mmc初始化
int mmc_initialize(bd_t *bis)
{
struct mmc *mmc;
int err;
INIT_LIST_HEAD(&mmc_devices);
cur_dev_num = 0;
if (board_mmc_init(bis) < 0)
cpu_mmc_init(bis);
#if defined(DEBUG_S3C_HSMMC)
print_mmc_devices(',');
#endif
#ifdef CONFIG_CHECK_X210CV3
mmc = find_mmc_device(1);//lqm
#else
mmc = find_mmc_device(0);
#endif
if (mmc) {
err = mmc_init(mmc);
if (err)
err = mmc_init(mmc);
if (err) {
printf("Card init fail!\n");
return err;
}
}
printf("%ldMB\n", (mmc->capacity/(1024*1024/(1<<9))));
return 0;
}
- 初始化一些SoC内部的控制器
- 最后打印容量,capacity以扇区为单位的,一个扇区是512字节。1左移9位也就是512。本应该先将扇区转换为字节,即
capacity*(1<<9)
,然后再除以1M(1024*1024)
,但是capacity*512后可能超过了范围,因此按照上面的写法
环境变量重定位env_relocate
- 此功能完成从SD卡中将环境变量读取到DDR中的任务
- SD卡有独立的扇区作为环境变量的存储区域。但是我们烧录系统时,只是烧录了uboot,kernel以及rootfs分区。所以当我们烧录完第一次启动时环境变量分区是空的,本次启动uboot尝试去SD卡的环境变量分区读取数据时失败(读取回来后进行CRC校验时失败),uboot选择从uboot内部代码中设置的一套默认的环境变量出发来使用(这就是默认环境变量),然后通过
saveenv
命令写入环境变量分区 - 真正的从SD卡到DDR中重定位ENV的代码是在env_relocate_spec内部的movi_read_env
IP与MAC地址的确定
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
/* MAC Address */
{
int i;
ulong reg;
char *s, *e;
char tmp[64];
i = getenv_r ("ethaddr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
- 通过读取环境变量来确定IP与MAC地址
硬件设备初始化
- 通过函数
devices_init ();
完成
初始化loadaddr、bootfile
/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
#if defined(CONFIG_CMD_NET)
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));
}
#endif
- 从环境变量中获取这两个值,在启动Linux内核时会参考它们
LCD初始化和显示Logo
- 接近最后了,用来初始化屏幕并显示Logo
系统升级
- 最后提供了通过SD卡升级本地系统的机制
完成
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
- 最后进入死循环,提供与用户的交互功能