转载请注明地址:http://blog.csdn.net/zsy2020314/article/details/9824035
1.关于启动流程
1.1 启动阶段分为3个,bl0,bl1,bl2。下面只是就功能方面对它们做说明,实际设计的时候,也许会对其具体功能做出调整,也就是说,这几个阶段的划分是就功能而言的,不能看得太死。
bl0:出厂的时候就固化在irom中一段代码,主要负责拷贝8kb的bl1到s5pv210的一个96kb大小内部sram(Internal SRAM)中运行。值得注意的是s5pv210的Internal SRAM支持的bl1的大小可以达到16kb,容量的扩增是为了适应bootloder变得越来复杂而做的。虽然如此,但目前我们制作出来的bl1的大小仍然可以保持在8kb以内,同样能满足需求。
bl1:u-boot的前8kb代码(s5pv210也支持16kb大小,原因上一点提过了),除了初始化系统时钟和一些基本的硬件外,主要负责完成代码的搬运工作(我设计成搬运bl1+bl2,而不仅仅是bl2),也就是将完整的u-boot代码(bl1+bl2)从nand flash或者mmcSD等的存储器中读取到内存中,然后跳转到内存中运行u-boot。
bl2:完成全面的硬件初始化和加载OS到内存中,接着运行OS。
上述几个阶段的流程描述在s5pv210_irom_application手册中有详细描述。见下图1:
图1
1.2 首先把启动部分的代码分为3部分,以start.S为主,另外还有lowlevel_init.S,mem_setup.S,ctr0.S。
其中lowlevel_init.S主要是一部分硬件的初始化,尤其是系统时钟和DRAM的初始化。如果u-boot一旦被搬运到内存中运行,那么是必须要跳过时钟和DRAM的初始化的,因为这在搬运之前已经做过了。并且如果代码在内存中运行的时侯你却去初始化DRAM,那必然导致崩溃!
mem_setup.S:DRAM初始化代码和MMU相关代码放在这个文件中。
ctr0.S:u-boot自带的代码文件,存放汇编函数main。
1.3 启动代码相关的几个文件在u-boot中的路径
start.S: /arch/arm/cpu/armv7/start.S (需要自己修改)
lowlevel_init.S:/board/samsung/zsy210/ lowlevel_init.S (需要自己修改)
mem_setup.S: /board/samsung/zsy210/ mem_setup.S (u-boot没有,需要自己添加)
ctr0.S: /arch/arm/lib/ctr0.S (u-boot自带,一般不需要修改)
2. 启动过程原理
必须要明白的一点是,当代码从存储介质(nand flash,SD,norflash,onenand等)中搬运到了DRAM中后随即会跳转到内存中运行u-boot,接着会有一个重定位(relocate_code)的过程,relocate_code子函数在start.S中,而给relocate_code子函数传参数的是crt0.S中的main子函数。当判断到当前u-boot在内存的低地址处,那么relocate_code就会工作,把u-boot代码从低地址处再搬运到内存地址的顶端,然后跳转到新的位置去继续运行u-boot。而搬运的目标地址是在board_init_f()函数(此函数在/arch/arm/lib/board.c中)中计算出来的,见图2。
图2
下面,以start.S为主线,画出了其程序流程图,图中同样也表现出启动的整个流程和启动代码文件间的组织关系。所以后面直接贴出start.S的完整代码,大家结合流程图相信都可以看明白,至于逐句汇编的分析不是本文的重点。见图3.
图3
3. start.S lowlevel_init.S mem_setup.S crt0.S的完整代码。
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> * * 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> #include <asm/system.h> #include <linux/linkage.h> #include <s5pv210.h> #ifndef CONFIG_ENABLE_MMU #ifndef CONFIG_PHY_UBOOT_BASE #define CONFIG_PHY_UBOOT_BASE CONFIG_UBOOT_BASE #endif /* CONFIG_PHY_UBOOT_BASE */ #endif /* CONFIG_ENABLE_MMU */ .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: .word CONFIG_SYS_TEXT_BASE /* * Below variable is very important because we use MMU in U-Boot. * Without it, we cannot run code correctly before MMU is ON. * by scsuh. */ .globl _TEXT_PHY_BASE _TEXT_PHY_BASE: .word CONFIG_PHY_UBOOT_BASE /* * These are defined in the board-specific linker script. */ .globl _bss_start_ofs _bss_start_ofs: .word __bss_start - _start .global _image_copy_end_ofs _image_copy_end_ofs: .word __image_copy_end - _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 /* * set the cpu to SVC32 mode and IRQ & FIQ disable */ msr cpsr_c, #0xd3 @ I & F disable, Mode: 0x13 - SVC /* * 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 /***************************** zsy add 2013-3-14 *****************************/ #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 bl zsy210_iic_pm_open /************************** end of zsy add 2013-3-14 ****************************/ /* the mask ROM code should have PLL and others stable */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_cp15 bl cpu_init_crit #endif /*************************** zsy add 2013-3-14 ********************************/ /* 读取启动模式信息 */ 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. */ ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ ldr r0,=0x00000000 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 bl board_init_f_nand mmcsd_boot: bl ledon_1 bl board_init_f_movi nor_boot: bl ledon onenand_boot: bl ledon /************************************************************************* * * after_copy * *************************************************************************/ 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 ledon_2 bl _main /************************** end of zsy add 2013-3-14 ****************************/ /*------------------------------------------------------------------------------*/ #ifndef CONFIG_SPL_BUILD /* * void relocate_code (addr_sp, gd, addr_moni) * * This "function" does not return, instead it continues in RAM * after relocating the monitor code. * */ ENTRY(relocate_code) mov r4, r0 /* save addr_sp */ mov r5, r1 /* save addr of gd */ mov r6, r2 /* save addr of destination */ adr r0, _start cmp r0, r6 moveq r9, #0 /* no relocation. relocation offset(r9) = 0 */ beq relocate_done /* skip relocation */ mov r1, r6 /* r1 <- scratch for copy_loop */ ldr r3, _image_copy_end_ofs add r2, r0, r3 /* r2 <- source end address */ copy_loop: ldmia r0!, {r9-r10} /* copy from source address [r0] */ stmia r1!, {r9-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end address [r2] */ blo copy_loop /* * fix .rel.dyn relocations */ ldr r0, _TEXT_BASE /* r0 <- Text base */ sub r9, r6, r0 /* r9 <- relocation offset */ ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ add r10, r10, r0 /* r10 <- sym table in FLASH */ ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ fixloop: ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ add r0, r0, r9 /* r0 <- location to fix up in RAM */ ldr r1, [r2, #4] and r7, r1, #0xff cmp r7, #23 /* relative fixup? */ beq fixrel cmp r7, #2 /* absolute fixup? */ beq fixabs /* ignore unknown type of fixup */ b fixnext fixabs: /* absolute fix: set location to (offset) symbol value */ mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ add r1, r10, r1 /* r1 <- address of symbol in table */ ldr r1, [r1, #4] /* r1 <- symbol value */ add r1, r1, r9 /* r1 <- relocated sym addr */ b fixnext fixrel: /* relative fix: increase location by offset */ ldr r1, [r0] add r1, r1, r9 fixnext: str r1, [r0] add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ cmp r2, r3 blo fixloop relocate_done: bx lr _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 ENDPROC(relocate_code) #endif 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 */ #if !defined(CONFIG_TEGRA20) /* Set vector address in CP15 VBAR register */ ldr r0, =_start add r0, r0, r9 mcr p15, 0, r0, c12, c0, 0 @Set VBAR #endif /* !Tegra20 */ 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 /* * 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 12 (Z---) BTB mcr p15, 0, r0, c1, c0, 0 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 /************************************************************************* * * zsy210_iic_pm_open * *************************************************************************/ ENTRY(zsy210_iic_pm_open) /*电源管理,保持供电*/ #ifdef CONFIG_ZSY210_IIC_PM_CHIP /* PS_HOLD(GPJ2_5) 设置为高点平 */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x00100000 str r1, [r0, #GPJ2CON_OFFSET] ldr r1, =0x0400 str r1, [r0, #GPJ2PUD_OFFSET] ldr r1, =0x20 str r1, [r0, #GPJ2DAT_OFFSET] #endif /* CONFIG_ZSY210_IIC_PM_CHIP */ mov pc, lr @ back to my caller ENDPROC(zsy210_iic_pm_open) #if defined(CONFIG_ENABLE_MMU) _mmu_table_base: .word mmu_table #endif /* * we assume that cache operation is done before. (eg. cleanup_before_linux()) * actually, we don't need to do anything about cache if not use d-cache in U-Boot * So, in this function we clean only MMU. by scsuh * * void theLastJump(void *kernel, int arch_num, uint boot_params); */ #if defined(CONFIG_ENABLE_MMU) .globl theLastJump theLastJump: mov r9, r0 ldr r3, =0xfff00000 ldr r4, _TEXT_PHY_BASE adr r5, phy_last_jump bic r5, r5, r3 orr r5, r5, r4 mov pc, r5 phy_last_jump: /* * disable MMU stuff */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ mcr p15, 0, r0, c1, c0, 0 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ mov r0, #0 mov pc, r9 #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 r0, spsr @ get the spsr str lr, [r0, #4] @ save spsr in position 1 of @ saved stack 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 /* CONFIG_SPL_BUILD */
lowlevel_init.S的完整代码:
/* * Copyright (C) 2009 Samsung Electronics * Kyungmin Park <kyungmin.park@samsung.com> * Minkyu Kang <mk7.kang@samsung.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 <config.h> #include <version.h> #include <asm/arch/cpu.h> #include <asm/arch/power.h> #include <s5pv210.h> #include "zsy210_val.h" /* * Register usages: * * r5 has zero always */ _TEXT_BASE: .word CONFIG_SYS_TEXT_BASE .globl lowlevel_init lowlevel_init: mov r9, lr /* check reset status */ ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) ldr r1, [r0] bic r1, r1, #0xfff6ffff cmp r1, #0x10000 beq wakeup_reset_pre cmp r1, #0x80000 beq wakeup_reset_from_didle /* IO Retention release */ ldr r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET) ldr r1, [r0] ldr r2, =IO_RET_REL orr r1, r1, r2 str r1, [r0] /* Disable Watchdog */ ldr r0, =ELFIN_WATCHDOG_BASE /* 0xE2700000 */ mov r1, #0 str r1, [r0] /* SRAM(2MB) init for SMDKC110 */ /* GPJ1 SROM_ADDR_16to21 */ ldr r0, =ELFIN_GPIO_BASE ldr r1, [r0, #GPJ1CON_OFFSET] bic r1, r1, #0xFFFFFF ldr r2, =0x444444 orr r1, r1, r2 str r1, [r0, #GPJ1CON_OFFSET] ldr r1, [r0, #GPJ1PUD_OFFSET] ldr r2, =0x3ff bic r1, r1, r2 str r1, [r0, #GPJ1PUD_OFFSET] /* GPJ4 SROM_ADDR_16to21 */ ldr r1, [r0, #GPJ4CON_OFFSET] bic r1, r1, #(0xf<<16) ldr r2, =(0x4<<16) orr r1, r1, r2 str r1, [r0, #GPJ4CON_OFFSET] ldr r1, [r0, #GPJ4PUD_OFFSET] ldr r2, =(0x3<<8) bic r1, r1, r2 str r1, [r0, #GPJ4PUD_OFFSET] /* CS0 - 16bit sram, enable nBE, Byte base address */ ldr r0, =ELFIN_SROM_BASE /* 0xE8000000 */ mov r1, #0x1 str r1, [r0] /* PS_HOLD pin(GPH0_0) set to high */ ldr r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET) ldr r1, [r0] orr r1, r1, #0x300 orr r1, r1, #0x1 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. */ ldr r0, =0xff000fff bic r1, pc, r0 /* r0 <- current base addr of code */ ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */ bic r2, r2, r0 /* r0 <- current base addr of code */ cmp r1, r2 /* compare r0, r1 */ beq 1f /* r0 == r1 then skip sdram init */ /* init PMIC chip */ #ifdef CONFIG_ZSY210_IIC_PM_CHIP bl PMIC_InitIp #endif /* init system clock */ bl system_clock_init /* Memory initialize */ bl mem_ctrl_asm_init 1: /* for UART */ bl uart_asm_init /* for TZPC */ bl tzpc_asm_init #if defined(CONFIG_NAND) /* simple init for NAND */ bl nand_asm_init #endif /* check reset status */ ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) ldr r1, [r0] bic r1, r1, #0xfffeffff cmp r1, #0x10000 beq wakeup_reset_pre /* ABB disable */ ldr r0, =0xE010C300 orr r1, r1, #(0x1<<23) str r1, [r0] /* Print 'K' */ ldr r0, =ELFIN_UART_CONSOLE_BASE ldr r1, =0x4b4b4b4b str r1, [r0, #UTXH_OFFSET] mov lr, r9 mov pc, lr /* * uart_asm_init: Initialize UART's pins */ uart_asm_init: /* set GPIO(GPA) to enable UART */ @ GPIO setting for UART ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x22222222 str r1, [r0, #GPA0CON_OFFSET] ldr r1, =0x2222 str r1, [r0, #GPA1CON_OFFSET] ldr r0, =ELFIN_UART_CONSOLE_BASE @0xEC000000 mov r1, #0x0 str r1, [r0, #UFCON_OFFSET] str r1, [r0, #UMCON_OFFSET] mov r1, #0x3 str r1, [r0, #ULCON_OFFSET] ldr r1, =0x3c5 str r1, [r0, #UCON_OFFSET] ldr r1, =UART_UBRDIV_VAL str r1, [r0, #UBRDIV_OFFSET] ldr r1, =UART_UDIVSLOT_VAL str r1, [r0, #UDIVSLOT_OFFSET] ldr r1, =0x4f4f4f4f str r1, [r0, #UTXH_OFFSET] @'O' mov pc, lr /* * tzpc_asm_init: Initialize TZPC */ tzpc_asm_init: ldr r0, =ELFIN_TZPC0_BASE mov r1, #0x0 str r1, [r0] mov r1, #0xff str r1, [r0, #TZPC_DECPROT0SET_OFFSET] str r1, [r0, #TZPC_DECPROT1SET_OFFSET] str r1, [r0, #TZPC_DECPROT2SET_OFFSET] ldr r0, =ELFIN_TZPC1_BASE str r1, [r0, #TZPC_DECPROT0SET_OFFSET] str r1, [r0, #TZPC_DECPROT1SET_OFFSET] str r1, [r0, #TZPC_DECPROT2SET_OFFSET] ldr r0, =ELFIN_TZPC2_BASE str r1, [r0, #TZPC_DECPROT0SET_OFFSET] str r1, [r0, #TZPC_DECPROT1SET_OFFSET] str r1, [r0, #TZPC_DECPROT2SET_OFFSET] str r1, [r0, #TZPC_DECPROT3SET_OFFSET] ldr r0, =ELFIN_TZPC3_BASE str r1, [r0, #TZPC_DECPROT0SET_OFFSET] str r1, [r0, #TZPC_DECPROT1SET_OFFSET] str r1, [r0, #TZPC_DECPROT2SET_OFFSET] mov pc, lr /******************** zsy add 2013.3.14 *******************************/ /* * Nand Interface Init for SMDKC110 */ nand_asm_init: /* Setting GPIO for NAND */ /* This setting is NAND initialze code at booting time in iROM. */ ldr r0, =ELFIN_GPIO_BASE ldr r1, [r0, #MP01CON_OFFSET] bic r1, r1, #(0xf<<8) orr r1, r1, #(0x3<<8) str r1, [r0, #MP01CON_OFFSET] ldr r1, [r0, #MP01PUD_OFFSET] bic r1, r1, #(0x3<<4) str r1, [r0, #MP01PUD_OFFSET] ldr r1, [r0, #MP03CON_OFFSET] bic r1, r1, #0xFFFFFF ldr r2, =0x22222222 orr r1, r1, r2 str r1, [r0, #MP03CON_OFFSET] ldr r1, [r0, #MP03PUD_OFFSET] ldr r2, =0x3fff bic r1, r1, r2 str r1, [r0, #MP03PUD_OFFSET] ldr r0, =ELFIN_NAND_BASE ldr r1, [r0, #NFCONF_OFFSET] ldr r2, =0x777F bic r1, r1, r2 ldr r2, =NFCONF_VAL orr r1, r1, r2 str r1, [r0, #NFCONF_OFFSET] ldr r1, [r0, #NFCONT_OFFSET] ldr r2, =0x707C7 bic r1, r1, r2 ldr r2, =NFCONT_VAL orr r1, r1, r2 str r1, [r0, #NFCONT_OFFSET] ldr r1, [r0, #NFCONF_OFFSET] orr r1, r1, #0x70 orr r1, r1, #0x7700 str r1, [r0, #NFCONF_OFFSET] ldr r1, [r0, #NFCONT_OFFSET] orr r1, r1, #0x03 str r1, [r0, #NFCONT_OFFSET] mov pc, lr /******************** zsy add 2013.3.14 *******************************/ wakeup_reset_from_didle: /* Wait when APLL is locked */ ldr r0, =ELFIN_CLOCK_POWER_BASE lockloop: ldr r1, [r0, #APLL_CON0_OFFSET] and r1, r1, #(1<<29) cmp r1, #(1<<29) bne lockloop beq exit_wakeup wakeup_reset_pre: mrc p15, 0, r1, c1, c0, 1 @Read CP15 Auxiliary control register and r1, r1, #0x80000000 @Check L2RD is disable or not cmp r1, #0x80000000 bne wakeup_reset @if L2RD is not disable jump to wakeup_reset bl disable_l2cache bl v7_flush_dcache_all /* L2 cache enable at sleep.S of kernel * bl enable_l2cache */ #ifdef CONFIG_ZSY210 bl enable_l2cache #endif wakeup_reset: /* init system clock */ bl system_clock_init bl mem_ctrl_asm_init bl tzpc_asm_init #if defined(CONFIG_NAND) bl nand_asm_init #endif exit_wakeup: /*Load return address and jump to kernel*/ ldr r0, =(INF_REG_BASE+INF_REG0_OFFSET) ldr r1, [r0] /* r1 = physical address of s5pc110_cpu_resume function*/ mov pc, r1 /*Jump to kernel */ nop nop /* * system_clock_init: Initialize core clock and bus clock. * void system_clock_init(void) */ system_clock_init: ldr r0, =ELFIN_CLOCK_POWER_BASE @0xe0100000 /* Set Mux to FIN */ ldr r1, =0x0 str r1, [r0, #CLK_SRC0_OFFSET] ldr r1, =APLL_LOCKTIME_VAL str r1, [r0, #APLL_LOCK_OFFSET] /* Disable PLL */ #if defined(CONFIG_CHECK_MPLL_LOCK) retryloop: #endif ldr r1, =0x0 str r1, [r0, #APLL_CON0_OFFSET] ldr r1, =0x0 str r1, [r0, #MPLL_CON_OFFSET] ldr r1, =0x0 str r1, [r0, #MPLL_CON_OFFSET] ldr r1, [r0, #CLK_DIV0_OFFSET] ldr r2, =CLK_DIV0_MASK bic r1, r1, r2 ldr r2, =CLK_DIV0_VAL orr r1, r1, r2 str r1, [r0, #CLK_DIV0_OFFSET] ldr r1, =APLL_VAL str r1, [r0, #APLL_CON0_OFFSET] ldr r1, =MPLL_VAL str r1, [r0, #MPLL_CON_OFFSET] ldr r1, =VPLL_VAL str r1, [r0, #VPLL_CON_OFFSET] #if defined(CONFIG_EVT1) ldr r1, =AFC_ON str r1, [r0, #APLL_CON1_OFFSET] #endif mov r1, #0x10000 1: subs r1, r1, #1 bne 1b #if defined(CONFIG_CHECK_MPLL_LOCK) /* MPLL software workaround */ ldr r1, [r0, #MPLL_CON_OFFSET] orr r1, r1, #(1<<28) str r1, [r0, #MPLL_CON_OFFSET] mov r1, #0x100 1: subs r1, r1, #1 bne 1b ldr r1, [r0, #MPLL_CON_OFFSET] and r1, r1, #(1<<29) cmp r1, #(1<<29) bne retryloop /* H/W lock detect disable */ ldr r1, [r0, #MPLL_CON_OFFSET] bic r1, r1, #(1<<28) str r1, [r0, #MPLL_CON_OFFSET] #endif ldr r1, [r0, #CLK_SRC0_OFFSET] ldr r2, =0x10001111 orr r1, r1, r2 str r1, [r0, #CLK_SRC0_OFFSET] #if defined(CONFIG_MCP_AC) /* CLK_SRC6[25:24] -> OneDRAM clock sel = MPLL */ ldr r1, [r0, #CLK_SRC6_OFFSET] bic r1, r1, #(0x3<<24) orr r1, r1, #0x01000000 str r1, [r0, #CLK_SRC6_OFFSET] /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */ ldr r1, [r0, #CLK_DIV6_OFFSET] bic r1, r1, #(0xF<<28) bic r1, r1, #(0x7<<12) @; ONENAND_RATIO: 0 orr r1, r1, #0x30000000 str r1, [r0, #CLK_DIV6_OFFSET] #elif defined (CONFIG_MCP_N) /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */ ldr r1, [r0, #CLK_SRC6_OFFSET] mov r1, #0x00000000 str r1, [r0, #CLK_SRC6_OFFSET] /* CLK_DIV6[31:28] -> 0=1/1 */ ldr r1, [r0, #CLK_DIV6_OFFSET] mov r1, #0x00000000 str r1, [r0, #CLK_DIV6_OFFSET] #elif defined (CONFIG_MCP_H) /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */ ldr r1, [r0, #CLK_SRC6_OFFSET] bic r1, r1, #(0x3<<24) orr r1, r1, #0x00000000 str r1, [r0, #CLK_SRC6_OFFSET] /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */ ldr r1, [r0, #CLK_DIV6_OFFSET] bic r1, r1, #(0xF<<28) bic r1, r1, #(0x7<<12) @; ONENAND_RATIO: 0 orr r1, r1, #0x00000000 str r1, [r0, #CLK_DIV6_OFFSET] #elif defined (CONFIG_MCP_B) || defined (CONFIG_MCP_D) /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */ ldr r1, [r0, #CLK_SRC6_OFFSET] bic r1, r1, #(0x3<<24) orr r1, r1, #0x01000000 str r1, [r0, #CLK_SRC6_OFFSET] /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */ ldr r1, [r0, #CLK_DIV6_OFFSET] bic r1, r1, #(0xF<<28) bic r1, r1, #(0x7<<12) @; ONENAND_RATIO: 0 orr r1, r1, #0x30000000 str r1, [r0, #CLK_DIV6_OFFSET] #elif defined (CONFIG_MCP_SINGLE) /* CLK_DIV6 */ ldr r1, [r0, #CLK_DIV6_OFFSET] bic r1, r1, #(0x7<<12) @; ONENAND_RATIO: 0 str r1, [r0, #CLK_DIV6_OFFSET] #endif mov pc, lr #ifdef CONFIG_ENABLE_MMU #ifdef CONFIG_MCP_SINGLE /* * MMU Table for SMDKC110 * 0x0000_0000 -- 0xBFFF_FFFF => Not Allowed * 0xB000_0000 -- 0xB7FF_FFFF => A:0xB000_0000 -- 0xB7FF_FFFF * 0xC000_0000 -- 0xC7FF_FFFF => A:0x3000_0000 -- 0x37FF_FFFF * 0xC800_0000 -- 0xDFFF_FFFF => Not Allowed * 0xE000_0000 -- 0xFFFF_FFFF => A:0xE000_0000 -- 0XFFFF_FFFF */ /* form a first-level section entry */ .macro FL_SECTION_ENTRY base,ap,d,c,b .word (\base << 20) | (\ap << 10) | \ (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1) .endm .section .mmudata, "a" .align 14 // the following alignment creates the mmu table at address 0x4000. .globl mmu_table mmu_table: .set __base,0 // Access for iRAM .rept 0x100 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr // Not Allowed .rept 0x200 - 0x100 .word 0x00000000 .endr #ifdef CONFIG_ZSY10_1G .set __base,0x200 // should be accessed .rept 0x600 - 0x200 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr #else .set __base,0x200 // should be accessed .rept 0x600 - 0x200 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr /* .set __base,0x400 // should be accessed .rept 0x500 - 0x400 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr*/ #endif /* CONFIG_ZSY10_1G */ .rept 0x800 - 0x600 .word 0x00000000 .endr .set __base,0x800 // should be accessed .rept 0xb00 - 0x800 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr /* .rept 0xc00 - 0xb00 .word 0x00000000 .endr */ .set __base,0xB00 .rept 0xc00 - 0xb00 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr #ifdef CONFIG_ZSY10_1G .set __base,0x200 // 256MB for SDRAM with cacheable .rept 0xD00 - 0xC00 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr // access is not allowed. @.rept 0xD00 - 0xC80 @.word 0x00000000 @.endr .set __base,0xD00 // 1:1 mapping for debugging with non-cacheable .rept 0x1000 - 0xD00 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr #else .set __base,0x200 // 256MB for SDRAM with cacheable .rept 0xD00 - 0xC00 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr // access is not allowed. @.rept 0xD00 - 0xC80 @.word 0x00000000 @.endr .set __base,0xD00 // 1:1 mapping for debugging with non-cacheable .rept 0x1000 - 0xD00 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr #endif /* CONFIG_ZSY10_1G */ #else // CONFIG_MCP_AC, CONFIG_MCP_H, CONFIG_MCP_B /* * MMU Table for SMDKC110 * 0x0000_0000 -- 0xBFFF_FFFF => Not Allowed * 0xB000_0000 -- 0xB7FF_FFFF => A:0xB000_0000 -- 0xB7FF_FFFF * 0xC000_0000 -- 0xC7FF_FFFF => A:0x3000_0000 -- 0x37FF_FFFF * 0xC800_0000 -- 0xDFFF_FFFF => Not Allowed * 0xE000_0000 -- 0xFFFF_FFFF => A:0xE000_0000 -- 0XFFFF_FFFF */ /* form a first-level section entry */ .macro FL_SECTION_ENTRY base,ap,d,c,b .word (\base << 20) | (\ap << 10) | \ (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1) .endm .section .mmudata, "a" .align 14 // the following alignment creates the mmu table at address 0x4000. .globl mmu_table mmu_table: .set __base,0 // Access for iRAM .rept 0x100 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr // Not Allowed .rept 0x300 - 0x100 .word 0x00000000 .endr #if defined(CONFIG_MCP_N) .set __base,0x300 // should be accessed .rept 0x400 - 0x300 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr #else .set __base,0x300 // should be accessed .rept 0x350 - 0x300 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr // Not Allowed .rept 0x400 - 0x350 .word 0x00000000 .endr #endif .set __base,0x400 // should be accessed .rept 0x500 - 0x400 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr .rept 0x800 - 0x500 .word 0x00000000 .endr .set __base,0x800 // should be accessed .rept 0xb00 - 0x800 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr .set __base,0xB00 .rept 0xc00 - 0xb00 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr #if defined(CONFIG_MCP_N) .set __base,0x300 // 256MB for SDRAM with cacheable .rept 0xD00 - 0xC00 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr #else .set __base,0x300 // 80MB for SDRAM with cacheable .rept 0xC50 - 0xC00 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr // Not Allowed .rept 0xD00 - 0xC50 .word 0x00000000 .endr #endif .set __base,0xD00 // 1:1 mapping for debugging with non-cacheable .rept 0x1000 - 0xD00 FL_SECTION_ENTRY __base,3,0,0,0 .set __base,__base+1 .endr #endif #endif
mem_setup.S的完整代码:
#include <config.h> #include <s5pv210.h> .globl mem_ctrl_asm_init mem_ctrl_asm_init: #ifndef CONFIG_EVT1 ldr r0, =ASYNC_MSYS_DMC0_BASE ldr r1, =0x0 str r1, [r0, #0x0] /* This register is removed at EVT1 of C110. */ ldr r1, =0x0 str r1, [r0, #0xC] #endif #ifdef CONFIG_MCP_SINGLE /* DMC0 Drive Strength (Setting 2X) */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x0000AAAA str r1, [r0, #MP1_0DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_1DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_2DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_3DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_4DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_5DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_6DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_7DRV_SR_OFFSET] ldr r1, =0x00002AAA str r1, [r0, #MP1_8DRV_SR_OFFSET] /* DMC1 Drive Strength (Setting 2X) */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x0000AAAA str r1, [r0, #MP2_0DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_1DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_2DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_3DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_4DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_5DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_6DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_7DRV_SR_OFFSET] ldr r1, =0x00002AAA str r1, [r0, #MP2_8DRV_SR_OFFSET] /* DMC0 initialization at single Type*/ ldr r0, =APB_DMC_0_BASE ldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000 str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case str r1, [r0, #DMC_PHYCONTROL1] ldr r1, =0x00101002 @PhyControl0 DLL on str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00101003 @PhyControl0 DLL start str r1, [r0, #DMC_PHYCONTROL0] find_lock_val: ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value and r2, r1, #0x7 cmp r2, #0x7 @Loop until DLL is locked bne find_lock_val and r1, #0x3fc0 mov r2, r1, LSL #18 orr r2, r2, #0x100000 orr r2 ,r2, #0x1000 orr r1, r2, #0x3 @Force Value locking str r1, [r0, #DMC_PHYCONTROL0] #if 0 /* Memory margin test 10.01.05 */ orr r1, r2, #0x1 @DLL off str r1, [r0, #DMC_PHYCONTROL0] #endif /* setting DDR2 */ ldr r1, =0x0FFF2010 @ConControl auto refresh off str r1, [r0, #DMC_CONCONTROL] ldr r1, =0x00212400 @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] ldr r1, =DMC0_MEMCONFIG_0 @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed str r1, [r0, #DMC_MEMCONFIG0] ldr r1, =DMC0_MEMCONFIG_1 @MemConfig1 str r1, [r0, #DMC_MEMCONFIG1] ldr r1, =0xFF000000 @PrechConfig str r1, [r0, #DMC_PRECHCONFIG] ldr r1, =DMC0_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E) str r1, [r0, #DMC_TIMINGAREF] ldr r1, =DMC0_TIMING_ROW @TimingRow for @200MHz str r1, [r0, #DMC_TIMINGROW] ldr r1, =DMC0_TIMING_DATA @TimingData CL=3 str r1, [r0, #DMC_TIMINGDATA] ldr r1, =DMC0_TIMING_PWR @TimingPower str r1, [r0, #DMC_TIMINGPOWER] ldr r1, =0x07000000 @DirectCmd chip0 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00020000 @DirectCmd chip0 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00030000 @DirectCmd chip0 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x07100000 @DirectCmd chip1 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00120000 @DirectCmd chip1 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00130000 @DirectCmd chip1 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x0FF02030 @ConControl auto refresh on str r1, [r0, #DMC_CONCONTROL] ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG] ldr r1, =0x00202400 @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] /* DMC1 initialization */ ldr r0, =APB_DMC_1_BASE ldr r1, =0x00101000 @Phycontrol0 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00000086 @Phycontrol1 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL1] ldr r1, =0x00101002 @PhyControl0 DLL on str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00101003 @PhyControl0 DLL start str r1, [r0, #DMC_PHYCONTROL0] find_lock_val1: ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value and r2, r1, #0x7 cmp r2, #0x7 @Loop until DLL is locked bne find_lock_val1 and r1, #0x3fc0 mov r2, r1, LSL #18 orr r2, r2, #0x100000 orr r2, r2, #0x1000 orr r1, r2, #0x3 @Force Value locking str r1, [r0, #DMC_PHYCONTROL0] #if 0 /* Memory margin test 10.01.05 */ orr r1, r2, #0x1 @DLL off str r1, [r0, #DMC_PHYCONTROL0] #endif /* settinf fot DDR2 */ ldr r0, =APB_DMC_1_BASE ldr r1, =0x0FFF2010 @auto refresh off str r1, [r0, #DMC_CONCONTROL] ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] ldr r1, =DMC1_MEMCONFIG_0 @MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed str r1, [r0, #DMC_MEMCONFIG0] ldr r1, =DMC1_MEMCONFIG_1 @MemConfig1 str r1, [r0, #DMC_MEMCONFIG1] ldr r1, =0xFF000000 str r1, [r0, #DMC_PRECHCONFIG] ldr r1, =DMC1_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4 str r1, [r0, #DMC_TIMINGAREF] ldr r1, =DMC1_TIMING_ROW @TimingRow for @200MHz str r1, [r0, #DMC_TIMINGROW] ldr r1, =DMC1_TIMING_DATA @TimingData CL=3 str r1, [r0, #DMC_TIMINGDATA] ldr r1, =DMC1_TIMING_PWR @TimingPower str r1, [r0, #DMC_TIMINGPOWER] ldr r1, =0x07000000 @DirectCmd chip0 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00020000 @DirectCmd chip0 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00030000 @DirectCmd chip0 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x07100000 @DirectCmd chip1 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00120000 @DirectCmd chip1 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00130000 @DirectCmd chip1 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110440 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x0FF02030 @ConControl auto refresh on str r1, [r0, #DMC_CONCONTROL] ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG] ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] #else /* CONFIG_MCP_SINGLE */ /* DMC0 initialization */ ldr r0, =APB_DMC_0_BASE ldr r1, =0x00101000 @Phycontrol0 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00000084 @Phycontrol1 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL1] ldr r1, =0x00101002 @Phycontrol2 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00101003 @Dll on str r1, [r0, #DMC_PHYCONTROL0] find_lock_val: ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value and r2, r1, #0x7 cmp r2, #0x7 @Loop until DLL is locked bne find_lock_val and r1, #0x3fc0 mov r2, r1, LSL #18 orr r2, r2, #0x100000 orr r2, r2, #0x1000 orr r1, r2, #0x3 @Force Value locking str r1, [r0, #DMC_PHYCONTROL0] #if 1 /* DRAM margin test 10.01.06 */ orr r1, r2, #0x1 @DLL off str r1, [r0, #DMC_PHYCONTROL0] #endif ldr r1, =0x0fff1010 @auto refresh off str r1, [r0, #DMC_CONCONTROL] ldr r1, =0x00212100 str r1, [r0, #DMC_MEMCONTROL] ldr r1, =DMC0_MEMCONFIG_0 str r1, [r0, #DMC_MEMCONFIG0] ldr r1, =DMC0_MEMCONFIG_1 str r1, [r0, #DMC_MEMCONFIG1] ldr r1, =0xff000000 str r1, [r0, #DMC_PRECHCONFIG] ldr r1, =DMC0_TIMINGA_REF str r1, [r0, #DMC_TIMINGAREF] ldr r1, =DMC0_TIMING_ROW @TimingRow @133MHz str r1, [r0, #DMC_TIMINGROW] ldr r1, =DMC0_TIMING_DATA str r1, [r0, #DMC_TIMINGDATA] ldr r1, =DMC0_TIMING_PWR @Timing Power str r1, [r0, #DMC_TIMINGPOWER] ldr r1, =0x07000000 @chip0 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000032 @chip0 MRS str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x07100000 @chip1 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100032 @chip1 MRS str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x0FFF20B0 @ConControl auto refresh on str r1, [r0, #DMC_CONCONTROL] ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG] ldr r1, =0x00212113 @MemControl str r1, [r0, #DMC_MEMCONTROL] /* DMC1 initialization */ ldr r0, =APB_DMC_1_BASE ldr r1, =0x00101000 @Phycontrol0 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00000084 @Phycontrol1 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL1] ldr r1, =0x00101002 @Phycontrol2 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00101003 @Dll on str r1, [r0, #DMC_PHYCONTROL0] find_lock_val1: ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value and r2, r1, #0x7 cmp r2, #0x7 @Loop until DLL is locked bne find_lock_val1 and r1, #0x3fc0 mov r2, r1, LSL #18 orr r2, r2, #0x100000 orr r2, r2, #0x1000 orr r1, r2, #0x3 @Force Value locking str r1, [r0, #DMC_PHYCONTROL0] #if 1 /* Memory margin test 10.01.05 */ orr r1, r2, #0x1 @DLL off str r1, [r0, #DMC_PHYCONTROL0] #endif ldr r0, =APB_DMC_1_BASE ldr r1, =0x0FFF1010 @auto refresh off str r1, [r0, #DMC_CONCONTROL] ldr r1, =DMC1_MEMCONTROL str r1, [r0, #DMC_MEMCONTROL] ldr r1, =DMC1_MEMCONFIG_0 str r1, [r0, #DMC_MEMCONFIG0] ldr r1, =DMC1_MEMCONFIG_1 str r1, [r0, #DMC_MEMCONFIG1] ldr r1, =0xff000000 str r1, [r0, #DMC_PRECHCONFIG] ldr r1, =DMC1_TIMINGA_REF str r1, [r0, #DMC_TIMINGAREF] ldr r1, =DMC1_TIMING_ROW @TimingRow @133MHz str r1, [r0, #DMC_TIMINGROW] ldr r1, =DMC1_TIMING_DATA str r1, [r0, #DMC_TIMINGDATA] ldr r1, =DMC1_TIMING_PWR @Timing Power str r1, [r0, #DMC_TIMINGPOWER] ldr r1, =0x07000000 @chip0 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000032 @chip0 MRS str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00020020 @chip0 EMRS str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x07100000 @chip1 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100032 @chip1 MRS str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00120020 @chip0 EMRS str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x0FFF10B0 @ConControl auto refresh on str r1, [r0, #DMC_CONCONTROL] ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG] ldr r1, =0x00212113 @MemControl str r1, [r0, #DMC_MEMCONTROL] #endif /* CONFIG_MCP_AC / CONFIG_MCP_H / CONFIG_MCP_B / CONFIG_MCP_D / CONFIG_MCP_N */ mov pc, lr /* * v7_flush_dcache_all() * * Flush the whole D-cache. * * Corrupted registers: r0-r5, r7, r9-r11 * * - mm - mm_struct describing address space */ .align 5 .global v7_flush_dcache_all v7_flush_dcache_all: ldr r0, =0xffffffff mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR ands r3, r0, #0x7000000 mov r3, r3, LSR #23 @ Cache level value (naturally aligned) beq Finished mov r10, #0 Loop1: add r2, r10, r10, LSR #1 @ Work out 3xcachelevel mov r1, r0, LSR r2 @ bottom 3 bits are the Ctype for this level and r1, r1, #7 @ get those 3 bits alone cmp r1, #2 blt Skip @ no cache or only instruction cache at this level mcr p15, 2, r10, c0, c0, 0 @ write the Cache Size selection register mov r1, #0 mcr p15, 0, r1, c7, c5, 4 @ PrefetchFlush to sync the change to the CacheSizeID reg mrc p15, 1, r1, c0, c0, 0 @ reads current Cache Size ID register and r2, r1, #0x7 @ extract the line length field add r2, r2, #4 @ add 4 for the line length offset (log2 16 bytes) ldr r4, =0x3FF ands r4, r4, r1, LSR #3 @ R4 is the max number on the way size (right aligned) clz r5, r4 @ R5 is the bit position of the way size increment ldr r7, =0x00007FFF ands r7, r7, r1, LSR #13 @ R7 is the max number of the index size (right aligned) Loop2: mov r9, r4 @ R9 working copy of the max way size (right aligned) Loop3: orr r11, r10, r9, LSL r5 @ factor in the way number and cache number into R11 orr r11, r11, r7, LSL r2 @ factor in the index number mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way subs r9, r9, #1 @ decrement the way number bge Loop3 subs r7, r7, #1 @ decrement the index bge Loop2 Skip: add r10, r10, #2 @ increment the cache number cmp r3, r10 bgt Loop1 Finished: mov pc, lr .align 5 .global disable_l2cache disable_l2cache: mrc p15, 0, r0, c1, c0, 1 bic r0, r0, #(1<<1) mcr p15, 0, r0, c1, c0, 1 mov pc, lr .align 5 .global enable_l2cache enable_l2cache: mrc p15, 0, r0, c1, c0, 1 orr r0, r0, #(1<<1) mcr p15, 0, r0, c1, c0, 1 mov pc, lr .align 5 .global set_l2cache_auxctrl set_l2cache_auxctrl: mov r0, #0x0 mcr p15, 1, r0, c9, c0, 2 mov pc, lr .align 5 .global set_l2cache_auxctrl_cycle set_l2cache_auxctrl_cycle: mrc p15, 1, r0, c9, c0, 2 bic r0, r0, #(0x1<<29) bic r0, r0, #(0x1<<21) bic r0, r0, #(0x7<<6) bic r0, r0, #(0x7<<0) mcr p15, 1, r0, c9, c0, 2 mov pc,lr .align 5 CoInvalidateDCacheIndex: ;/* r0 = index */ mcr p15, 0, r0, c7, c6, 2 mov pc,lr /* Below code is for ARM926EJS and ARM1026EJS */ .globl cleanDCache cleanDCache: mrc p15, 0, pc, c7, c10, 3 /* test/clean D-Cache */ bne cleanDCache mov pc, lr .globl cleanFlushDCache cleanFlushDCache: mrc p15, 0, pc, c7, c14, 3 /* test/cleanflush D-Cache */ bne cleanFlushDCache mov pc, lr .globl cleanFlushCache cleanFlushCache: mrc p15, 0, pc, c7, c14, 3 /* test/cleanflush D-Cache */ bne cleanFlushCache mcr p15, 0, r0, c7, c5, 0 /* flush I-Cache */ mov pc, lr .ltorg .globl ledon_1 ledon_1: /*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x11000 str r1, [r0, #GPC0CON_OFFSET] ldr r2, [r0, #GPC0CON_OFFSET] orr r2, r2, #0x08 str r2, [r0, #GPC0DAT_OFFSET] mov pc, lr .globl ledon_2 ledon_2: /*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x11000 str r1, [r0, #GPC0CON_OFFSET] ldr r2, [r0, #GPC0CON_OFFSET] orr r2, r2, #0x10 str r2, [r0, #GPC0DAT_OFFSET] mov pc, lr .globl ledon ledon: /*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x11000 str r1, [r0, #GPC0CON_OFFSET] ldr r2, =0x18 str r2, [r0, #GPC0DAT_OFFSET] mov pc, lr .globl ledoff ledoff: /*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x11000 str r1, [r0, #GPC0CON_OFFSET] ldr r2, =0x00 str r2, [r0, #GPC0DAT_OFFSET] mov pc, lr
crt0.S的完整代码(这个代码u-boot本身就有,并且不需要改动,但这里也贴出来):
/* * crt0 - C-runtime startup Code for ARM U-Boot * * Copyright (c) 2012 Albert ARIBAUD <albert.u.boot@aribaud.net> * * 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 <config.h> #include <asm-offsets.h> /* * This file handles the target-independent stages of the U-Boot * start-up where a C runtime environment is needed. Its entry point * is _main and is branched into from the target's start.S file. * * _main execution sequence is: * * 1. Set up initial environment for calling board_init_f(). * This environment only provides a stack and a place to store * the GD ('global data') structure, both located in some readily * available RAM (SRAM, locked cache...). In this context, VARIABLE * global data, initialized or not (BSS), are UNAVAILABLE; only * CONSTANT initialized data are available. * * 2. Call board_init_f(). This function prepares the hardware for * execution from system RAM (DRAM, DDR...) As system RAM may not * be available yet, , board_init_f() must use the current GD to * store any data which must be passed on to later stages. These * data include the relocation destination, the future stack, and * the future GD location. * * (the following applies only to non-SPL builds) * * 3. Set up intermediate environment where the stack and GD are the * ones allocated by board_init_f() in system RAM, but BSS and * initialized non-const data are still not available. * * 4. Call relocate_code(). This function relocates U-Boot from its * current location into the relocation destination computed by * board_init_f(). * * 5. Set up final environment for calling board_init_r(). This * environment has BSS (initialized to 0), initialized non-const * data (initialized to their intended value), and stack in system * RAM. GD has retained values set by board_init_f(). Some CPUs * have some work left to do at this point regarding memory, so * call c_runtime_cpu_setup. * * 6. Branch to either nand_boot() or board_init_r(). */ /* * declare nand_boot() or board_init_r() to jump to at end of crt0 */ #if defined(CONFIG_NAND_SPL) .globl nand_boot #elif !defined(CONFIG_SPL_BUILD) .globl board_init_r #endif /* * start and end of BSS */ .globl __bss_start .globl __bss_end__ /* * entry point of crt0 sequence */ .global _main _main: /* * Set up initial C runtime environment and call board_init_f(0). */ #if defined(CONFIG_NAND_SPL) /* deprecated, use instead CONFIG_SPL_BUILD */ ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr sp, =(CONFIG_SPL_STACK) #else ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #endif bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ sub sp, #GD_SIZE /* allocate one GD above SP */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ mov r8, sp /* GD is above SP */ mov r0, #0 bl board_init_f #if ! defined(CONFIG_SPL_BUILD) /* * Set up intermediate environment (new sp and gd) and call * relocate_code(addr_sp, gd, addr_moni). Trick here is that * we'll return 'here' but relocated. */ ldr sp, [r8, #GD_START_ADDR_SP] /* r8 = gd->start_addr_sp */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ ldr r8, [r8, #GD_BD] /* r8 = gd->bd */ sub r8, r8, #GD_SIZE /* new GD is below bd */ adr lr, here ldr r0, [r8, #GD_RELOC_OFF] /* lr = gd->start_addr_sp */ add lr, lr, r0 ldr r0, [r8, #GD_START_ADDR_SP] /* r0 = gd->start_addr_sp */ mov r1, r8 /* r1 = gd */ ldr r2, [r8, #GD_RELOCADDR] /* r2 = gd->relocaddr */ b relocate_code here: /* Set up final (full) environment */ bl c_runtime_cpu_setup /* we still call old routine here */ ldr r0, =__bss_start /* this is auto-relocated! */ ldr r1, =__bss_end__ /* this is auto-relocated! */ mov r2, #0x00000000 /* prepare zero to clear BSS */ clbss_l:cmp r0, r1 /* while not at end of BSS */ strlo r2, [r0] /* clear 32-bit BSS word */ addlo r0, r0, #4 /* move to next */ blo clbss_l bl coloured_LED_init bl red_led_on #if defined(CONFIG_NAND_SPL) /* call _nand_boot() */ ldr pc, =nand_boot #else /* call board_init_r(gd_t *id, ulong dest_addr) */ mov r0, r8 /* gd_t */ ldr r1, [r8, #GD_RELOCADDR] /* dest_addr */ /* call board_init_r */ ldr pc, =board_init_r /* this is auto-relocated! */ #endif /* we should not return here. */ #endif