u-boot移植第三弹——移植2013.10u-boot到RealARM210 cortex-A8开发板(支持moviNAND_Fusing_Tool_v2.0)

在移植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。










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值