uboot-2010-03移植到tiny6410(1)

一、s3c6410启动流程

要移植uboot到tiny6410,首先需要弄清楚tiny6410的启动流程,下面是三星官方文档给出的启动流程图
这里写图片描述

从流程图中可以看到需要4步:
1、上电后先运行IROM里面的代码,芯片厂商固定好,进行硬件初始化,包括系统时钟初始化,D-TCM初始化等,这部分叫BL0。
2、iRom在初始化完后会把外部启动设备(nand flash、sd卡等)中的bootloader的前4K拷贝到stepping stone中,然后调到stepping stone中运行,这部分叫BL1。
3、BL1会初始化系统时钟,串口和内存,初始化完后,会把剩余的bootloader从启动设备拷贝到内存,这部分叫BL2。
4、拷贝完后跳到内存运行,之后就是加载内核、文件系统等。

大致的步骤就是这样,步骤1已经是固定好的,我们需要移植的是步骤2、3、4。
先下载好uboot-2010-03版本的uboot源码,在官方上好像下载不了,可以在这里下载:
http://download.csdn.net/detail/atmega_chen/9795885

二、uboot-2010-03 移植前分析
1、什么是nand spl
在下载好源码,解压后,移植前先分析uboot的编译流程和移植方向。因为2010-03版本的uboot加了nand spl,之前使用的版本并未使用到nand spl,所以会分析有nand spl和无nand spl的区别已经移植的。
nand spl也就是一个包含uboot前面4k大小的bin文件,在生成的时候uboot的总文件的时候会将4k的bin文件和u-boot.bin合并成一个大小为256k的u-boot-nand.bin。下面根据源码具体分析有nand spl和无nand spl的区别。

2、nand spl生成分析
由于我们要移植的是tiny6410,uboot2010-03中并没有支持tiny6410,但是有支持smdk6400,所以我们先用smdk6400的代码分析。
先看到根目录下面的Makefile,在6400配置规则里面当执行make smdk6400的时候会把CONFIG_NAND_U_BOOT宏定义写入到include/config.mk里面去,编译的时候会调用。

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
        @if [ -z "$(findstring smdk6400_noUSB_config,$@)" ]; then                       \
                echo "RAM_TEXT = 0x57e00000" >> $(obj)board/samsung/smdk6400/config.tmp;\
                $(MKCONFIG) $(@:_config=) arm arm1176 smdk6400 samsung s3c64xx;         \
        else                                                                            \
                echo "RAM_TEXT = 0xc7e00000" >> $(obj)board/samsung/smdk6400/config.tmp;\
                $(MKCONFIG) $(@:_noUSB_config=) arm arm1176 smdk6400 samsung s3c64xx;   \
        fi
        @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk

然后找到这个宏使用的地方,这里就是说如果有定义CONFIG_NAND_U_BOOT,就定义NAND_SPL和U_BOOT_NAND这两个变量,这两个变量有什么用呢。

ifeq ($(CONFIG_NAND_U_BOOT),y)
NAND_SPL = nand_spl
U_BOOT_NAND = $(obj)u-boot-nand.bin
endif

我们先看到Makefile的总生成目标,可以看到总的生成目标里面有u-boot.srec,u-boot.bin和U_BOOT_NAND,也就是u-boot-nand.bin

# Always append ALL so that arch config.mk's can add custom ones
ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)

all:            $(ALL)

在往下找U_BOOT_NAND的生产规则,u-boot-nand.bin依赖NAND_SPL和u-boot.bin,其中u-boot.bin的生成不分析就是正常的uboot生成u-boot.bin的流程,主要分析NAND_SPL的生成。如果依赖关系满足,那么就将u-boot-spl-16k.bin和u-boot.bin这个两个文件合并成u-boot-nand.bin。其中u-boot-spl-16k.bin这个文件的生成,就是根据依赖NAND_SPL来生成,具体怎么生成往下分析。

$(U_BOOT_NAND): $(NAND_SPL) $(obj)u-boot.bin
                cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin

搜索NAND_SPL的生成规则,这条规则会去编译nand_spl/board/ (BOARDDIR) (BOARDDIR)就是samsung目录。

