基于友善之臂ARM-tiny4412--uboot源码分析

来源:互联网 发布:类似于prisma的软件 编辑:程序博客网 时间:2024/05/22 06:14
/* * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core * * Copyright (c) 2004Texas Instruments <r-woodruff2@ti.com> * * Copyright (c) 2001Marius Gr?ger <mag@sysgo.de> * Copyright (c) 2002Alex Züpke <azu@sysgo.de> * Copyright (c) 2002Gary Jennejohn <garyj@denx.de> * Copyright (c) 2003Richard Woodruff <r-woodruff2@ti.com> * Copyright (c) 2003Kshitij <kshitij@ti.com> * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com> * * 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 <asm-offsets.h>#include <config.h>#include <version.h>#if defined(CONFIG_S5PC110) && defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)   @阶段启动相关设置.word 0x2000.word 0x0.word 0x0.word 0x0#endif.globl _start_start: breset        @复位入口,此时使用b指令作为相对调整,不依赖运行地址@以下为进入异常处理函数ldrpc, _undefined_instructionldrpc, _software_interruptldrpc, _prefetch_abortldrpc, _data_abortldrpc, _not_usedldrpc, _irqldrpc, _fiq_undefined_instruction: .word undefined_instruction   @定义异常处理函数_software_interrupt:.word software_interrupt_prefetch_abort:.word prefetch_abort_data_abort:.word data_abort_not_used:.word not_used_irq:.word irq_fiq:.word fiq_pad:.word 0x12345678 /* now 16*4=64 */  @此处保证16个字节进行对齐.global _end_vect_end_vect:.balignl 16,0xdeadbeef   @同样是保证16个字节进行对齐/************************************************************************* * * 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:.wordCONFIG_SYS_TEXT_BASE   @此处为根目录下Makefile传进来的参数,具体为0xc3e00000/* * These are defined in the board-specific linker script. */.globl _bss_start_ofs_bss_start_ofs:.word __bss_start - _start     //__bss_start在链接脚本文件中bss段开始,_end在bss段结尾,用于清除bss段,这两个值要链接时才确定.globl _bss_end_ofs_bss_end_ofs:.word _end - _start#ifdef CONFIG_USE_IRQ    /* IRQ stack memory (calculated at run-time) */   中断栈内存.globl IRQ_STACK_STARTIRQ_STACK_START:        .word0x0badc0de/* IRQ stack memory (calculated at run-time) */.globl FIQ_STACK_STARTFIQ_STACK_START:.word 0x0badc0de#endif/* IRQ stack memory (calculated at run-time) + 8 bytes */.globl IRQ_STACK_START_INIRQ_STACK_START_IN:.word0x0badc0de/* * the actual reset code  复位相关的代码 */reset:/* * set the cpu to SVC32 mode  设置CPU进入SVC模式 */mrsr0, cpsr       清CPSR的第I位bicr0, r0, #0x1forrr0, r0, #0xd3msrcpsr,r0#if (CONFIG_OMAP34XX)/* Copy vectors to mask ROM indirect addr *// *拷贝载体掩模ROM间接地址*/adrr0, _start@ r0 <- current position of codeaddr0, r0, #4@ skip reset vectormovr2, #64@ r2 <- size to copy   r2寄存器进行拷贝addr2, r0, r2@ r2 <- source end addressmovr1, #SRAM_OFFSET0@ build vect addrmovr3, #SRAM_OFFSET1addr1, r1, r3movr3, #SRAM_OFFSET2addr1, r1, r3next:ldmiar0!, {r3 - r10}@ copy from source address [r0]stmiar1!, {r3 - r10}@ copy to   target address [r1]cmpr0, r2@ until source end address [r2]bnenext@ loop until equal */#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)/* No need to copy/exec the clock code - DPLL adjust already done * in NAND/oneNAND Boot. */ @这里不需要复制/执行时钟代码数字锁相环调整已经完成在NAND / OneNAND启动。blcpy_clk_code@ put dpll adjust code behind vectors#endif /* NAND Boot */#endif/* the mask ROM code should have PLL and others stable *// *屏蔽代码应该有锁相环和其他稳定* /#ifndef CONFIG_SKIP_LOWLEVEL_INITblcpu_init_crit#endif/* Set stackpointer in internal RAM to call board_init_f */call_board_init_f:ldrsp, =(CONFIG_SYS_INIT_SP_ADDR)bicsp, sp, #7 /* 8-byte alignment for ABI compliance */ldrr0,=0x00000000blboard_init_f/*------------------------------------------------------------------------------*//* * void relocate_code (addr_sp, gd, addr_moni) * * This "function" does not return, instead it continues in RAM * after relocating the monitor code. * */.globlrelocate_coderelocate_code:movr4, r0/* save addr_sp */movr5, r1/* save addr of gd */movr6, r2/* save addr of destination *//* Set up the stack    */stack_setup:movsp, r4adrr0, _start#if defined(CONFIG_S5PC110) && defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)subr0, r0, #16#endif#ifndef CONFIG_PRELOADERcmpr0, r6beqclear_bss/* skip relocation */#endifmovr1, r6/* r1 <- scratch for copy_loop */ldrr2, _TEXT_BASEldrr3, _bss_start_ofsaddr2, r0, r3/* r2 <- source end address    */copy_loop:ldmiar0!, {r9-r10}/* copy from source address [r0]    */stmiar1!, {r9-r10}/* copy to   target address [r1]    */cmpr0, r2/* until source end address [r2]    */blocopy_loop#ifndef CONFIG_PRELOADER/* * fix .rel.dyn relocations */ldrr0, _TEXT_BASE/* r0 <- Text base */subr9, r6, r0/* r9 <- relocation offset */ldrr10, _dynsym_start_ofs/* r10 <- sym table ofs */addr10, r10, r0/* r10 <- sym table in FLASH */ldrr2, _rel_dyn_start_ofs/* r2 <- rel dyn start ofs */addr2, r2, r0/* r2 <- rel dyn start in FLASH */ldrr3, _rel_dyn_end_ofs/* r3 <- rel dyn end ofs */addr3, r3, r0/* r3 <- rel dyn end in FLASH */fixloop:ldrr0, [r2]/* r0 <- location to fix up, IN FLASH! */addr0, r0, r9/* r0 <- location to fix up in RAM */ldrr1, [r2, #4]andr7, r1, #0xffcmpr7, #23/* relative fixup? */beqfixrelcmpr7, #2/* absolute fixup? */beqfixabs/* ignore unknown type of fixup */bfixnextfixabs:/* absolute fix: set location to (offset) symbol value */movr1, r1, LSR #4/* r1 <- symbol index in .dynsym */addr1, r10, r1/* r1 <- address of symbol in table */ldrr1, [r1, #4]/* r1 <- symbol value */addr1, r1, r9/* r1 <- relocated sym addr */bfixnextfixrel:/* relative fix: increase location by offset */ldrr1, [r0]addr1, r1, r9fixnext:strr1, [r0]addr2, r2, #8/* each rel.dyn entry is 8 bytes */cmpr2, r3blofixloopclear_bss:  @清除_bss 段ldrr0, _bss_start_ofsldrr1, _bss_end_ofsldrr3, _TEXT_BASE/* Text base */movr4, r6/* reloc addr */addr0, r0, r4addr1, r1, r4movr2, #0x00000000/* clear    */clbss_l:strr2, [r0]/* clear loop...    */addr0, r0, #4cmpr0, r1bneclbss_l#endif/* #ifndef CONFIG_PRELOADER *//* * We are done. Do not return, instead branch to second part of board * initialization, now running from RAM. */ @初始化部分,从内存中开始运行jump_2_ram:ldrr0, _board_init_r_ofsadrr1, _startaddlr, r0, r1@addlr, lr, r9/* setup parameters for board_init_r */movr0, r5/* gd_t */movr1, r6/* dest_addr *//* jump to it ... */movpc, lr_board_init_r_ofs:.word board_init_r - _start_rel_dyn_start_ofs:.word __rel_dyn_start - _start_rel_dyn_end_ofs:.word __rel_dyn_end - _start_dynsym_start_ofs:.word __dynsym_start - _start/************************************************************************* * * CPU_init_critical registers    CO=PU初始化控制錴 * * setup important registers * setup memory timing * *************************************************************************/cpu_init_crit:bl cache_init      @跳到缓存进行初始化/* * Invalidate L1 I/D */movr0, #0@ set up for MCR   mcrp15, 0, r0, c8, c7, 0@ invalidate TLBs    禁止TLBmcrp15, 0, r0, c7, c5, 0@ invalidate icache  禁止指令缓存/*  * disable MMU stuff and caches      */mrcp15, 0, r0, c1, c0, 0bicr0, r0, #0x00002000@ clear bits 13 (--V-)bicr0, r0, #0x00000007@ clear bits 2:0 (-CAM)orrr0, r0, #0x00000002@ set bit 1 (--A-) Alignorrr0, r0, #0x00000800@ set bit 12 (Z---) BTBmcrp15, 0, r0, c1, c0, 0       @进制MMC和Cache/* * 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. */movip, lr@ persevere link reg across callbllowlevel_init@ go setup pll,mux,memorymovlr, ip@ restore linkmovpc, lr@ back to my caller/* ************************************************************************* * * Interrupt handling   中断处理句柄 * ************************************************************************* */@@ IRQ stack frame.@#define S_FRAME_SIZE72#define S_OLD_R068#define S_PSR64#define S_PC60#define S_LR56#define S_SP52#define S_IP48#define S_FP44#define S_R1040#define S_R936#define S_R832#define S_R728#define S_R624#define S_R520#define S_R416#define S_R312#define S_R28#define S_R14#define S_R00#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 */.macrobad_save_user_regssubsp, sp, #S_FRAME_SIZE@ carve out a frame on current@ user stackstmiasp, {r0 - r12}@ Save user registers (now in@ svc mode) r0-r12ldrr2, IRQ_STACK_START_IN@ set base 2 words into abort@ stackldmiar2, {r2 - r3}@ get values for "aborted" pc@ and cpsr (into parm regs)addr0, sp, #S_FRAME_SIZE@ grab pointer to old stackaddr5, sp, #S_SPmovr1, lrstmiar5, {r0 - r3}@ save sp_SVC, lr_SVC, pc, cpsrmovr0, sp@ save current stack into r0@ (param register).endm.macroirq_save_user_regssubsp, sp, #S_FRAME_SIZEstmiasp, {r0 - r12}@ Calling r0-r12addr8, sp, #S_PC@ !! R8 NEEDS to be saved !!@ a reserved stack spot would@ be good.stmdbr8, {sp, lr}^@ Calling SP, LRstrlr, [r8, #0]@ Save calling PCmrsr6, spsrstrr6, [r8, #4]@ Save CPSRstrr0, [r8, #8]@ Save OLD_R0movr0, sp.endm.macroirq_restore_user_regsldmiasp, {r0 - lr}^@ Calling r0 - lrmovr0, r0ldrlr, [sp, #S_PC]@ Get PCaddsp, sp, #S_FRAME_SIZEsubspc, lr, #4@ return & move spsr_svc into@ cpsr.endm.macro get_bad_stackldrr13, IRQ_STACK_START_IN@ setup our mode stack (enter@ in banked mode)strlr, [r13]@ save caller lr in position 0@ of saved stackmrslr, spsr@ get the spsrstrlr, [r13, #4]@ save spsr in position 1 of@ saved stackmovr13, #MODE_SVC@ prepare SVC-Mode@ msrspsr_c, r13msrspsr, r13@ switch modes, make sure@ moves will executemovlr, pc@ capture return pcmovspc, lr@ jump to next instruction &@ switch modes..endm.macro get_bad_stack_swisubr13, r13, #4@ space on current stack for@ scratch reg.strr0, [r13]@ save R0's value.ldrr0, IRQ_STACK_START_IN@ get data regions start@ spots for abort stackstrlr, [r0]@ save caller lr in position 0@ of saved stackmrsr0, spsr@ get the spsrstrlr, [r0, #4]@ save spsr in position 1 of@ saved stack  ldrr0, [r13]@ restore r0addr13, r13, #4@ pop stack entry.endm.macro get_irq_stack@ setup IRQ stackldrsp, IRQ_STACK_START.endm.macro get_fiq_stack@ setup FIQ stackldrsp, FIQ_STACK_START.endm/* * exception handlers   异常处理句柄 */.align5undefined_instruction:get_bad_stackbad_save_user_regsbldo_undefined_instruction.align5software_interrupt:get_bad_stack_swibad_save_user_regsbldo_software_interrupt.align5prefetch_abort:get_bad_stackbad_save_user_regsbldo_prefetch_abort.align5data_abort:get_bad_stackbad_save_user_regsbldo_data_abort.align5not_used:get_bad_stackbad_save_user_regsbldo_not_used#ifdef CONFIG_USE_IRQ.align5irq:get_irq_stackirq_save_user_regsbldo_irqirq_restore_user_regs.align5fiq:get_fiq_stack/* someone ought to write a more effective fiq_save_user_regs */irq_save_user_regsbldo_fiqirq_restore_user_regs#else.align5irq:get_bad_stackbad_save_user_regsbldo_irq.align5fiq:get_bad_stackbad_save_user_regsbldo_fiq#endif

1 0