/* * 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> @@在mkconfig里边编译生成的,位置include目录下 #include <version.h> @@包含一个头文件,头文件里存到版本号 #if defined(CONFIG_ENABLE_MMU) #include <asm/proc/domain.h> @@跟mkconfig有关,符号链接 #endif #include <regs.h> @@跟mkconfig有关,符号链接 #ifndef CONFIG_ENABLE_MMU #ifndef CFG_PHY_UBOOT_BASE #define CFG_PHY_UBOOT_BASE CFG_UBOOT_BASE #endif #endif
#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED) .word 0x2000 @@定义了一个变量(四个字节),这个变量的值是0x2000 .word 0x0 .word 0x0 .word 0x0 #endif @@这十六字节是为了那十六字节的校验头预留的 @@什么要加这十六字节的数据呢;SD卡启动/Nand启动等整个镜像开头需要16字节的校验头,所以先在这占着,SD启动的时候mkv210image.c会给它加16字节的校验头(现在这个校验和是不对的,后边要去计算校验重新填充) @@这十六字节是为了那十六字节的校验头预留的 .globl _start @@.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 @@快速中断
_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 */ .global _end_vect _end_vect: .balignl 16,0xdeadbeef @@di zhi dui qi,这些内存用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 * ************************************************************************* */ _TEXT_BASE: @@链接地址;TEXT_BASE = 0xc3e00000 .word TEXT_BASE @@在makefile的2591行有给他一个地址(这个值来自于makefile)
主要用来后边清理bss段
/* * 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 .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
uboot中很少使用
#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 @@cpsr 是cheng xu 状态寄存器;_c 为0~7位; @@CPU设置为禁止FIQ和 IRQ,状态是ARM状态,SVC模式
@@底层的初始化 bl disable_l2cache @@禁止L2 cache bl set_l2cache_auxctrl_cycle @@L2 cache相关的初始化 bl enable_l2cache @@使能L2 cache /* * Invalidate L1 I/D @@刷新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
判断是nand还是sd启动
/* Read booting information */ @@读取启动信息 ldr r0, =PRO_ID_BASE @@PRO_ID_BASE寄存器通过读取硬件OM引脚,判断启动介质是nand还是sd ldr r1, [r0,#OMR_OFFSET] bic r2, r1, #0xffffffc1 @@将启动的信息存在r2中,r2的值决定了是从SD启动还是nand启动
/* 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 @@通过比较r2里边的值,确定r3里的值 /* NOR BOOT */ cmp r2, #0x14 moveq r3, #BOOT_NOR
到这要去分析lowlevel_init这个函数
/* * Go setup Memory and board specific bits prior to relocation. */ @@设置栈,栈的位置在SRAM(DDR); 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 */ @@初始化一些底层的东西
没有什么意义,lowleve_init.S里有锁存过
/* 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 */ @@设置栈(又),这次栈的位置在DDR里边。为什么要再次设置,因为原来SRAM中的内存少,容易溢出 ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */ 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 @@这个寄存器 硬件会自动往这里给值,通过这个值判断使用的是哪个口SD0是0xEB000000 SD2是0xEB200000 ldr r1, [r0] ldr r2, =0xEB200000 cmp r1, r2 @@读出来的值跟0xEB200000比较 beq
ldr r0, =INF_REG_BASE ldr r1, [r0, #INF_REG3_OFFSET] @@在把277行存入的值取出来 cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */ @@在比较,确定启动方式,跳转到BOOT_MMCSD 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
去movi.c文件分析
bl movi_bl2_copy @@真正的重定位在是这个函数里实现的
b after_copy @@虚拟地址映射
after_copy: #if defined(CONFIG_ENABLE_MMU) enable_mmu: /* enable domain access */ @@使能预访问 ldr r5, =0x0000ffff mcr p15, 0, r5, c3, c0, 0 @load domain access register @@协处理器里的c3是用来控制域访问的 @@ @@mcr指令是用来写协处理器的,mrc指令是用来读协处理器的 /* Set the TTB register */ @@TTB就是转换表的基址;找出重定位到DDR里边的转换表的地址 ldr r0, _mmu_table_base 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 @@将c1的值读到r0 orr r0, r0, #1 @@把1或到r0 mcr p15, 0, r0, c1, c0, 0 @@将r0的值写到c1,打开MMU nop nop nop nop #endif
skip_hw_init: /* Set up the stack */ stack_setup: #if defined(CONFIG_MEMORY_UPPER_CODE) ldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000) @@第三次设置栈是在合适的位置设置栈;安全、紧凑不浪费内存;设置在uboot起始地址上方的2M那,栈是满减栈 #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
clear_bss: @@清BSS段 ldr r0, _bss_start /* find start of bss segment */@@_bss_start 来自链接脚本,但是他的值在本文件里定义 ldr r1, _bss_end /* stop here */ @@_end 来自链接脚本,但是他的值在本文件里定义 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 @@第一阶段的最后一步,也是第二阶段的开始;使用的是远跳转,可以从SRAM跳转到DDR中(当前还在SRAM中运行);_start_armboot 相当于一个指针,指向一个函数 @@在uboot/lib_arm/board.c