$(NAND_SPL):    $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk
                $(MAKE) -C nand_spl/board/$(BOARDDIR) all

进入到nand_spl/board/samsung/smdk6400目录,看到一开始只有三个文件。
这里写图片描述

这里就是nand spl的关键所在,也就说前面只要定义了CONFIG_NAND_U_BOOT就会编译nand spl这个目录,那么编译出来的是什么东西呢?打开Makefile看看。
首先定义了CONFIG_NAND_SPL = y,这个宏比较重要,后面会介绍用处。

CONFIG_NAND_SPL = y

include $(TOPDIR)/config.mk
include $(TOPDIR)/nand_spl/board/$(BOARDDIR)/config.mk

LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds
LDFLAGS = -Bstatic -T $(nandobj)u-boot.lds -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
AFLAGS  += -DCONFIG_NAND_SPL
CFLAGS  += -DCONFIG_NAND_SPL

SOBJS   = start.o cpu_init.o lowlevel_init.o
COBJS   = nand_boot.o nand_ecc.o s3c64xx.o

SRCS    := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
OBJS    := $(addprefix $(obj),$(SOBJS) $(COBJS))
__OBJS  := $(SOBJS) $(COBJS)
LNDIR   := $(OBJTREE)/nand_spl/board/$(BOARDDIR)

nandobj := $(OBJTREE)/nand_spl/

ALL = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin

all:    $(obj).depend $(ALL)

$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl
    $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@

$(nandobj)u-boot-spl.bin:	$(nandobj)u-boot-spl
    $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

$(nandobj)u-boot-spl:	$(OBJS) $(nandobj)u-boot.lds
    cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \
        -Map $(nandobj)u-boot-spl.map \
        -o $(nandobj)u-boot-spl

$(nandobj)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)/cpu/arm1176/start.S $@

# from SoC directory
$(obj)cpu_init.S:
    @rm -f $@
    @ln -s $(TOPDIR)/cpu/arm1176/s3c64xx/cpu_init.S $@

# from board directory
$(obj)lowlevel_init.S:
    @rm -f $@
    @ln -s $(TOPDIR)/board/samsung/smdk6400/lowlevel_init.S $@

# from nand_spl directory
$(obj)nand_boot.c:
    @rm -f $@
    @ln -s $(TOPDIR)/nand_spl/nand_boot.c $@

# from drivers/mtd/nand directory
$(obj)nand_ecc.c:
    @rm -f $@
    @ln -s $(TOPDIR)/drivers/mtd/nand/nand_ecc.c $@

$(obj)s3c64xx.c:
    @rm -f $@
    @ln -s $(TOPDIR)/drivers/mtd/nand/s3c64xx.c $@

#########################################################################

$(obj)%.o:	$(obj)%.S
    $(CC) $(AFLAGS) -c -o $@ $<

$(obj)%.o:	$(obj)%.c
    $(CC) $(CFLAGS) -c -o $@ $<

# defines $(obj).depend target
include $(SRCTREE)/rules.mk

sinclude $(obj).depend

###################

通过ALL总目标可以知道这个Makefile编译生成的文件u-boot-spl,u-boot-spl.bin和u-boot-spl-16k.bin。其中u-boot-spl-16k.bin就是前面提到的合成u-boot-nand.bin需要的文件,这个文件具体有什么用呢。

ALL     = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin

可以看到u-boot-spl-16k.bin依赖u-boot-spl

$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl
        $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@

u-boot-spl依赖$(OBJS)和u-boot.lds

$(nandobj)u-boot-spl:   $(OBJS) $(nandobj)u-boot.lds
        cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \
                -Map $(nandobj)u-boot-spl.map \
                -o $(nandobj)u-boot-spl

$(OBJS)又依赖start.s,cpu_init.s等等,但是这个目录下面并没有这些源文件,那是如何编译出.o文件的呢,往下看。

SOBJS   = start.o cpu_init.o lowlevel_init.o
COBJS   = nand_boot.o nand_ecc.o s3c64xx.o

SRCS    := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
OBJS    := $(addprefix $(obj),$(SOBJS) $(COBJS))
__OBJS  := $(SOBJS) $(COBJS)
LNDIR   := $(OBJTREE)/nand_spl/board/$(BOARDDIR)

