1. 启动方式
6410支持SD/MMC Card, OneNand, Nand启动方式。由于我手上的这款开发板采用的MLC2的Nand Flash(K9GAG08U0E),适合1KBytes/12 bit 硬件ECC校验,而6410 最大支持 512 Bytes/8 bit 硬件ECC校验,所以S3C6410在硬件上根本就不支K9GAG08U0E,友善之臂采用了软件和硬件结合的ECC校验,没有提供开源代码。所以我也不打算折腾采用Nand启动的方式启动u-boot,而采用SD卡启动u-boot,然后使用TFTP下载linux内核,最后使用NFS启动文件系统。
2. 代码实现
上一篇文章已经基于s3c6400对Tiny6410的单板进行了复制,现在要在此基础上进行修改代码,实现SD卡启动u-boot。u-boot-2012.10支持spl,即将u-boot.bin分割成两部分,前4k被称作spl(nand-spl或者mmc-spl),前4k放在BL1, 整个u-boot.bin则放在BL2。系统上电时,由iROM里面的启动代码(BL0)自动将其复制到启动设备(SD卡或者Nand Flash)。然后由这4k代码(BL1)实现将u-boot.bin(BL2)移动到SDRAM中,最后跳转到起始地址进行u-boot的启动。
2.1 仿照nand-spl复制mmc-spl
u-boot-2012.10默认为nand-spl启动,没有提供mmc-spl的启动。因此需要仿照nand-spl复制mmc-spl。
[wf@localhost u-boot-2012.10]$ ls
api config.mk drivers lib nand_spl snapshot.commit
arch COPYING dts MAINTAINERS net spl
board CREDITS examples MAKEALL post test
boards.cfg disk fs Makefile README tools
common doc include mkconfig rules.mk
[wf@localhost u-boot-2012.10]$ cp -a nand_spl mmc_spl
[wf@localhost u-boot-2012.10]$ ls
api config.mk drivers lib mmc_spl rules.mk
arch COPYING dts MAINTAINERS nand_spl snapshot.commit
board CREDITS examples MAKEALL net spl
boards.cfg disk fs Makefile post test
common doc include mkconfig README tools
然后删除根nand相关的文件,并新建一个mmc_boot.c, 用于实现将u-boot的代码从SD卡复制到SDRAM中。
[wf@localhost mmc_spl]$ ls
board nand_boot.c nand_boot_fsl_elbc.c nand_boot_fsl_ifc.c nand_boot_fsl_nfc.c
[wf@localhost mmc_spl]$ rm *.c
[wf@localhost mmc_spl]$ ls
board
[wf@localhost mmc_spl]$ touch mmc_boot.c
[wf@localhost mmc_spl]$ ls
board mmc_boot.c
三星Internal ROM Application Note提供了启动设备的复制函数:
根据手册,SD卡的复制函数如下:
/**
**This Function copies SD/MMC Card Data to memory.
**Always use EPLL clock.
**@param channel(z): HSMMC Controller channel number
**@param StartBlkAddress(a): Source card(SD/MMC) Address.(It must be block address)
**@param blockSize(b): Number of block to copy.
**@param memoryPtr(c): Buffer to copy from.
**@param with init(e): reinitialize or not
**@return bool(unsigned char) - success or failure
*/
#define CopyMMCtoMem(z,a,b,c,e) ((((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool)) (*((unsigned int *)0x0C004008))))(z,a,b,c,e)
代码实现:
© Copyright 2011
Tekkaman Ninja, tekkamanninja at gmail.com
/*
* Copyright (C) 2011 Samsung Electronics
*
* (C) Copyright 2011
* Tekkaman Ninja, <tekkamanninja at gmail.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <asm/types.h>
#include <asm/io.h>
#include <config.h>
/* TCM function for bl2 load */
#if defined(CONFIG_S3C6400)
#define copy_sd_mmc_to_mem(a,b,c,d,e) \
(((int(*)(uint, ushort, uint *, uint, int))(*((uint *)(TCM_BASE + 0x8))))(a,b,c,d,e))
#elif defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)
#define copy_sd_mmc_to_mem(a,b,c,d,e) \
(((int(*)(int, uint, ushort, uint *, int))(*((uint *)(TCM_BASE + 0x8))))(a,b,c,d,e))
#endif
void copy_uboot_to_ram(void)
{
copy_sd_mmc_to_mem(MMC_BOOT_CHANNEL,
MMC_UBOOT_POS, MMC_UBOOT_BLKCNT, (uint *)(CONFIG_SYS_MMC_U_BOOT_START),
MMC_INIT_REQUIRED);
#ifdef CONFIG_MMC_ENV_DST
copy_sd_mmc_to_mem(MMC_BOOT_CHANNEL,
MMC_ENV_POS, MMC_ENV_BLKCNT, (uint *)CONFIG_MMC_ENV_DST,
MMC_INIT_REQUIRED);
#ifdef CONFIG_MMC_OFFSET_REDUND
copy_sd_mmc_to_mem(MMC_BOOT_CHANNEL,
MMC_ENV_POS_REDUND, MMC_ENV_BLKCNT, (uint *)CONFIG_MMC_ENV_DST+ CONFIG_ENV_SIZE,
MMC_INIT_REQUIRED);
#endif
#endif
}
void mmc_boot_copy(void)
{
volatile u32 *mmc_control4;
__attribute__((noreturn)) void (*uboot)(void);
if (MMC_BOOT_CHANNEL == 0) {
mmc_control4 = (volatile u32 *)0x7C20008C;
} else if (MMC_BOOT_CHANNEL == 1) {
mmc_control4 = (volatile u32 *)0x7C30008C;
} else if (MMC_BOOT_CHANNEL == 2) {
mmc_control4 = (volatile u32 *)0x7C40008C;
}
writel(readl(mmc_control4) | (0x3 << 16), mmc_control4);
copy_uboot_to_ram();
/*
* Jump to U-Boot image
*/
uboot = (void *)(CONFIG_SYS_MMC_U_BOOT_START);
(*uboot)();
}
这里解释一下这个函数:
这个函数将512K的u-boot(实际的u-boot.bin小于512K)从MMC卡复制到SRAM。 MMC的地址必须为块地址。
MMC_BOOT_CHANNEL = 0
配置从MMC控制器的通道
TCM_BASE = 0x0C004000
0x0C004000 是启动设备复制函数的基地址
MMC_TOTAL_BLKCNT = TCM_BASE - 0x4 = 0XC003FFC
根据“6410 Internal Rom Application Note”, 如果MMC用于启动设备,MMC的信息必须存储再特殊区域。 地址0XC003FFC用于存储MMC的块总计数。因此,本函数中MMC_TOTAL_BLKCNT就是MMC的总块数。
MMC_UBOOT_POS_BACKWARD = 0x300000
在MMC中给U-BOOT留出0x300000 Bytes(3MB)的空间
MMC_BLKSIZE = 512
MMC一个块的大小为512 Bytes
CONFIG_SYS_MMC_U_BOOT_SIZE = (512 * 1024)
配置u-boot的大小为512KB
MMC_UBOOT_POS
= (MMC_TOTAL_BLKCNT-(MMC_UBOOT_POS_BACKWARD/MMC_BLKSIZE))
= (MMC_TOTAL_BLKCNT - (3M/512))
= (MMC_TOTAL_BLKCNT - 6144)我使用的8GB SDHC的总块数为15523840
IROM所认为的总块数MMC_TOTAL_BLKCNT=15522816(15523840-1024)
所以nand_spl/u-boot-spl-16k.bin烧写的位置是15522798块(15522816-18)
u-boot.bin烧写的位置是15516672块(15522816-6144(3MB))
MMC_UBOOT_BLKCNT
= (CONFIG_SYS_MMC_U_BOOT_SIZE / MMC_BLKSIZE)
= (512 * 1024) / 512
配置的u-boot的大小为512KB, 除以512,算出UBOOT在MMC所需要占的块数。
CONFIG_SYS_MMC_U_BOOT_START
= CONFIG_SYS_PHY_UBOOT_BASE
= CONFIG_SYS_SDRAM_BASE + 0x07e00000
将U-BOOT从MMC复制到SDRAM的地址。
修改u-boot-2012.10/mmc_spl/board/samsung/tiny6410/Makefile:
#
# (C) Copyright 2006-2007
# Stefan Roese, DENX Software Engineering, sr@denx.de.
#
# (C) Copyright 2008
# Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
CONFIG_MMC_SPL = y
include $(TOPDIR)/config.mk
include $(TOPDIR)/mmc_spl/board/$(BOARDDIR)/config.mk
mmcobj := $(OBJTREE)/mmc_spl/
LDSCRIPT= $(TOPDIR)/mmc_spl/board/$(BOARDDIR)/u-boot.lds
LDFLAGS := -T $(mmcobj)u-boot.lds -Ttext $(CONFIG_SYS_TEXT_BASE) $(LDFLAGS) \
$(LDFLAGS_FINAL) -gc-sections
AFLAGS += -DCONFIG_MMC_SPL -DCONFIG_SPL_BUILD
CFLAGS += -DCONFIG_MMC_SPL -DCONFIG_SPL_BUILD -ffunction-sections
SOBJS = start.o cpu_init.o lowlevel_init.o
COBJS = mmc_boot.o tiny6410_mmc_spl.o
SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
__OBJS := $(SOBJS) $(COBJS)
LNDIR := $(mmcobj)board/$(BOARDDIR)
ALL = $(mmcobj)u-boot-spl $(mmcobj)u-boot-spl.bin $(mmcobj)u-boot-spl-16k.bin
all: $(obj).depend $(ALL)
$(mmcobj)u-boot-spl-16k.bin: $(mmcobj)u-boot-spl
$(OBJCOPY) ${
OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@
$(mmcobj)u-boot-spl.bin: $(mmcobj)u-boot-spl
$(OBJCOPY) ${
OBJCFLAGS} -O binary $< $@
$(mmcobj)u-boot-spl: $(OBJS) $(mmcobj)u-boot.lds
cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \
-Map $(mmcobj)u-boot-spl.map \
-o $(mmcobj)u-boot-spl
$(mmcobj)u-boot.lds: $(LDSCRIPT)
$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@
# create symbolic links for common files
# from cpu directory
$(obj)start.S:
@rm -f $@
@ln -s $(TOPDIR)/arch/arm/cpu/arm1176/start.S $@
# from SoC directory
$(obj)cpu_init.S:
@rm -f $@
@ln -s $(TOPDIR)/arch/arm/cpu/arm1176/s3c64xx/cpu_init.S $@
# from board directory
$(obj)lowlevel_init.S:
@rm -f $@
@ln -s $(TOPDIR)/board/samsung/tiny6410/lowlevel_init.S $@
# from mmc_spl directory
$(obj)mmc_boot.c:
@rm -f $@
@ln -s $(TOPDIR)/mmc_spl/mmc_boot.c $@
$(obj)tiny6410_mmc_spl.c:
@rm -f $@
@ln -s $(TOPDIR)/board/samsung/tiny6410/tiny6410_mmc_spl.c $@
#########################################################################
$(obj)%.o: $(obj)%.S
$(CC) $(AFLAGS) -c -o $@ $<
$(obj)%.o: $(obj)%.c
$(CC) $(CFLAGS) -c -o $@ $<
# defines $(obj).depend target
include $(SRCTREE