在移植2012.10过程中遇到个麻烦的问题,到写这篇文章的时候还是没找原因在哪,导致无法正常运行。我遇到的问题如下:__bss_start和__bss_end__这两个地址无法正确得到地址,也就是bss段清除的时候失败,程序死掉。使用前两篇文件介绍的bl1,且没有开启重定位功能的情况下board_init_f这个函数中的addr -= gd->mon_len;这句一定要修改成你的u-boot基址,也就是CONFIG_SYS_TEXT_BASE的值,否则会很痛苦的。
如果哪位朋友知道__bss_start和__bss_end__这个不能正确得到地址的原因,还麻烦指点指点,呵呵。
由于上面说到的原因,一直也不知道是哪里的问题,所以就放弃了这个2012.10版本u-boot的移植,进而使用了2013.10版本的u-boot。前两篇分别记录了独立的bl1和2012.10版本u-boot配合这个bl1实现的启动。这篇相对于前两篇的移植记录有些区别,最大的区别就是(不是版本问题哈,呵呵)该篇文章记录的是使u-boot-2013.10这个版本u-boot支持moviNAND_Fusing_Tool_v2.0.exe这个软件,也就是说,编译生成的u-boot.bin可以使用moviNAND_Fusing_Tool_v2.0.exe这个软件直接下载到SD卡中,并不需要在linux系统下输入命令去烧写,当然,在linux下输入命令也是可以烧写的。为什么要这么做呢,我的情况是这样的,ubuntu在多次插拔SD卡后会出现不识别SD卡的现象,必须重启虚拟机才可以识别,相当的郁闷,导致非常没有效率。windows下就没这种情况啦,比较好用,而且下载还快。
我移植的u-boot-2013.10这个版本实际上是按照三星的1.3.4版本的u-boot启动方式来的。
可以看这个博文普及一下先,我就不贴在这里了,地址是http://blog.csdn.net/zsy2020314/article/details/9824035
对于代码我不做详细的解释,我这里说一下移植中可能比较重要的东西。
在移植中主要修改的文件有两类,板级类和CPU相关类。
板级类请参考我上传的源码v1.0-u-boot-2013.10中的board目录
CPU相关类请参考我上传的源码v1.0-u-boot-2013.10中的arch目录
在v1.0-u-boot-2013.10中include目录是相关的配置头文件,boards.cfg和Makefile也是必须的。除此之外其他的文件或者文件夹不是移植中必须的,只是为了调试或者工具之类,可不必纠结在这些文件。由于本次u-boot.bin的下载是在windows下使用moviNAND_Fusing_Tool_v2.0.exe软件完成,所以linux下的sd_fusing工具也可以不用了。
源码地址在后边有贴出
如果想急着看运行效果可以直接拷贝我上传的源码到u-boot-2013.10版本官方源码中,使用合并替换功能即可。然后再终端输入make real210_config和make即可完成编译生成u-boot.bin文件,把u-boot.bin文件拷贝到windows中(具体怎么拷贝我就不多说了,方法很多种,使用觉得方便的即可),使用moviNAND_Fusing_Tool_v2.0.exe软件烧写到SD即可。启动即可看到如下所示的界面
下面介绍一下移植过程:
首先要理清代码的启动顺序,启动是以start.S为开始,那么就从这个文件开始走。全部代码如下:
/*
* armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
*
* Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com>
*
* Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
* Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
* Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
* Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003 Kshitij <kshitij@ti.com>
* Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm-offsets.h>
#include <config.h>
#include <version.h>
#include <asm/system.h>
#include <linux/linkage.h>
#include <configs/real210.h>
#include <s5pc110.h>
#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
.word 0x2000
.word 0x0
.word 0x0
.word 0x0
#endif
.globl _start
_start: b reset
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
#ifdef CONFIG_SPL_BUILD
_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
_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 */
#endif /* CONFIG_SPL_BUILD */
.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
*
*************************************************************************/
.globl _TEXT_BASE
_TEXT_BASE:
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
.word CONFIG_SPL_TEXT_BASE
#else
.word CONFIG_SYS_TEXT_BASE
#endif
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif
/* IRQ stack memory (calculated at run-time) + 8 bytes */
.globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
.word 0x0badc0de
/*
* the actual reset code
*/
reset:
bl save_boot_params
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
*/
mrs r0, cpsr
and r1, r0, #0x1f @ mask mode bits
teq r1, #0x1a @ test for HYP mode
bicne r0, r0, #0x1f @ clear all mode bits
orrne r0, r0, #0x13 @ set SVC mode
orr r0, r0, #0xc0 @ disable FIQ and IRQ
msr cpsr,r0
/*
* Setup vector:
* (OMAP4 spl TEXT_BASE is not 32 byte aligned.
* Continue to use ROM code vector only in OMAP4 spl)
*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
/* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register
bic r0, #CR_V @ V = 0
mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif
#ifndef CONFIG_EVT1
bl disable_l2cache
mov r0, #0x0 @
mov r1, #0x0 @ i
mov r3, #0x0
mov r4, #0x0
lp1:
mov r2, #0x0 @ j
lp2:
mov r3, r1, LSL #29 @ r3 = r1(i) <<29
mov r4, r2, LSL #6 @ r4 = r2(j) <<6
orr r4, r4, #0x2 @ r3 = (i<<29)|(j<<6)|(1<<1)
orr r3, r3, r4
mov r0, r3 @ r0 = r3
bl CoInvalidateDCacheIndex
add r2, #0x1 @ r2(j)++
cmp r2, #1024 @ r2 < 1024
bne lp2 @ jump to lp2
add r1, #0x1 @ r1(i)++
cmp r1, #8 @ r1(i) < 8
bne lp1 @ jump to lp1
bl set_l2cache_auxctrl
bl enable_l2cache
#endif
bl disable_l2cache
bl set_l2cache_auxctrl_cycle
bl enable_l2cache
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_cp15
bl cpu_init_crit
#endif
/* 读取启动模式信息 */
ldr r0, =PRO_ID_BASE
ldr r1, [r0,#OMR_OFFSET]
bic r2, r1, #0xffffffc1
/* NAND BOOT */
cmp r2, #0x0 @ 512B 4-cycle
moveq r3, #BOOT_NAND
cmp r2, #0x2 @ 2KB 5-cycle
moveq r3, #BOOT_NAND
cmp r2, #0x4 @ 4KB 5-cycle 8-bit ECC
moveq r3, #BOOT_NAND
cmp r2, #0x6 @ 4KB 5-cycle 16-bit ECC
moveq r3, #BOOT_NAND
cmp r2, #0x8 @ OneNAND Mux
moveq r3, #BOOT_ONENAND
/* SD/MMC BOOT */
cmp r2, #0xc
moveq r3, #BOOT_MMCSD
/* NOR BOOT */
cmp r2, #0x14
moveq r3, #BOOT_NOR
/* Uart BOOTONG failed */
cmp r2, #(0x1<<4)
moveq r3, #BOOT_SEC_DEV
ldr r0, =INF_REG_BASE
str r3, [r0, #INF_REG3_OFFSET]
ldr r0, =0xE010E81C /* PS_HOLD_CONTROL register */
ldr r1, =0x00005301 /* PS_HOLD output high */
str r1, [r0]
/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
#if 0
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r0,=0x00000000
#endif
ldr r1, =0xff000fff
bic r2, pc, r1 /* r0 <- current base addr of code */
ldr r3, _TEXT_BASE /* r1 <- original base addr in ram */
bic r3, r3, r1 /* r0 <- current base addr of code */
cmp r2, r3 /* compare r0, r1 */
beq run_in_ram /* r0 == r1 then skip sdram init */
#if defined(CONFIG_EVT1)
/* If BL1 was copied from SD/MMC CH2 */
ldr r0, =0xD0037488
ldr r1, [r0]
ldr r2, =0xEB200000
cmp r1, r2
beq mmcsd_boot
#endif
ldr r0, =INF_REG_BASE
ldr r1, [r0, #INF_REG3_OFFSET]
cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */
beq nand_boot
cmp r1, #BOOT_ONENAND /* 0x1 => boot device is onenand */
beq onenand_boot
cmp r1, #BOOT_MMCSD
beq mmcsd_boot
cmp r1, #BOOT_NOR
beq nor_boot
cmp r1, #BOOT_SEC_DEV
beq mmcsd_boot
nand_boot:
/*bl ledon_1*/
mmcsd_boot:
/*bl ledon_2*/
bl copy_uboot_to_ram
bl run_in_ram
nor_boot:
/*bl ledon*/
onenand_boot:
/*bl ledon*/
run_in_ram:
#if defined(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_PHY_UBOOT_BASE
ldr r2, =0xfff00000
bic r0, r0, r2
orr r1, r0, r1
mcr p15, 0, r1, c2, c0, 0
/* Enable the MMU */
mmu_on:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1
mcr p15, 0, r0, c1, c0, 0
nop
nop
nop
nop
#endif
bl ledoff
bl _main
/*------------------------------------------------------------------------------*/
ENTRY(c_runtime_cpu_setup)
/*
* If I-cache is enabled invalidate it
*/
#ifndef CONFIG_SYS_ICACHE_OFF
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
#endif
/*
* Move vector table
*/
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
bx lr
ENDPROC(c_runtime_cpu_setup)
/*************************************************************************
*
* void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
* __attribute__((weak));
*
* Stack pointer is not yet initialized at this moment
* Don't save anything to stack even if compiled with -O0
*
*************************************************************************/
ENTRY(save_boot_params)
bx lr @ back to my caller
ENDPROC(save_boot_params)
.weak save_boot_params
/*************************************************************************
*
* cpu_init_cp15
*
* Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
* CONFIG_SYS_ICACHE_OFF is defined.
*
*************************************************************************/
ENTRY(cpu_init_cp15)
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
#ifdef CONFIG_SYS_ICACHE_OFF
bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
#else
orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
#endif
mcr p15, 0, r0, c1, c0, 0
#ifdef CONFIG_ARM_ERRATA_716044
mrc p15, 0, r0, c1, c0, 0 @ read system control register
orr r0, r0, #1 << 11 @ set bit #11
mcr p15, 0, r0, c1, c0, 0 @ write system control register
#endif
#ifdef CONFIG_ARM_ERRATA_742230
mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
orr r0, r0, #1 << 4 @ set bit #4
mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
#endif
#ifdef CONFIG_ARM_ERRATA_743622
mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
orr r0, r0, #1 << 6 @ set bit #6
mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
#endif
#ifdef CONFIG_ARM_ERRATA_751472
mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
orr r0, r0, #1 << 11 @ set bit #11
mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
#endif
mov pc, lr @ back to my caller
ENDPROC(cpu_init_cp15)
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************/
ENTRY(cpu_init_crit)
/*
* Jump to board specific initialization...
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
b lowlevel_init @ go setup pll,mux,memory
ENDPROC(cpu_init_crit)
#endif
#ifndef CONFIG_SPL_BUILD
/*
*************************************************************************
*
* 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 ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/
.macro bad_save_user_regs
sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current
@ user stack
stmia sp, {r0 - r12} @ Save user registers (now in
@ svc mode) r0-r12
ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort
@ stack
ldmia r2, {r2 - r3} @ get values for "aborted" pc
@ and cpsr (into parm regs)
add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
add r5, sp, #S_SP
mov r1, lr
stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp @ save current stack into r0
@ (param register)
.endm
.macro irq_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0-r12
add r8, sp, #S_PC @ !! R8 NEEDS to be saved !!
@ a reserved stack spot would
@ be good.
stmdb r8, {sp, lr}^ @ Calling SP, LR
str lr, [r8, #0] @ Save calling PC
mrs r6, spsr
str r6, [r8, #4] @ Save CPSR
str r0, [r8, #8] @ Save OLD_R0
mov r0, sp
.endm
.macro irq_restore_user_regs
ldmia sp, {r0 - lr}^ @ Calling r0 - lr
mov r0, r0
ldr lr, [sp, #S_PC] @ Get PC
add sp, sp, #S_FRAME_SIZE
subs pc, lr, #4 @ return & move spsr_svc into
@ cpsr
.endm
.macro get_bad_stack
ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter
@ in banked mode)
str lr, [r13] @ save caller lr in position 0
@ of saved stack
mrs lr, spsr @ get the spsr
str lr, [r13, #4] @ save spsr in position 1 of
@ saved stack
mov r13, #MODE_SVC @ prepare SVC-Mode
@ msr spsr_c, r13
msr spsr, r13 @ switch modes, make sure
@ moves will execute
mov lr, pc @ capture return pc
movs pc, lr @ jump to next instruction &
@ switch modes.
.endm
.macro get_bad_stack_swi
sub r13, r13, #4 @ space on current stack for
@ scratch reg.
str r0, [r13] @ save R0's value.
ldr r0, IRQ_STACK_START_IN @ get data regions start
@ spots for abort stack
str lr, [r0] @ save caller lr in position 0
@ of saved stack
mrs lr, spsr @ get the spsr
str lr, [r0, #4] @ save spsr in position 1 of
@ saved stack
ldr lr, [r0] @ restore lr
ldr r0, [r13] @ restore r0
add r13, r13, #4 @ pop stack entry
.endm
.macro get_irq_stack @ setup IRQ stack
ldr sp, IRQ_STACK_START
.endm
.macro get_fiq_stack @ setup FIQ stack
ldr sp, FIQ_STACK_START
.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
#ifdef CONFIG_USE_IRQ
.align 5
irq:
get_irq_stack
irq_save_user_regs
bl do_irq
irq_restore_user_regs
.align 5
fiq:
get_fiq_stack
/* someone ought to write a more effective fiq_save_user_regs */
irq_save_user_regs
bl do_fiq
irq_restore_user_regs
#else
.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_USE_IRQ */
#endif
可把下图所示的流程对着上面的代码仔细看看,这里不多说。所调用的函数位置在http://blog.csdn.net/zsy2020314/article/details/9824035这个博文中都有说明,我也不多说了。当然我的start.S与其他人的可能有所不同,为了支持windows下软件可下载,这个start.S最开始的地方有如下代码:
#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
.word 0x2000
.word 0x0
.word 0x0
.word 0x0
#endif
这个是必须要有的,具体原因不详,可能是软件的要求,去掉是无法启动的。
下面这个是对板子的前期初始化,主要是时钟、内存、串口的初始化:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_cp15
bl cpu_init_crit
#endif
最终调用的是lowlevel_init这个函数对板子的前期初始化。lowlevel_init函数在板级目录下文件lowlevel_init.S中,请看源码我不贴出了。主要进行的是时钟、内存、串口等的初始化工作。mem_setup.S文件就是内存的初始化。mmc_boot.c文件是从SD卡拷贝代码到ram的函数。
ENTRY(cpu_init_crit)
/*
* Jump to board specific initialization...
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
b lowlevel_init @ go setup pll,mux,memory
ENDPROC(cpu_init_crit)
下面是代码的拷贝部分,在初始化板子之后会有一个启动判断,以及决定去哪个地方拷贝代码到内存,代码是下面的部分:
/* 读取启动模式信息 */
ldr r0, =PRO_ID_BASE
ldr r1, [r0,#OMR_OFFSET]
bic r2, r1, #0xffffffc1
/* NAND BOOT */
cmp r2, #0x0 @ 512B 4-cycle
moveq r3, #BOOT_NAND
cmp r2, #0x2 @ 2KB 5-cycle
moveq r3, #BOOT_NAND
cmp r2, #0x4 @ 4KB 5-cycle 8-bit ECC
moveq r3, #BOOT_NAND
cmp r2, #0x6 @ 4KB 5-cycle 16-bit ECC
moveq r3, #BOOT_NAND
cmp r2, #0x8 @ OneNAND Mux
moveq r3, #BOOT_ONENAND
/* SD/MMC BOOT */
cmp r2, #0xc
moveq r3, #BOOT_MMCSD
/* NOR BOOT */
cmp r2, #0x14
moveq r3, #BOOT_NOR
/* Uart BOOTONG failed */
cmp r2, #(0x1<<4)
moveq r3, #BOOT_SEC_DEV
ldr r0, =INF_REG_BASE
str r3, [r0, #INF_REG3_OFFSET]
ldr r0, =0xE010E81C /* PS_HOLD_CONTROL register */
ldr r1, =0x00005301 /* PS_HOLD output high */
str r1, [r0]
/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
#if 0
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r0,=0x00000000
#endif
ldr r1, =0xff000fff
bic r2, pc, r1 /* r0 <- current base addr of code */
ldr r3, _TEXT_BASE /* r1 <- original base addr in ram */
bic r3, r3, r1 /* r0 <- current base addr of code */
cmp r2, r3 /* compare r0, r1 */
beq run_in_ram /* r0 == r1 then skip sdram init */
#if defined(CONFIG_EVT1)
/* If BL1 was copied from SD/MMC CH2 */
ldr r0, =0xD0037488
ldr r1, [r0]
ldr r2, =0xEB200000
cmp r1, r2
beq mmcsd_boot
#endif
ldr r0, =INF_REG_BASE
ldr r1, [r0, #INF_REG3_OFFSET]
cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */
beq nand_boot
cmp r1, #BOOT_ONENAND /* 0x1 => boot device is onenand */
beq onenand_boot
cmp r1, #BOOT_MMCSD
beq mmcsd_boot
cmp r1, #BOOT_NOR
beq nor_boot
cmp r1, #BOOT_SEC_DEV
beq mmcsd_boot
nand_boot:
/*bl ledon_1*/
mmcsd_boot:
/*bl ledon_2*/
bl copy_uboot_to_ram
bl run_in_ram
nor_boot:
/*bl ledon*/
onenand_boot:
判断的结果当然是从SD卡启动了,这时会调用copy_uboot_to_ram函数进行代码的搬移,也就是拷贝bl2,然后就直接跳到内存中运行了,bl
run_in_ram这句代码不必关心。
跳到内存后当然又是从reset处开始运行了,不过这次得运行于刚启动时运行的不同,跳到内存运行后是不会再对时钟和内存做初始化了,尤其是内存不能做初始化,因为已经在内存中运行了,再初始化,肯定会当掉,所以在跳转到内存后这部分的初始化会跳过的。
另外下面这部分代码也会做判断,判断程序是否在内存中运行,如果是就直接跳转到run_in_ram处继续执行,不再进行bl2的搬运了
ldr r1, =0xff000fff
bic r2, pc, r1 /* r0 <- current base addr of code */
ldr r3, _TEXT_BASE /* r1 <- original base addr in ram */
bic r3, r3, r1 /* r0 <- current base addr of code */
cmp r2, r3 /* compare r0, r1 */
beq run_in_ram /* r0 == r1 then skip sdram init */
run_in_ram这部分做的是什么呢,代码如下:
run_in_ram:
#if defined(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_PHY_UBOOT_BASE
ldr r2, =0xfff00000
bic r0, r0, r2
orr r1, r0, r1
mcr p15, 0, r1, c2, c0, 0
/* Enable the MMU */
mmu_on:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1
mcr p15, 0, r0, c1, c0, 0
nop
nop
nop
nop
#endif
bl ledoff
bl _main
可以看到最后跳转到了_main函数运行,这个函数在crt0.S中定义,上面部分有个mmu的条件编译,如果定义了CONFIG_ENABLE_MMU宏就开启内存映射功能,否则就不开启。
在_main函数中前后会调用board_init_f和board_init_r,最后进入u-boot控制台。
修改的源码下载地址http://download.csdn.net/detail/u010406724/6924075(我没有下载资源分了,所以本资源我设置了2个下载分,以后会取消下载分的)
需要对u-boot.lds的链接做个说明,也就是指定某个文件的函数放在u-boot的前8K之中,因为bl1用了8K,如果调用的函数在这之外,那么bl1肯定是失败的。可以的话大家可以自行测试一下,我就不贴出我自己的测试了。
这里贴出我的这个文件代码:
/*
* Copyright (c) 2004-2008 Texas Instruments
*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
*
* SPDX-License-Identifier: GPL-2.0+
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
*(.__image_copy_start)
CPUDIR/start.o (.text*)
board/samsung/real210/real210_board.o (.text)/*用户添加*/
*(.text*)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
*(.data*)
}
. = ALIGN(4);
. = .;
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN(4);
.image_copy_end :
{
*(.__image_copy_end)
}
.rel_dyn_start :
{
*(.__rel_dyn_start)
}
.rel.dyn : {
*(.rel*)
}
.rel_dyn_end :
{
*(.__rel_dyn_end)
}
_end = .;
/*
* Deprecated: this MMU section is used by pxa at present but
* should not be used by new boards/CPUs.
*/
. = ALIGN(4096);
.mmutable : {
*(.mmutable)
}
/*
* Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
* __bss_base and __bss_limit are for linker only (overlay ordering)
*/
.bss_start __rel_dyn_start (OVERLAY) : {
KEEP(*(.__bss_start));
__bss_base = .;
}
.bss __bss_base (OVERLAY) : {
*(.bss*)
. = ALIGN(4);
__bss_limit = .;
}
.bss_end __bss_limit (OVERLAY) : {
KEEP(*(.__bss_end));
}
/DISCARD/ : { *(.dynsym) }
/DISCARD/ : { *(.dynstr*) }
/DISCARD/ : { *(.dynamic*) }
/DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) }
/DISCARD/ : { *(.ARM.exidx*) }
/DISCARD/ : { *(.gnu.linkonce.armexidx
由上可以知道我添加的是
board/samsung/real210/real210_board.o (.text)/*用户添加*/
这一行代码,也就是把real210_board.o文件链接进来。这个文件在哪里呢,这个文件是在编译时产生的,位置在board/samsung/real210这个目录。real210_board.o又是由哪些文件生成的呢,这就需要看makefile了。
这里说明一下,u-boot-2013.10版本u-boot与1.3.4版本u-boot的连接可能不太一样,不是只要把连接的目标添加到u-boot.lds就可以的,还需要修改makefile才行,否则就会报重定义的错误。我的makefile文件代码如下:
#
# (C) Copyright 2000, 2001, 2002
# Wolfgang Denk, DENX Software Engineering, wd@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
#
include $(TOPDIR)/config.mk
#下面为用户添加,功能是把lowlevel_init.o mem_setup.o mmc_boot.o这三个目标独立出来,生成real210_board.o,用于在u-boot.lds中做链接
#这样做的目的是,为了在增加该目录下代码量时,不影响生成u-boot.bin前8K的BL1
LIBReal = $(obj)real210_board.o
REAL210_board := lowlevel_init.o mem_setup.o mmc_boot.o
SRCS := $(REAL210_board:.o=.S)
REAL210_board := $(addprefix $(obj),$(REAL210_board))
#上面为用户添加
LIB = $(obj)lib$(BOARD).o
COBJS-y := real210.o
#COBJS-$(CONFIG_SAMSUNG_ONENAND) += onenand.o
SOBJS :=
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
SOBJS := $(addprefix $(obj),$(SOBJS))
#下面为用户添加,下面的ALL一定不能少,它的意思是告诉编译器后面的两个LIB全部都要编译,不加只会编译前面的一个,后面的不会编译
ALL :$(LIB) $(LIBReal)
$(LIBReal):$(obj).depend $(REAL210_board)
$(call cmd_link_o_target, $(REAL210_board))
#上面为用户添加
$(LIB) :$(obj).depend $(SOBJS) $(OBJS)
$(call cmd_link_o_target, $(SOBJS) $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################
注释已经很详细了,我不多解释了。
好了本篇到此告一段落。下一篇是加入DM9000的网络支持。
还有个栈的问题未弄明白,还得再看看。也就是CONFIG_SYS_INIT_SP_ADDR这个宏的值是多少的问题,以后还得看看,或者谁了解告知我,感激不尽。
copy_uboot_to_ram这个函数的问题请参考我的另一篇博客http://blog.csdn.net/wang_shuai_ww/article/details/19235833。