从本节开始,就正式进入移植过程,首先进行u-boot-spl.bin的移植。
一、因为第一步要移植u-boot-spl.bin,所以我们需要先在头文件里添加宏CONFIG_SPL
u-boot-2016.09$ vim include/configs/tq210.h
#define CONFIG_SPL
二、时钟初始化
由上节分析,由于我们没有定义宏CONFIG_SKIP_LOWLEVEL_INIT,所以进入board/samsung/tq210/lowlevel_init.S进行硬件初始化。
首先添加S5PV210的时钟相关寄存器:
u-boot-2016.09$ vim arch/arm/mach-s5pv210/include/mach/clock.h
由于现在的操作只需要在 u-boot-spl.bin 中进行,因此这里使用 CONFIG_SPL_BUILD 宏来控制,当编译u-boot-spl.bin 才会将这些初始化代码编译进 u-boot-spl.bin,而编译 u-boot.bin 时就不会。修改lowlevel_init.S如下:
并在tq210.c中加入clock头文件并实现clock_init(这里也如lowlevel_init.S使用CONFIG_SPL_BUILD 来控制编译顺序):
在clock_init的实现函数中,使用了struct s5pv210_clock const clock = (struct s5pv210_clock )samsung_get_base_clock(),其中samsung_get_base_clock,在arch/arm/mach-s5pv210/include/mach/cpu.h中实现:
将其修改为
三、DDR初始化
u-boot-2016.09$ vim board/samsung/tq210/lowlevel_init.S
添加DMC信息,参考《嵌入式Linux学习笔记(基于s5pv210、tq210)》,这里就不详细贴出来了。
在tq210.c中添加dmc的头文件并实现ddr_init。
#include <asm/arch/dmc.h>
在arch/arm/mach-s5pv210/include/mach/cpu.h中添加宏
#define S5PV210_DMC0_BASE 0xF0000000
#define S5PV210_DMC1_BASE 0xF1400000
SAMSUNG_BASE(dmc0, DMC0_BASE)
SAMSUNG_BASE(dmc1, DMC1_BASE)
S5PV210_DMC0_BASE与S5PV210_DMC1_BASE在第一节我们已经定义了,如果没有定义,这里自己定义
接着执行到_main函数,
由于u-boot-spl.bin文件比较小,使用SRAM提供栈内存就好,所以可以将栈指针屏蔽掉,修改为:
五、拷贝BL2到SDRAM
在tq210.c中实现拷贝函数,拷贝完成后,直接跳转到DDR的起始地址执行 BL2。
CONFIG_SYS_SDRAM_BASE 在 u-boot-2014.04/include/configs/smdkv210.h 中定义,我们将其修改为我们实际 DDR 的起始地址0x20000000,CopySDMMCtoMem实现从SD的34扇区复制BL2到到DDR的起始地址0x20000000。
注:
因为BL1最大只能到16K,而每个扇区的大小为512B,16K正好是32个扇区,所以为了安全起见,我们将BL2的起始扇区设置为34。这个值并不固定,只要比u-boot-spl.bin的大小大就可以了。
四、编译
u-boot-2016.09$ make tq210_defconfig
u-boot-2016.09$ make spl/u-boot-spl.bin
发现会出现No rule to make target ‘checkarmreloc’, needed by ‘all’,修改arch/arm/mach-s5pv210/Kconfig,添加SPL选项
修改configs/tq210_defconfig,添加CONFIG_SPL=y
再次编译,发现出现mkexynosspl:Command not find。分析scripts/Makefile.spl
如果定义了CONFIG_SUMSANG,就会添加目标(obj)/$(BOARD)-spl.bin,展开即为spl/tq210-spl.bin,这里需要一个添加头文件的工具。
我这里的工具是使用的国嵌的mkv210,将其复制到tool下,将名字改为mktq210spl,修改
scripts/Makefile.spl
再次编译,发现已经产生了我们需要的spl/tq210-spl.bin。
五、烧录与测试
单独的.bin文件启动看不到现象,这里我在board/samsung/tq210/lowlevel_init.S中添加了蜂鸣器鸣叫的片段。
.globl lowlevel_init
lowlevel_init:
mov r9, lr
#ifdef CONFIG_SPL_BUILD
bl clock_init /* 时钟初始化 */
bl beep_asm_init
bl delay
bl beep_asm_off
bl ddr_init /* DDR初始化 */
bl uart_asm_init
#endif
mov pc, r9
/*
* beep_asm_init: 初始化蜂鸣器,并让其发声
*/
beep_asm_init:
ldr r0, = 0xE02000A0
ldr r1, = 0x00000010
str r1, [r0]
ldr r0, = 0xE02000A4
ldr r1, = 0x2
str r1, [r0]
mov pc, lr
/*
* delay: 延时
*/
delay:
mov r0, #0x2000000
delay_loop:
sub r0, r0, #1
cmp r0, #0
bne delay_loop
mov pc, lr
/*
* beep_asm_off: 关闭蜂鸣器
*/
beep_asm_off:
ldr r0, = 0xE02000A4
ldr r1, = 0x0
str r1, [r0]
mov pc, lr
为了偷懒,我直接使用了网上搜索的TQ210的裸机LED程序,编译得到led.bin。
烧录测试:
使用DD_for_win7.exe将tq210-spl.bin与led.bin分别烧入1和34扇区
然后将SD卡插入开发板,打开电源,发现蜂鸣器鸣叫一声,并且LED不停闪烁,表示我们tq210-spl.bin移植成功。
注:
DD_for_win7.exe有添加头字节选项,如果我们使用tq210-spl.bin就不需要选择这个选项,如果使用u-boot-spl.bin就必须将这个选项勾上。