这些源文件其实都是软连接,连接到不同的目录下面去,所以这个nand spl编译出来的u-boot-spl-16k.bin其实就是包含start.S的uboot的前4K的头部,具体这个头部和以前是有的u-boot.bin有什么不同呢,分析一下start.S就知道了。

# from cpu directory
$(obj)start.S:
        @rm -f $@
        @ln -s $(TOPDIR)/cpu/arm1176/start.S $@

# from SoC directory
$(obj)cpu_init.S:
        @rm -f $@
        @ln -s $(TOPDIR)/cpu/arm1176/s3c64xx/cpu_init.S $@

# from board directory
$(obj)lowlevel_init.S:
        @rm -f $@
        @ln -s $(TOPDIR)/board/samsung/smdk6400/lowlevel_init.S $@

# from nand_spl directory
$(obj)nand_boot.c:
        @rm -f $@
        @ln -s $(TOPDIR)/nand_spl/nand_boot.c $@

# from drivers/mtd/nand directory
$(obj)nand_ecc.c:
        @rm -f $@
        @ln -s $(TOPDIR)/drivers/mtd/nand/nand_ecc.c $@

$(obj)s3c64xx.c:
        @rm -f $@
        @ln -s $(TOPDIR)/drivers/mtd/nand/s3c64xx.c $@

3、nand spl作用
打开u-boot-2010.03/cpu/arm1176/start.S,搜索CONFIG_NAND_SPL
可以看到有三个地方用到了#ifndef CONFIG_NAND_SPL,而这个宏在哪里定义呢,就是我们前面分析的nand spl的Makefile,一开始就定义了这个宏,所以可以知道在u-boot-spl-16k.bin这个文件中,这个宏是被定义的,但是在u-boot.bin这个文件中这个宏是没有被定义的,这样做有什么用呢。

#include <config.h>
#include <version.h>
#ifdef CONFIG_ENABLE_MMU
#include <asm/proc/domain.h>
#endif
#include <asm/arch/s3c6400.h>

#if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)
#define CONFIG_SYS_PHY_UBOOT_BASE   CONFIG_SYS_UBOOT_BASE
#endif

/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */

.globl _start
_start: b   reset
#ifndef CONFIG_NAND_SPL
    ldr pc, _undefined_instruction
    ldr pc, _software_interrupt
    ldr pc, _prefetch_abort
    ldr pc, _data_abort
    ldr pc, _not_used
    ldr pc, _irq
    ldr pc, _fiq

_undefined_instruction:
    .word undefined_instruction
_software_interrupt:
    .word software_interrupt
_prefetch_abort:
    .word prefetch_abort
_data_abort:
    .word data_abort
_not_used:
    .word not_used
_irq:
    .word irq
_fiq:
    .word fiq
_pad:
    .word 0x12345678 /* now 16*4=64 */
#else
    . = _start + 64
#endif

.global _end_vect
_end_vect:
    .balignl 16,0xdeadbeef
/*
 *************************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don't start from memory!
 * setup Memory and board specific bits prior to relocation.
 * relocate armboot to ram
 * setup stack
 *
 *************************************************************************
 */

_TEXT_BASE:
    .word   TEXT_BASE

/*
 * Below variable is very important because we use MMU in U-Boot.
 * Without it, we cannot run code correctly before MMU is ON.
 * by scsuh.
 */
_TEXT_PHY_BASE:
    .word   CONFIG_SYS_PHY_UBOOT_BASE

.globl _armboot_start
_armboot_start:
    .word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
    .word __bss_start

.globl _bss_end
_bss_end:
    .word _end

/*
 * the actual reset code
 */

reset:
    /*
     * set the cpu to SVC32 mode
     */
    mrs r0, cpsr
    bic r0, r0, #0x3f
    orr r0, r0, #0xd3
    msr cpsr, r0

/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */
    /*
     * we do sys-critical inits only at reboot,
     * not when booting from ram!
     */
cpu_init_crit:
    /*
     * When booting from NAND - it has definitely been a reset, so, no need
     * to flush caches and disable the MMU
     */
