上一篇思路有点乱,又参考了一些资料,随手记录一下。
因为最近用的Xilinx,所以以arm里面的arm7为例:
u-boot的启动过程可以分为两个阶段,分别如下:
第一阶段:
.初始化硬件:如关看门狗、设置时钟、设置SDRAM、初始化NANFLASH等
.如果u-boot的代码量较大,将其u-boot代码加载到SDRAM,即重定位到SDRAM
.设置好栈
.跳转到第二阶段代码入口
第二阶段
.初始化本阶段使用的一些硬件设备
.检测系统内存映射
.将内核从FLASH读取到RAM中
.设置“要传给内核的参数”
.调用内核
第一阶段
程序入口:由u-boot.lds(/arch/arm/cpu/u-boot.lds)的ENTRY(_start)可知,程序的入口在_start。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") //输出格式为elf,32位,小端
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
......
. = 0x00000000;
. = ALIGN(4);
.text :
{
*(.__image_copy_start)
*(.vectors)
CPUDIR/start.o (.text*)
*(.text*)
}
入口_start在/arch/arm/lib/vertors.S中,
_start:
#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
.word CONFIG_SYS_DV_NOR_BOOT_CFG
#endif
ARM_VECTORS
#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */
文件开始定义了ARM_VECTORS
/*
* A macro to allow insertion of an ARM exception vector either
* for the non-boot0 case or by a boot0-header.
*/
.macro ARM_VECTORS
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
.endm
可以看到,从_start入口进去后,立刻跳转到reset中执行。而resert在start.S中。
来到start.S:(/arch/arm/cpu/armv7/start.s)
/*
* armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
*
* Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com>
*
* Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
* Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
* Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
* Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003 Kshitij <kshitij@ti.com>
* Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm-offsets.h>
#include <config.h>
#include <asm/system.h>
#include <linux/linkage.h>
#include <asm/armv7.h>
/*************************************************************************
*
* 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 reset
.globl save_boot_params_ret
.type save_boot_params_ret,%function
#ifdef CONFIG_ARMV7_LPAE
.global switch_to_hypervisor_ret
#endif
//(1)单板保存一些重要参数(默认不保存)
reset:
/* Allow the board to save important registers */
b save_boot_params
save_boot_params_ret:
#ifdef CONFIG_ARMV7_LPAE
/*
* check for Hypervisor support
*/
mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1
and r0, r0, #CPUID_ARM_VIRT_MASK @ mask virtualization bits
cmp r0, #(1 << CPUID_ARM_VIRT_SHIFT)
beq switch_to_hypervisor
switch_to_hypervisor_ret:
#endif
//(2)屏蔽中断
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
*/
mrs r0, cpsr
and r1, r0, #0x1f @ mask mode bits
teq r1, #0x1a @ test for HYP mode
bicne r0, r0, #0x1f @ clear all mode bits
orrne r0, r0, #0x13 @ set SVC mode
orr r0, r0, #0xc0 @ disable FIQ and IRQ
msr cpsr,r0
/*
* Setup vector:
* (OMAP4 spl TEXT_BASE is not 32 byte aligned.
* Continue to use ROM code vector only in OMAP4 spl)
*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register
bic r0, #CR_V @ V = 0
mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif
//(3)底层相关初始化,然后跳转到_main函数执行。
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_cp15
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
bl cpu_init_crit
#endif
#endif
bl _main
/*------------------------------------------------------------------------------*/
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
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)
b save_boot_params_ret @ back to my caller
ENDPROC(save_boot_params)
.weak save_boot_params
#ifdef CONFIG_ARMV7_LPAE
ENTRY(switch_to_hypervisor)
b switch_to_hypervisor_ret
ENDPROC(switch_to_hypervisor)
.weak switch_to_hypervisor
#endif
/*************************************************************************
*
* 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
mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
/*
* 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 @