在[37]_uboot中顶层Makefile、config.mk、u-boot.lds之间的三角恋关系之简单分析 中,分析了到uboot.lds的入口地址是ENTRY(_start),本节接着分析uboot启动的第一阶段,其中uboot启动的第一阶段做的事情,我总结如下:
1.构建异常向量表 (一种是7种异常)
2.开icache (icache是SOC内部的一个器件,读写速度仅次于cpu > 寄存器 > icache > DDR )
3.关MMU (MMU是虚拟内存映射)
4.读取板子的启动信息 ( 可以从norflash、SD\MMC、nandflash等启动介质 )
5.设置sp栈地址 (此时栈地址是设置在soc那种的iram中),然后使用bl _lowlevel_init 进一步进行系统级的初始化
在lowlevel_init.S做的事情如下:
1.检测板子的复位状态
2.关看门狗
3.初始化soc内部的sram
4. PS_HOLD 置为高电平 (主要是硬件的需要,上电锁存)
5. 接下来是调用下面几个幻术初始化soc片内外设和内存
bl system_clock_init (初始化系统时钟)
bl men_ctrl_asm_init (初始化外部的DDR内存)
bl uart_asm_init ( 初始化串口,串口正常初始化后打印出来一个 “OK” )
6. 设置DDR栈地址 (原因是在lowlevel_init.S中已经初始化了DDR,现在可以使用了DDR)
7.执行uboot中的BL2部分重定位到DDR中 (使用的函数是 movi_bl2_copy )
8.开启MMU虚拟内存地址映射 ( 操作MMU主要是操作cp15协处理器,建立TTB,然后再使能MMU )
9.再次设置DDR中的sp栈地址 (目的是使这个sp栈地址设置再DDR中更合适的位置,避免栈溢出)
10.清bss段 ,然后跳转到uboot的第二的启动阶段 (主要使执行这条语句: ldr pc, _start_armboot )
下面使代码start.S 和 lowlevel_init.S的详细解读:
star.S文件中的代码: /* * armboot - Startup Code for S5PC110/ARM-Cortex CPU-core * * Copyright (c) 2009 Samsung Electronics * * * 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 * * Base codes by scsuh (sc.suh) */ #include <config.h> //指向#include <configs/x210_sd.h> -->整个uboot移植的配置文件 #include <version.h> //指向#include "version_autogenerated.h" --->等于顶层Makefile中指定的uboot的版本信息 #if defined(CONFIG_ENABLE_MMU) //MMU被定义 #include <asm/proc/domain.h> #endif #include <regs.h> //SOC 片内寄存器基地址和偏移地址的定义 #ifndef CONFIG_ENABLE_MMU #ifndef CFG_PHY_UBOOT_BASE #define CFG_PHY_UBOOT_BASE CFG_UBOOT_BASE #endif #endif /* ************************************************************************* * * Jump vector table as in table 3.1 in [1] * ************************************************************************* */ #if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED) //成立 .word 0x2000 // .word 是个伪指令,跟int类型差不多,主要是拿来占位的,4个.word一共占16位 .word 0x0 .word 0x0 .word 0x0 #endif .globl _start //异常向量表的构建,异常向量表的每一种异常都应该处理 _start: b reset //uboot中异常处理一般是处理这个,其它异常基本上不会被执行 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 _undefined_instruction: .word undefined_instruction // undefined_instruction 这些是函数 ,不过这uboot中这些函数基本上不会被执行 _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 */ .global _end_vect _end_vect: .balignl 16,0xdeadbeef //内存16字节对齐,如果没对齐,则使用 deadbeef 这些填充 /* ************************************************************************* * * 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 * ************************************************************************* */ _TEXT_BASE: .word TEXT_BASE //这个 TEXT_BASE 是程序的链接地址,是在uboot配置前期 指定的 /* * 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. */ _TEXT_PHY_BASE: .word CFG_PHY_UBOOT_BASE //通过计算:CFG_PHY_UBOOT_BASE = 0x33e00000 .globl _armboot_start _armboot_start: .word _start /* * These are defined in the board-specific linker script. */ .globl _bss_start _bss_start: .word __bss_start .globl _bss_end _bss_end: .word _end #if defined(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 /* * the actual reset code */ reset: /* * set the cpu to SVC32 mode and IRQ & FIQ disable */ @;mrs r0,cpsr @;bic r0,r0,#0x1f @;orr r0,r0,#0xd3 @;msr cpsr,r0 msr cpsr_c, #0xd3 @ I & F disable, Mode: 0x13 - SVC /* ************************************************************************* * * CPU_init_critical registers * * setup important registers * setup memory timing * ************************************************************************* */ /* * we do sys-critical inits only at reboot, * not when booting from ram! */ cpu_init_crit: #ifndef CONFIG_EVT1 /*-- 无用代码,可以删掉 --*/ #if 0 bl v7_flush_dcache_all #else 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 #endif bl disable_l2cache /*-- 禁止L2 cache --*/ bl set_l2cache_auxctrl_cycle /*-- l2 cache相关初始化--*/ bl enable_l2cache /*-- 使能l2 cache --*/ /* * Invalidate L1 I/D /*这段代码的作用是:刷新L1 cache的icache和dcache*/ */ 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 /*-- 关MMU -- / */ 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 /* Read booting information */ /*这段代码R2的值决定开发板从sd启动*/ ldr r0, =PRO_ID_BASE ldr r1, [r0,#OMR_OFFSET] bic r2, r1, #0xffffffc1 #ifdef CONFIG_VOGUES /*学习:不是这个开发板,可以删掉这部分的代码*/ /* PS_HOLD(GPH0_0) set to output high */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x00000001 str r1, [r0, #GPH0CON_OFFSET] ldr r1, =0x5500 str r1, [r0, #GPH0PUD_OFFSET] ldr r1, =0x01 str r1, [r0, #GPH0DAT_OFFSET] #endif /* NAND BOOT */ /* NAND启动介质 */ cmp r2, #0x0 @ 512B 4-cycle moveq r3, #BOOT_NAND cmp r2, #0x2 @ 2KB 5-cycle, /* 512B、2KB都是小页nand*/ moveq r3, #BOOT_NAND cmp r2, #0x4 @ 4KB 5-cycle 8-bit ECC /* 4KB都是大页nand */ 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 */ /* SD/MMC启动介质 */ cmp r2, #0xc moveq r3, #BOOT_MMCSD /* NOR BOOT */ /* NOR 启动介质 */ cmp r2, #0x14 moveq r3, #BOOT_NOR #if 0 /* Android C110 BSP uses OneNAND booting! */ /* For second device booting */ /* OneNAND BOOTONG failed */ cmp r2, #0x8 moveq r3, #BOOT_SEC_DEV #endif /* Uart BOOT ONG failed */ cmp r2, #(0x1<<4) moveq r3, #BOOT_SEC_DEV ldr r0, =INF_REG_BASE str r3, [r0, #INF_REG3_OFFSET] /* * Go setup Memory and board specific bits prior to relocation. */ ldr sp, =0xd0036000 /* end of sram dedicated to u-boot */ /*调用函数前必须设置栈*/ sub sp, sp, #12 /* set stack */ mov fp, #0 bl lowlevel_init /* go setup pll,mux,memory */ /*这个函数初始化了时钟、DDR、串口等*/ /* To hold max8698 output before releasing power on switch, * set PS_HOLD signal to high */ ldr r0, =0xE010E81C /* PS_HOLD_CONTROL register */ ldr r1, =0x00005301 /* PS_HOLD output high */ str r1, [r0] /* get ready to call C functions */ /* 因为在lowlevel_init初始化了DDR,所以接下来是把uboot搬到DDR中执行 */ ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */ /*栈转移到DDR中,在DDR中重新设置栈地址*/ sub sp, sp, #12 mov fp, #0 /* no previous frame, so fp=0 */ /* 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 after_copy /* r0 == r1 then skip flash copy */ #if defined(CONFIG_EVT1) /*这部分是重定位代码*/ /* If BL1 was copied from SD/MMC CH2 */ ldr r0, =0xD0037488 /* 这个是来自 S5PV210_iROM_ApplicationNote_Preliminary_20091126.pdf,是由硬件自动设置的 */ 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: mov r0, #0x1000 bl copy_from_nand b after_copy onenand_boot: bl onenand_bl2_copy b after_copy mmcsd_boot: #if DELETE ldr sp, _TEXT_PHY_BASE sub sp, sp, #12 mov fp, #0 #endif bl movi_bl2_copy //在SD卡uboot的BL2是通过movi_bl2_copy这个函数完成的。 b after_copy nor_boot: bl read_hword b after_copy after_copy: #if defined(CONFIG_ENABLE_MMU) //使能MMU虚拟内存映射,操作MMU就是操作cp15协处理器 enable_mmu: /* enable domain access */ ldr r5, =0x0000ffff mcr p15, 0, r5, c3, c0, 0 @load domain access register /* Set the TTB register */ //TTB 即是 转换表基地址 ldr r0, _mmu_table_base //_mmu_table_base函数,实现最初始的mmu_table ldr r1, =CFG_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 skip_hw_init: /* Set up the stack */ //再次设置栈,主要是把栈在设置在DDR合理的位置,实现资源的最有效利用 stack_setup: #if defined(CONFIG_MEMORY_UPPER_CODE) ldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000) //*0xc3e00000 + (2*1024*1024) - 0x1000 *// #else ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #if defined(CONFIG_USE_IRQ) sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12 /* leave 3 words for abort-stack */ #endif /* stack setup ending */ clear_bss: //清楚bss段,bss段的开头和结尾都来自u-boot.lds ldr r0, _bss_start /* find start of bss segment */ ldr r1, _bss_end /* stop here */ mov r2, #0x00000000 /* clear */ clbss_l: str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 ble clbss_l ldr pc, _start_armboot /*这里这个 ldr 远跳转就是uboot第一阶段和第二阶段的分界线。*/ _start_armboot: .word start_armboot / /*start_armboot是一个函数指针,是u-boot的stage2的入口点*// #if defined(CONFIG_ENABLE_MMU) _mmu_table_base: .word mmu_table #endif /* * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND) * r0: size to be compared * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size */ .globl copy_from_nand copy_from_nand: push {lr} /* save return address */ mov r9, r0 mov r9, #0x100 /* Compare about 8KB */ bl copy_uboot_to_ram /**从Inand中拷贝uboot到SDRAM**/ tst r0, #0x0 bne copy_failed #if defined(CONFIG_EVT1) ldr r0, =0xd0020000 #else ldr r0, =0xd0030000 #endif ldr r1, _TEXT_PHY_BASE /* 0x23e00000 */ #if !defined(CONFIG_SECURE_BOOT) 1: ldr r3, [r0], #4 ldr r4, [r1], #4 teq r3, r4 bne compare_failed /* not matched */ subs r9, r9, #4 bne 1b #endif pop {pc} /* all is OK */ copy_failed: nop /* copy from nand failed */ b copy_failed compare_failed: nop /* compare failed */ b compare_failed /* * 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 /* ************************************************************************* * * 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, _armboot_start sub r2, r2, #(CFG_MALLOC_LEN) sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ 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, _armboot_start @ setup our mode stack (enter in banked mode) sub r13, r13, #(CFG_MALLOC_LEN) @ move past malloc pool sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack 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, _armboot_start @ get data regions start sub r0, r0, #(CFG_MALLOC_LEN) @ move past malloc pool sub r0, r0, #(CFG_GBL_DATA_SIZE+8) @ move past gbl and a couple 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 #if defined(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 effiction 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 .align 5 .global arm_cache_flush arm_cache_flush: mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache mov pc, lr @ back to caller /* * 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 #if defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_CINTEGRATOR) /* Use the IntegratorCP function from board/integratorcp/platform.S */ #elif defined(CONFIG_S5PC11X) /* For future usage of S3C64XX*/ #else .align 5 .globl reset_cpu reset_cpu: ldr r1, rstctl /* get addr for global reset reg */ mov r3, #0x2 /* full reset pll+mpu */ str r3, [r1] /* force reset */ mov r0, r0 _loop_forever: b _loop_forever rstctl: .word PM_RSTCTRL_WKUP #endif
lowlevel_init.S文件: /* * Memory Setup stuff - taken from blob memsetup.S * * Copyright (C) 1999 2000 2001 Erik Mouw ([email protected]) and * Jan-Derk Bakker ([email protected]) * * Modified for the Samsung SMDK2410 by * (C) Copyright 2002 * David Mueller, ELSOFT AG, <[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 <config.h> #include <version.h> #include <s5pc110.h> #include "smdkc110_val.h" _TEXT_BASE: .word TEXT_BASE .globl lowlevel_init lowlevel_init: push {lr} /* check reset status */ ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) //0xE0100000 + 0xa000 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 */ //这里是soc内部动态内存的初始化 2018.06.18 /* 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) //0xE0100000 + 0xe81c 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. */ /*##### 这里做的操作是否要初始化下面的时钟和DDR内存 ######*/ ldr r0, =0xff000fff bic r1, pc, r0 /* r0 <- current base addr of code */ /*将pc的值中的某些bit位清0,剩下一些特殊的bit位赋值给r1*/ ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */ /*加载链接地址到r2,然后将r2的相应位清0剩下特定位。*/ bic r2, r2, r0 /* r0 <- current base addr of code */ cmp r1, r2 /* compare r0, r1 */ beq 1f /* r0 == r1 then skip sdram init */ /*这里的1f不是标号,真正的标号是123行的:1:*/ /* init system clock */ bl system_clock_init //系统时钟的初始化 (重点) /* Memory initialize */ bl mem_ctrl_asm_init //外部DDR初始化 (重点) 1: /* for UART */ bl uart_asm_init //UART串口初始化 (这个初始化完成后打印出来一个“O”.说明前面时钟、DDR初始化都是没问题了) bl tzpc_init //可信区域保护控制器初始化 #if defined(CONFIG_ONENAND) bl onenandcon_init #endif #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 */ //不知道ABB是什么鬼,应该是SOC内部的一个旗舰,反正是关掉它 ldr r0, =0xE010C300 orr r1, r1, #(0x1<<23) str r1, [r0] /* Print 'K' */ //打印出来这一句,说明上面的时钟、DDR、串口初始化应该是没问题了 ldr r0, =ELFIN_UART_CONSOLE_BASE //这应该是开发板启动后从串口打印出来的最开始的信息了。 ldr r1, =0x4b4b4b4b str r1, [r0, #UTXH_OFFSET] pop {pc} 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 */ wakeup_reset: /* init system clock */ bl system_clock_init bl mem_ctrl_asm_init bl tzpc_init #if defined(CONFIG_ONENAND) bl onenandcon_init #endif #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] /********lxg added*********************/ ldr r0, =ELFIN_CLOCK_POWER_BASE @0xe0100000 ldr r1, =MPLL_LOCKTIME_VAL str r1, [r0, #MPLL_LOCK_OFFSET] /********end*********************/ /* 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] /*******lxg added***********************/ ldr r1, =EPLL_VAL str r1, [r0, #EPLL_CON_OFFSET] /*******lxg added***********************/ ldr r1, [r0, #CLK_DIV1_OFFSET] ldr r2, =CLK_DIV1_MASK bic r1, r1, r2 ldr r2, =CLK_DIV1_VAL orr r1, r1, r2 str r1, [r0, #CLK_DIV1_OFFSET] ldr r1, [r0, #CLK_DIV2_OFFSET] ldr r2, =CLK_DIV2_MASK bic r1, r1, r2 ldr r2, =CLK_DIV2_VAL orr r1, r1, r2 str r1, [r0, #CLK_DIV2_OFFSET] ldr r1, [r0, #CLK_DIV4_OFFSET] ldr r2, =CLK_DIV4_MASK bic r1, r1, r2 ldr r2, =CLK_DIV4_VAL orr r1, r1, r2 str r1, [r0, #CLK_DIV4_OFFSET] ldr r1, [r0, #CLK_DIV6_OFFSET] ldr r2, =CLK_DIV6_MASK bic r1, r1, r2 ldr r2, =CLK_DIV6_VAL orr r1, r1, r2 str r1, [r0, #CLK_DIV6_OFFSET] /*******end*****************/ /*******end*****************/ #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 //lxg changed. ldr r2, =0x00000111 orr r1, r1, r2 str r1, [r0, #CLK_SRC0_OFFSET] // added by terry 2012.12.4 for camera ldr r1, [r0, #CLK_SRC1_OFFSET] bic r1, r1, #(0xf<<12) orr r1, r1, #(0x1<<12) //0001 XusbXTI str r1, [r0, #CLK_SRC1_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_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]*/ //lxg mask #endif mov pc, lr /* * uart_asm_init: Initialize UART in asm mode, 115200bps fixed. * void uart_asm_init(void) */ 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] // HP V210 use. SMDK not use. #if defined(CONFIG_VOGUES) ldr r1, =0x100 str r1, [r0, #GPC0CON_OFFSET] ldr r1, =0x4 str r1, [r0, #GPC0DAT_OFFSET] #endif 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' //打印出来一个“O”说明前面是没问题了 mov pc, lr /* * 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 /* * Setting TZPC[TrustZone Protection Controller] */ tzpc_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 /* * OneNAND Interface Init */ onenandcon_init: @; GPIO setting for OneNAND ldr r0, =ELFIN_GPIO_BASE @0xE0200000 ldr r1, [r0, #MP01CON_OFFSET] orr r1, r1, #0x00550000 str r1, [r0, #MP01CON_OFFSET] ldr r1, [r0, #MP03CON_OFFSET] orr r1, r1, #0x0550 orr r1, r1, #0x00550000 str r1, [r0, #MP03CON_OFFSET] ldr r1, =0xFFFF str r1, [r0, #MP01DRV_SR_OFFSET] str r1, [r0, #MP03DRV_SR_OFFSET] str r1, [r0, #MP06DRV_SR_OFFSET] str r1, [r0, #MP07DRV_SR_OFFSET] wait_orwb: @; Read ONENAND_IF_STATUS ldr r0, =ELFIN_ONENANDCON_BASE @; 0xB0600000 ldr r1, [r0, #ONENAND_IF_STATUS_OFFSET] bic r1, r1, #0xFFFFFFFE cmp r1, #0x0 @; ORWB != 0x0 bne wait_orwb @; write new configuration to onenand system configuration1 register ldr r1, =0xF006 @; Sync. ldr r2, =(ELFIN_ONENAND_BASE+0x1E442) @; 0x1E442(REG_SYS_CONF1) strh r1, [r2] @; read one dummy halfword ldrh r1, [r2] ldrh r1, [r2] @; write new configuration to ONENAND_IF_CTRL ldr r0, =ELFIN_ONENANDCON_BASE @; 0xB0600000 @;ldr r1, =0x2F006 @; ONENAND_IF_CTRL_REG_VAL (GCE off) ldr r1, =0x402F006 @; ONENAND_IF_CTRL_REG_VAL (GCE on) str r1, [r0, #ONENAND_IF_CTRL_OFFSET] 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 .set __base,0x200 // should be accessed .rept 0x600 - 0x200 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr .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 // 0xC000_0000鏄犲皠鍒?x2000_0000 .set __base,0x300 //.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 // 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 .set __base,0x300 // should be accessed .rept 0x400 - 0x300 //.rept 0x350 - 0x300 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr // Not Allowed //.rept 0x400 - 0x350 //.word 0x00000000 //.endr // DRAM - DMC1 area - used for STL_write : djpark (20090729) .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 .set __base,0x300 // 80MB for SDRAM with cacheable .rept 0xd00 - 0xC00 //.rept 0xC50 - 0xC00 FL_SECTION_ENTRY __base,3,0,1,1 .set __base,__base+1 .endr // Not Allowed @.rept 0xD00 - 0xC80 @.word 0x00000000 @.endr // Not Allowed //.rept 0xD00 - 0xC50 //.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 #endif后续.......