#ifndef CONFIG_NAND_SPL
    /*
     * flush v4 I/D caches
     */
    mov r0, #0
    mcr p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
    mcr p15, 0, r0, c8, c7, 0   /* flush v4 TLB */

    /*
     * disable MMU stuff and caches
     */
    mrc p15, 0, r0, c1, c0, 0
    bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
    bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
    orr r0, r0, #0x00000002 @ set bit 2 (A) Align
    orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
    /* Prepare to disable the MMU */
    adr r1, mmu_disable_phys
    /* We presume we're within the first 1024 bytes */
    and r1, r1, #0x3fc
    ldr r2, _TEXT_PHY_BASE
    ldr r3, =0xfff00000
    and r2, r2, r3
    orr r2, r2, r1
    b   mmu_disable

    .align 5
    /* Run in a single cache-line */
mmu_disable:
    mcr p15, 0, r0, c1, c0, 0
    nop
    nop
    mov pc, r2
#endif

mmu_disable_phys:
    /* Peri port setup */
    ldr r0, =0x70000000
    orr r0, r0, #0x13
    mcr p15,0,r0,c15,c2,4       @ 256M (0x70000000 - 0x7fffffff)

    /*
     * Go setup Memory and board specific bits prior to relocation.
     */
    bl  lowlevel_init       /* go setup pll,mux,memory */

after_copy:
#ifdef CONFIG_ENABLE_MMU
enable_mmu:
    /* enable domain access */
    ldr r5, =0x0000ffff
    mcr p15, 0, r5, c3, c0, 0   /* load domain access register */

    /* Set the TTB register */
    ldr r0, _mmu_table_base
    ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE
    ldr r2, =0xfff00000
    bic r0, r0, r2
    orr r1, r0, r1
    mcr p15, 0, r1, c2, c0, 0

    /* Enable the MMU */
    mrc p15, 0, r0, c1, c0, 0
    orr r0, r0, #1      /* Set CR_M to enable MMU */

    /* Prepare to enable the MMU */
    adr r1, skip_hw_init
    and r1, r1, #0x3fc
    ldr r2, _TEXT_BASE
    ldr r3, =0xfff00000
    and r2, r2, r3
    orr r2, r2, r1
    b   mmu_enable

    .align 5
    /* Run in a single cache-line */
mmu_enable:

    mcr p15, 0, r0, c1, c0, 0
    nop
    nop
    mov pc, r2
#endif

skip_hw_init:
    /* Set up the stack                         */
stack_setup:
    ldr r0, =CONFIG_SYS_UBOOT_BASE  /* base of copy in DRAM     */
    sub r0, r0, #CONFIG_SYS_MALLOC_LEN  /* malloc area                      */
    sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                        */
    sub sp, r0, #12     /* leave 3 words for abort-stack    */

clear_bss:
    ldr r0, _bss_start      /* find start of bss segment        */
    ldr r1, _bss_end        /* stop here                        */
    mov     r2, #0          /* clear                            */

clbss_l:
    str r2, [r0]        /* clear loop...                    */
    add r0, r0, #4
    cmp r0, r1
    ble clbss_l

#ifndef CONFIG_NAND_SPL
    ldr pc, _start_armboot

_start_armboot:
    .word start_armboot
#else
    b   nand_boot
/*  .word nand_boot*/
#endif

#ifdef CONFIG_ENABLE_MMU
_mmu_table_base:
    .word mmu_table
#endif

#ifndef CONFIG_NAND_SPL
/*
 * we assume that cache operation is done before. (eg. cleanup_before_linux())
 * actually, we don't need to do anything about cache if not use d-cache in
 * U-Boot. So, in this function we clean only MMU. by scsuh
 *
 * void theLastJump(void *kernel, int arch_num, uint boot_params);
 */
#ifdef CONFIG_ENABLE_MMU
    .globl theLastJump
theLastJump:
    mov r9, r0
    ldr r3, =0xfff00000
    ldr r4, _TEXT_PHY_BASE
    adr r5, phy_last_jump
    bic r5, r5, r3
    orr r5, r5, r4
    mov pc, r5
