GNU ARM汇编--(十八)u-boot-采用nand_spl方式的启动方法
%_config::unconfig
@$(MKCONFIG) -A $(@:_config=)
奇怪的就是在下面一点点有:
#########################################################################
## ARM1176 Systems
#########################################################################
smdk6400_noUSB_config
smdk6400_config :unconfig
@mkdir -p $(obj)include $(obj)board/samsung/smdk6400
@mkdir -p $(obj)nand_spl/board/samsung/smdk6400
@echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
@if [ -z "$(findstring smdk6400_noUSB_config,$@)" ]; then
echo "RAM_TEXT = 0x57e00000" >> $(obj)board/samsung/smdk6400/config.tmp;
else
echo "RAM_TEXT = 0xc7e00000" >> $(obj)board/samsung/smdk6400/config.tmp;
fi
@$(MKCONFIG) smdk6400armarm1176 smdk6400 samsung s3c64xx
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
当时看到这个觉得奇怪,在新版本的uboot中其他板子的配置都用%_config的目标,你丫的smdk6400凭什么单独搞一个目标出来,好奇的去看下nand_spl目录,并且make smdk6400_config和make看了下配置的过程和编译的过程,当时初步搞清楚了这是个神马情况:
在nand_spl目录下有个nand_boot.c,从这个文件名看上去倒是与从nand启动有关的,说到nand启动方式我要插一句:因为我是在装有ubuntu的破本子下进行GNU ARM汇编系列的学习的,因为是本子,所以没有并口,没有串口,只有搞个usb转串口来用,用不起jlink这样高级的玩意儿,因为是个破本子,win跑的不爽,干脆就跑linux了.所以我的板子里的nor flash我是一点都不敢动的,只能用nand flash,因此对nand flash启动的过程还是比较熟悉的.那为什么s3c2440从nand flash启动必须要用到内部那4K大小的sram,按照datasheet的解释是这样的:从nand启动时,一定要设置OM[0:1]这个拨码开关,将内部的4K大小的sram映射到0x00000000处,因为arm启动的时候都是从0x00000000开始的.而samsung的设计是在这种情况下nand中前4K大小的数据会由硬件load到sram中,这样依靠这4Ksram就可以从nand启动了.那为什么必须要这个4K的sram才可以做到nand启动了,根据一些前辈的说法和自己的理解,主要原因有二:第一nand flash的操作是需要控制器的,而soc在启动时,一条指令都没来的及执行,如何初始化控制器,控制器都没有初始化,那么又如何拿的到nand flash上面的指令;第二nand flash本身只能页读,cpu从nand无法取到一条32bit的指令,另外对于跳转指令,nand flash就傻眼了,nand flash没办法这样随机读.
说是插一句话,不经意插了一段,另起一段:
在nand_spl/board/samsung/smdk6400文件下有config.mk,Makefile和u-boot.lds三个文件,看看这三个文件再加上uboot根目录下的makefile文件就可以大概明白nand_spl这种方式是如何实现的了:
在uboot根目录下的makefile中有:
$(obj)u-boot-nand.bin:nand_spl $(obj)u-boot.bin
cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin
是将两个bin档用这种方式合并成一个bin档!!!
老实说,在做自己的bootloader的时候我也有这种想法,没想到在自己动手移植uboot的时候就发现新的uboot也采用了这种方式,有点小得意,^_^
更具体点说,就是在nand_spl目录下的u-boot-spl.bin做了以下事情:
1.设置cpu为svc模式
2.关闭开门狗和中断
3.初始化系统时钟
4.禁用MMU和Cache
5.初始化sdram控制器
6.设置sp,跳到刚才提到的nand_boot.c里面的nand_boot函数,这个函数初始化nand的控制器,并将4K之后的u-boot.bin image从nand中load到sdram中,然后跳转到u-boot.bin image的开始处继续后续的工作
为了实现这个u-boot-spl-16k.bin,可以照下列的步骤实施:
1.在uboot根目录下的makefile中新增一个目标:
######################################################################
#TQ2440 by Baikal
######################################################################
TQ2440_config: unconfig
@echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
#echo "RAM_TEXT = 0x33000000" > $(obj)board/samsung/TQ2400/config.tmp;
@$(MKCONFIG) TQ2440 arm arm920t - samsung s3c24x0
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
2.在nand_spl/board/samsung下新建文件夹TQ2440,可以将smdk6400目录下的三个文件复制过来再慢慢修改,最大的修改就是makefile的改动:
start.S用的是arch/arm/cpu/arm920t/start.S
lowlevel_init.S用的是board/samsung/smdk2410/lowlevel_init.S
nand_boot.c用的是nand_spl/nand_boot.c
s3c2440_nand.c用的是drivers/mtd/nand/s3c2440_nand.c
3.移植s3c2440_nand的代码
4.根据具体情况在start.S中将部分代码用#ifdef CONFIG_NAND_SPL或者#ifndef CONFIG_NAND_SPL包起来
5.最后的编译链接过程是链接出一个u-boot-spl文件,从u-boot-spl文件中剥离出二进制数据文件u-boot-spl.bin,实际上这个bin档才1.2k左右,将其填充到4K大小
如果对bootloader有一定理解,并且熟悉编译链接和makefile等脚本的话,单单这个工作量不大,忘记了还要熟悉nand flash的控制.
最后,说一下我在这个过程中遇到一个耽误了我好久的一个问题,忘记在跳nand_boot.c也要设置sp.因为只能通过led来调试,看到的现象让我错误的以为是我的nand flash驱动没调对.最后才恍然明了.当时看那几个led也是看的烦躁了....
just go on,戒躁
评论