在移植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 <[email protected]> * * Copyright (c) 2001 Marius Gröger <[email protected]> * Copyright (c) 2002 Alex Züpke <[email protected]> * Copyright (c) 2002 Gary Jennejohn <[email protected]> * Copyright (c) 2003 Richard Woodruff <[email protected]> * Copyright (c) 2003 Kshitij <[email protected]> * Copyright (c) 2006-2008 Syed Mohammed Khasim <[email protected]> * * 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: #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函数中前后会调用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, <[email protected]> * * 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, [email protected]. # # (C) Copyright 2008 # Guennadi Liakhovetki, DENX Software Engineering, <[email protected]> # # 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。