在这节,我们要完成u-boot-spl.bin移植,并且通过这个程序,拷贝我们自己写的一个led程序到内存,让led灯点亮,首先我们回顾一下u-boot-spl.bin的整个运行过程:
1. 运行 arch/arm/cpu/armv7/start.S 文件,设置异常向量表,关闭中断,设置处理器到svc模式,然后执行 cup_init_cp15这个段,从字面意思理解是初始化cp15。然后跳转到cpu_init_crit。在cpu_init_crit中调用 board/samsung/tiny210/lowlevel_init.S中lowlevel_init。
2. 在lowlevel_init中主要做了两件事情:system_clock_init和ddr_init。
3. 返回 arch/arm/cpu/armv7/start.S 中,然后跳转到函数_main,这个函数在 u-boot-2014.04/arch/arm/lib/crt0.S 中定义。
现在我们开始分析函数_main:
这里在设置栈指针,由于 u-boot-spl.bin 相当小,在芯片固化BL0中,已经设置了堆栈,看下面截图就很清楚:
所以,我们使用 SRAM 为其提供栈内存就够了,所以可以将这里的栈指针设置代码屏蔽掉(为 u-boot-spl.bin 屏蔽,对 u-boot.bin 没有影响) ,如下:
这里调用了一个函数 copy_bl2_to_ram,用于从 SD 卡或 NAND 拷贝 BL2 到 SDRAM在 u-boot-2014.04/board/samsung/tiny210/tiny210.c 中实现它:
void copy_bl2_to_ram(void)
{
/*
** ch: 通道
** sb: 起始块
** bs: 块大小
** dst: 目的地
** i: 是否初始化
*/
#define CopySDMMCtoMem(ch, sb, bs, dst, i) \
(((unsigned char(*)(int, unsigned int, unsigned short, unsigned int*, unsigned char))\
(*((unsigned int *)0xD0037F98)))(ch, sb, bs, dst, i))
unsigned int V210_SDMMC_BASE = *(volatile unsigned int *)(0xD0037488); // V210_SDMMC_BASE
unsigned char ch = 0;
/* 参考S5PV210手册7.9.1 SD/MMC REGISTER MAP */
if (V210_SDMMC_BASE == 0xEB000000) // 通道0
ch = 0;
else if (V210_SDMMC_BASE == 0xEB200000) // 通道2
ch = 2;
CopySDMMCtoMem(ch, 32, 400, (unsigned int *)CONFIG_SYS_SDRAM_BASE, 0);
}
拷贝完成后,直接跳转到 DDR的起始地址执行 BL2。CONFIG_SYS_SDRAM_BASE 在 u-boot-2014.04/include/configs/tiny210.h 中定义,我们将其修改为我们实际 DDR 的起始地址 0x20000000
为什么是 32?三星手册明确规定 BL1 的大小最大为 16KB,而每一个扇区为 512B,16KB 刚好在扇区 32。这不
是强制要求的,只要这个数字乘以 512 小于你的 u-boot-spl.bin 就可以了。
现在执行 make spl/u-boot-spl.bin,出现错误,分析 u-boot-2014.04/spl/Makefile知道 ,我们的sp5v210是需要加头文件的:
根据规则,我们应该把我们的加头文件命名为mktiny210spl并放在tools目录下:
然后修改 u-boot-2014.04/spl/Makefile :
现在再次执行 make spl/u-boot-spl.bin 编译,最终生成 spl/smdkv210-spl.bin,已经添加了 16B 头信息:
编译成功!
然后把是先准备好的led测试程序通过tiny210-u-boot-spl.bin 从sd卡的32处拷贝到内存运行。插入sd卡 在终端下运行:
观察核心板上的led四盏灯都亮了。说明tiny210-u-boot-spl.bin 移植成功!
这是移植好的程序,有需要的可以下载看看:tiny210_uboot_2014.04_v1.0 下节我们正式开始u-boot.bin 的移植也就是BL2.