phy_last_jump:
    /*
     * disable MMU stuff
     */
    mrc p15, 0, r0, c1, c0, 0
    bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
    bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
    orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
    orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
    mcr p15, 0, r0, c1, c0, 0

    mcr p15, 0, r0, c8, c7, 0   /* flush v4 TLB */

    mov r0, #0
    mov pc, r9
#endif
/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE    72

#define S_OLD_R0    68
#define S_PSR       64
#define S_PC        60
#define S_LR        56
#define S_SP        52

#define S_IP        48
#define S_FP        44
#define S_R10       40
#define S_R9        36
#define S_R8        32
#define S_R7        28
#define S_R6        24
#define S_R5        20
#define S_R4        16
#define S_R3        12
#define S_R2        8
#define S_R1        4
#define S_R0        0

#define MODE_SVC 0x13
#define I_BIT    0x80

/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 */

    .macro  bad_save_user_regs
    /* carve out a frame on current user stack */
    sub sp, sp, #S_FRAME_SIZE
    /* Save user registers (now in svc mode) r0-r12 */
    stmia   sp, {r0 - r12}

    ldr r2, _armboot_start
    sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
    /* set base 2 words into abort stack */
    sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
    /* get values for "aborted" pc and cpsr (into parm regs) */
    ldmia   r2, {r2 - r3}
    /* grab pointer to old stack */
    add r0, sp, #S_FRAME_SIZE

    add r5, sp, #S_SP
    mov r1, lr
    /* save sp_SVC, lr_SVC, pc, cpsr */
    stmia   r5, {r0 - r3}
    /* save current stack into r0 (param register) */
    mov r0, sp
    .endm

    .macro get_bad_stack
    /* setup our mode stack (enter in banked mode) */
    ldr r13, _armboot_start
    /* move past malloc pool */
    sub r13, r13, #(CONFIG_SYS_MALLOC_LEN)
    /* move to reserved a couple spots for abort stack */
    sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8)

    /* save caller lr in position 0 of saved stack */
    str lr, [r13]
    /* get the spsr */
    mrs lr, spsr
    /* save spsr in position 1 of saved stack */
    str lr, [r13, #4]

    /* prepare SVC-Mode */
    mov r13, #MODE_SVC
    @ msr   spsr_c, r13
    /* switch modes, make sure moves will execute */
    msr spsr, r13
    /* capture return pc */
    mov lr, pc
    /* jump to next instruction & switch modes. */
    movs    pc, lr
    .endm

    .macro get_bad_stack_swi
    /* space on current stack for scratch reg. */
    sub r13, r13, #4
    /* save R0's value. */
    str r0, [r13]
    /* get data regions start */
    ldr r0, _armboot_start
    /* move past malloc pool */
    sub r0, r0, #(CONFIG_SYS_MALLOC_LEN)
    /* move past gbl and a couple spots for abort stack */
    sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8)
    /* save caller lr in position 0 of saved stack */
    str lr, [r0]
    /* get the spsr */
    mrs r0, spsr
    /* save spsr in position 1 of saved stack */
    str lr, [r0, #4]
    /* restore r0 */
    ldr r0, [r13]
    /* pop stack entry */
    add r13, r13, #4
    .endm

/*
 * exception handlers
 */
    .align  5
undefined_instruction:
    get_bad_stack
    bad_save_user_regs
    bl  do_undefined_instruction

    .align  5
software_interrupt:
    get_bad_stack_swi
    bad_save_user_regs
    bl  do_software_interrupt

    .align  5
prefetch_abort:
    get_bad_stack
    bad_save_user_regs
    bl  do_prefetch_abort

    .align  5
data_abort:
    get_bad_stack
    bad_save_user_regs
    bl  do_data_abort

    .align  5
not_used:
    get_bad_stack
    bad_save_user_regs
    bl  do_not_used

    .align  5
irq:
    get_bad_stack
    bad_save_user_regs
    bl  do_irq

    .align  5
fiq:
    get_bad_stack
    bad_save_user_regs
    bl  do_fiq
#endif /* CONFIG_NAND_SPL */

因为我们前面分析了uboot的启动流程知道,首先启动设备的前4K代码会被拷贝到steeping stone中去,这里通过前面分析知道
u-boot-nand.bin的前4k代码就是u-boot-spl-16k.bin这个文件,所以一开始这个u-boot-spl-16k.bin会被执行,然后会执行start.S,由于u-boot-spl-16k.bin中定义了CONFIG_NAND_SPL所以三个地方的#ifndef CONFIG_NAND_SPL的代码都会被跳过,这些代码主要是做一些硬件的初始化,堆栈的设置等,并且最后会执行b nand_boot。
和以前分析的uboot不一样,以前uboot在start.S中执行到最后都会把剩余的uboot拷贝到内存里面去了,然后执行start_armboot进入内存运行。但加了nand spl后,前面跳过了很多代码,并没有执行拷贝uboot到内存的操作,是在b nand_boot里面执行的。

#ifndef CONFIG_NAND_SPL
    ldr pc, _start_armboot

_start_armboot:
    .word start_armboot
#else
    b   nand_boot
/*  .word nand_boot*/
#endif

打开nand_spl/nand_boot.c找到nand_boot函数,这个函数先调用nand_load函数拷贝uboot到内存,具体拷贝的是什么样的uboot呢,找到这个几个宏定义

void nand_boot(void)
{
    struct nand_chip nand_chip;
    nand_info_t nand_info;
    int ret;
    __attribute__((noreturn)) void (*uboot)(void);

    /*
     * Init board specific nand support
     */
    nand_info.priv = &nand_chip;
    nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W = (void  __iomem *)CONFIG_SYS_NAND_BASE;
    nand_chip.dev_ready = NULL; /* preset to NULL */
    board_nand_init(&nand_chip);

    if (nand_chip.select_chip)
        nand_chip.select_chip(&nand_info, 0);

    /*
     * Load U-Boot image from NAND into RAM
     */
    ret = nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
            (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);

#ifdef CONFIG_NAND_ENV_DST
    nand_load(&nand_info, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
          (uchar *)CONFIG_NAND_ENV_DST);

#ifdef CONFIG_ENV_OFFSET_REDUND
    nand_load(&nand_info, CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
          (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
#endif
#endif

    if (nand_chip.select_chip)
        nand_chip.select_chip(&nand_info, -1);

    /*
     * Jump to U-Boot image
     */
    uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
    (*uboot)();
}

通过宏定义可以知道,从nand flash的第4K位置开始拷贝,拷贝的大小为252K,也就是说跳过u-boot-spl-16k.bin,将u-boot.bin整个拷贝到内存

#define CONFIG_SYS_NAND_U_BOOT_OFFS (4 * 1024)  /* Offset to RAM U-Boot image */

#define CONFIG_SYS_NAND_U_BOOT_SIZE (252 * 1024)    /* Size of RAM U-Boot image   */

#define CONFIG_SYS_NAND_U_BOOT_DST  CONFIG_SYS_PHY_UBOOT_BASE   /* NUB load-addr      */

然后将指针指到内存的起始地址处,开始执行u-boot.bin。u-boot.bin又重新开始从start.S开始执行,因为u-boot.bin中没有定义CONFIG_NAND_SPL,所以三个#ifndef CONFIG_NAND_SPL的代码都会被执行到,之前是没有执行到的,然后做一些硬件的初始化,堆栈设置等,最后跳到start_armboot。

4、nand spl比较分析
使用nand spl启动的话,一开始的start.S会跳过很多初始化的代码,直接到最后调用nand_boot函数加载完整的u-boot.bin到内存,然后重新运行uboot并进行初始化,这也就是为什么在start.S中看不到类似copy_uboot_to_ram这样的操作。如果不使用nand spl的话,在执行到start.S的时候,会执行一些初始化工作,并且最重要的一点是会在跳到start_armboot之前先把代码拷贝到内存,会有类似copy_uboot_to_ram这样的操作。并且不使用nand spl的话只需要生成u-boot.bin即可,不用生成两部分。

5、具体移植做法
通过前面分析可以知道,启动可以分使用nand spl和不使用nand spl启动,我会把两种启动方式都移植到tiny6410上,因为uboot-2010-03默认使用的就是使用nand spl的方式启动,所以先移植使用nand spl启动的方式,之后会移植不使用nand spl要如何修改。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值