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 resetldr pc, _undefined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr 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, cpsrand r1, r0, #0x1f @ mask mode bitsteq r1, #0x1a @ test for HYP modebicne r0, r0, #0x1f @ clear all mode bitsorrne r0, r0, #0x13 @ set SVC modeorr r0, r0, #0xc0 @ disable FIQ and IRQmsr 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 Registerbic r0, #CR_V @ V = 0mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register/* Set vector address in CP15 VBAR register */ldr r0, =_startmcr p15, 0, r0, c12, c0, 0 @Set VBAR #endif #ifndef CONFIG_EVT1bl disable_l2cachemov r0, #0x0 @mov r1, #0x0 @ imov r3, #0x0mov r4, #0x0 lp1:mov r2, #0x0 @ j lp2:mov r3, r1, LSL #29 @ r3 = r1(i) <<29mov r4, r2, LSL #6 @ r4 = r2(j) <<6orr r4, r4, #0x2 @ r3 = (i<<29)|(j<<6)|(1<<1)orr r3, r3, r4mov r0, r3 @ r0 = r3bl CoInvalidateDCacheIndexadd r2, #0x1 @ r2(j)++cmp r2, #1024 @ r2 < 1024bne lp2 @ jump to lp2add r1, #0x1 @ r1(i)++cmp r1, #8 @ r1(i) < 8bne lp1 @ jump to lp1bl set_l2cache_auxctrlbl enable_l2cache #endifbl disable_l2cachebl set_l2cache_auxctrl_cyclebl enable_l2cache/* the mask ROM code should have PLL and others stable */ #ifndef CONFIG_SKIP_LOWLEVEL_INITbl cpu_init_cp15bl cpu_init_crit #endif/* 讀取啟動模式信息 */ldr r0, =PRO_ID_BASEldr r1, [r0,#OMR_OFFSET]bic r2, r1, #0xffffffc1/* NAND BOOT */cmp r2, #0x0 @ 512B 4-cyclemoveq r3, #BOOT_NANDcmp r2, #0x2 @ 2KB 5-cyclemoveq r3, #BOOT_NANDcmp r2, #0x4 @ 4KB 5-cycle 8-bit ECCmoveq r3, #BOOT_NANDcmp r2, #0x6 @ 4KB 5-cycle 16-bit ECCmoveq r3, #BOOT_NANDcmp r2, #0x8 @ OneNAND Muxmoveq r3, #BOOT_ONENAND/* SD/MMC BOOT */cmp r2, #0xcmoveq r3, #BOOT_MMCSD/* NOR BOOT */cmp r2, #0x14moveq r3, #BOOT_NOR/* Uart BOOTONG failed */cmp r2, #(0x1<<4)moveq r3, #BOOT_SEC_DEVldr r0, =INF_REG_BASEstr 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 0ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ldr r0,=0x00000000 #endifldr r1, =0xff000fffbic 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, =0xD0037488ldr r1, [r0]ldr r2, =0xEB200000cmp r1, r2beq mmcsd_boot #endifldr r0, =INF_REG_BASEldr r1, [r0, #INF_REG3_OFFSET]cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */beq nand_bootcmp r1, #BOOT_ONENAND /* 0x1 => boot device is onenand */beq onenand_bootcmp r1, #BOOT_MMCSDbeq mmcsd_bootcmp r1, #BOOT_NORbeq nor_bootcmp r1, #BOOT_SEC_DEVbeq mmcsd_bootnand_boot:/*bl ledon_1*/mmcsd_boot:/*bl ledon_2*/bl copy_uboot_to_rambl 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, =0x0000ffffmcr p15, 0, r5, c3, c0, 0 @load domain access register/* Set the TTB register */ldr r0, _mmu_table_baseldr r1, =CONFIG_PHY_UBOOT_BASEldr r2, =0xfff00000bic r0, r0, r2orr r1, r0, r1mcr p15, 0, r1, c2, c0, 0/* Enable the MMU */ mmu_on:mrc p15, 0, r0, c1, c0, 0orr r0, r0, #1mcr p15, 0, r0, c1, c0, 0nopnopnopnop #endifbl ledoffbl _main/*------------------------------------------------------------------------------*/ENTRY(c_runtime_cpu_setup) /** If I-cache is enabled invalidate it*/ #ifndef CONFIG_SYS_ICACHE_OFFmcr p15, 0, r0, c7, c5, 0 @ invalidate icachemcr p15, 0, r0, c7, c10, 4 @ DSBmcr p15, 0, r0, c7, c5, 4 @ ISB #endif /** Move vector table*//* Set vector address in CP15 VBAR register */ldr r0, =_startmcr p15, 0, r0, c12, c0, 0 @Set VBARbx lrENDPROC(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 MCRmcr p15, 0, r0, c8, c7, 0 @ invalidate TLBsmcr p15, 0, r0, c7, c5, 0 @ invalidate icachemcr p15, 0, r0, c7, c5, 6 @ invalidate BP arraymcr p15, 0, r0, c7, c10, 4 @ DSBmcr p15, 0, r0, c7, c5, 4 @ ISB/** disable MMU stuff and caches*/mrc p15, 0, r0, c1, c0, 0bic r0, r0, #0x00002000 @ clear bits 13 (--V-)bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)orr r0, r0, #0x00000002 @ set bit 1 (--A-) Alignorr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB #ifdef CONFIG_SYS_ICACHE_OFFbic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache #elseorr r0, r0, #0x00001000 @ set bit 12 (I) I-cache #endifmcr p15, 0, r0, c1, c0, 0#ifdef CONFIG_ARM_ERRATA_716044mrc p15, 0, r0, c1, c0, 0 @ read system control registerorr r0, r0, #1 << 11 @ set bit #11mcr p15, 0, r0, c1, c0, 0 @ write system control register #endif#ifdef CONFIG_ARM_ERRATA_742230mrc p15, 0, r0, c15, c0, 1 @ read diagnostic registerorr r0, r0, #1 << 4 @ set bit #4mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register #endif#ifdef CONFIG_ARM_ERRATA_743622mrc p15, 0, r0, c15, c0, 1 @ read diagnostic registerorr r0, r0, #1 << 6 @ set bit #6mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register #endif#ifdef CONFIG_ARM_ERRATA_751472mrc p15, 0, r0, c15, c0, 1 @ read diagnostic registerorr r0, r0, #1 << 11 @ set bit #11mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register #endifmov 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_regssub sp, sp, #S_FRAME_SIZE @ carve out a frame on current@ user stackstmia sp, {r0 - r12} @ Save user registers (now in@ svc mode) r0-r12ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort@ stackldmia r2, {r2 - r3} @ get values for "aborted" pc@ and cpsr (into parm regs)add r0, sp, #S_FRAME_SIZE @ grab pointer to old stackadd r5, sp, #S_SPmov r1, lrstmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsrmov r0, sp @ save current stack into r0@ (param register).endm.macro irq_save_user_regssub sp, sp, #S_FRAME_SIZEstmia sp, {r0 - r12} @ Calling r0-r12add r8, sp, #S_PC @ !! R8 NEEDS to be saved !!@ a reserved stack spot would@ be good.stmdb r8, {sp, lr}^ @ Calling SP, LRstr lr, [r8, #0] @ Save calling PCmrs r6, spsrstr r6, [r8, #4] @ Save CPSRstr r0, [r8, #8] @ Save OLD_R0mov r0, sp.endm.macro irq_restore_user_regsldmia sp, {r0 - lr}^ @ Calling r0 - lrmov r0, r0ldr lr, [sp, #S_PC] @ Get PCadd sp, sp, #S_FRAME_SIZEsubs pc, lr, #4 @ return & move spsr_svc into@ cpsr.endm.macro get_bad_stackldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter@ in banked mode)str lr, [r13] @ save caller lr in position 0@ of saved stackmrs lr, spsr @ get the spsrstr lr, [r13, #4] @ save spsr in position 1 of@ saved stackmov r13, #MODE_SVC @ prepare SVC-Mode@ msr spsr_c, r13msr spsr, r13 @ switch modes, make sure@ moves will executemov lr, pc @ capture return pcmovs pc, lr @ jump to next instruction &@ switch modes..endm.macro get_bad_stack_swisub 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 stackstr lr, [r0] @ save caller lr in position 0@ of saved stackmrs lr, spsr @ get the spsrstr lr, [r0, #4] @ save spsr in position 1 of@ saved stackldr lr, [r0] @ restore lrldr r0, [r13] @ restore r0add r13, r13, #4 @ pop stack entry.endm.macro get_irq_stack @ setup IRQ stackldr sp, IRQ_STACK_START.endm.macro get_fiq_stack @ setup FIQ stackldr sp, FIQ_STACK_START.endm/** exception handlers*/.align 5 undefined_instruction:get_bad_stackbad_save_user_regsbl do_undefined_instruction.align 5 software_interrupt:get_bad_stack_swibad_save_user_regsbl do_software_interrupt.align 5 prefetch_abort:get_bad_stackbad_save_user_regsbl do_prefetch_abort.align 5 data_abort:get_bad_stackbad_save_user_regsbl do_data_abort.align 5 not_used:get_bad_stackbad_save_user_regsbl do_not_used#ifdef CONFIG_USE_IRQ.align 5 irq:get_irq_stackirq_save_user_regsbl do_irqirq_restore_user_regs.align 5 fiq:get_fiq_stack/* someone ought to write a more effective fiq_save_user_regs */irq_save_user_regsbl do_fiqirq_restore_user_regs#else.align 5 irq:get_bad_stackbad_save_user_regsbl do_irq.align 5 fiq:get_bad_stackbad_save_user_regsbl 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_INITbl cpu_init_cp15bl 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_BASEldr r1, [r0,#OMR_OFFSET]bic r2, r1, #0xffffffc1/* NAND BOOT */cmp r2, #0x0 @ 512B 4-cyclemoveq r3, #BOOT_NANDcmp r2, #0x2 @ 2KB 5-cyclemoveq r3, #BOOT_NANDcmp r2, #0x4 @ 4KB 5-cycle 8-bit ECCmoveq r3, #BOOT_NANDcmp r2, #0x6 @ 4KB 5-cycle 16-bit ECCmoveq r3, #BOOT_NANDcmp r2, #0x8 @ OneNAND Muxmoveq r3, #BOOT_ONENAND/* SD/MMC BOOT */cmp r2, #0xcmoveq r3, #BOOT_MMCSD/* NOR BOOT */cmp r2, #0x14moveq r3, #BOOT_NOR/* Uart BOOTONG failed */cmp r2, #(0x1<<4)moveq r3, #BOOT_SEC_DEVldr r0, =INF_REG_BASEstr 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 0ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ldr r0,=0x00000000 #endifldr r1, =0xff000fffbic 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, =0xD0037488ldr r1, [r0]ldr r2, =0xEB200000cmp r1, r2beq mmcsd_boot #endifldr r0, =INF_REG_BASEldr r1, [r0, #INF_REG3_OFFSET]cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */beq nand_bootcmp r1, #BOOT_ONENAND /* 0x1 => boot device is onenand */beq onenand_bootcmp r1, #BOOT_MMCSDbeq mmcsd_bootcmp r1, #BOOT_NORbeq nor_bootcmp r1, #BOOT_SEC_DEVbeq mmcsd_bootnand_boot:/*bl ledon_1*/mmcsd_boot:/*bl ledon_2*/bl copy_uboot_to_rambl run_in_ram nor_boot:/*bl ledon*/ onenand_boot: 判斷的結果當然是從SD卡啟動了,這時會調用copy_uboot_to_ram函數進行代碼的搬移,也就是拷貝bl2,然后就直接跳到內存中運行了,bl run_in_ram這句代碼不必關心。
跳到內存后當然又是從reset處開始運行了,不過這次得運行于剛啟動時運行的不同,跳到內存運行后是不會再對時鐘和內存做初始化了,尤其是內存不能做初始化,因為已經在內存中運行了,再初始化,肯定會當掉,所以在跳轉到內存后這部分的初始化會跳過的。
另外下面這部分代碼也會做判斷,判斷程序是否在內存中運行,如果是就直接跳轉到run_in_ram處繼續執行,不再進行bl2的搬運了
run_in_ram這部分做的是什么呢,代碼如下: run_in_ram:#if defined(CONFIG_ENABLE_MMU) enable_mmu:/* enable domain access */ldr r5, =0x0000ffffmcr p15, 0, r5, c3, c0, 0 @load domain access register/* Set the TTB register */ldr r0, _mmu_table_baseldr r1, =CONFIG_PHY_UBOOT_BASEldr r2, =0xfff00000bic r0, r0, r2orr r1, r0, r1mcr p15, 0, r1, c2, c0, 0/* Enable the MMU */ mmu_on:mrc p15, 0, r0, c1, c0, 0orr r0, r0, #1mcr p15, 0, r0, c1, c0, 0nopnopnopnop #endifbl ledoffbl _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.oSRCS := $(REAL210_board:.o=.S) REAL210_board := $(addprefix $(obj),$(REAL210_board)) #上面為用戶添加LIB = $(obj)lib$(BOARD).oCOBJS-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.mksinclude $(obj).depend#########################################################################注釋已經很詳細了,我不多解釋了。
好了本篇到此告一段落。下一篇是加入DM9000的網絡支持。
還有個棧的問題未弄明白,還得再看看。也就是CONFIG_SYS_INIT_SP_ADDR這個宏的值是多少的問題,以后還得看看,或者誰了解告知我,感激不盡。
copy_uboot_to_ram這個函數的問題請參考我的另一篇博客http://blog.csdn.net/wang_shuai_ww/article/details/19235833。
總結
以上是生活随笔為你收集整理的u-boot移植第三弹——移植2013.10u-boot到RealARM210 cortex-A8开发板(支持moviNAND_Fusing_Tool_v2.0)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: u-boot移植第二弹——移植2012.
- 下一篇: u-boot移植重要问题说明