u-boot-2012.10移植(二)MMC启动

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提供了启动设备的复制函数:
Device Copy Function Pointer
Definition MMC Block Copy Function
根据手册,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的总块数。

mmcexample

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值