Uboot start process analysis (a)

1 Introduction

Starting Linux systems require a bootloader program, the bootloader will first initialize the DDR program and other peripherals, and then copy the Linux kernel from flash to DDR, the last start of the Linux kernel, uboot is called the Universal Boot Loader, Linux systems commonly used uboot bootloader that is, the next will be a simple process analysis start uboot, uboot source to uboot-imx-rel_imx_4.15_2.1.0.

 

2, uboot inlet

 After prior to analysis, the need for the entire project uboot compile, generate some need to use when analyzing documents, such as links and documents uboot.lds uboot mapping file uboot.map, by linking the file, you can find the entrance of uboot, uboot boot found the first line of code runs.

Find links uboot source file uboot.lds in the root directory, as follows:

The OUTPUT_FORMAT ( " ELF32-littlearm " , " ELF32-littlearm " , " ELF32-littlearm " ) 
The OUTPUT_ARCH (ARM) 
the ENTRY (_start)    // current entry _start 
a SECTIONS 
{ 
 . = 0x00000000 ; 
 . = The ALIGN ( . 4 ); 
 .text: 
 {
   * (.__ image_copy_start)   // entry 
  * (. Vectors) // interrupt vector table 
  Arch / ARM / CPU / ARMv7 / start.o (.text *) // Arch / ARM / CPU / ARMv7 / Start.S snippet 
  * (. * text ) 
 } 
 .= ALIGN(4);
 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 . = ALIGN(4);
 .data : {
  *(.data*)
 }
 . = ALIGN(4);
 . = .;
 . = ALIGN(4);
 .u_boot_list : {
  KEEP(*(SORT(.u_boot_list*)));
 }
 . = ALIGN(4);
 .image_copy_end :
 {
  *(.__image_copy_end)
 }
 .rel_dyn_start :
 {
  *(.__rel_dyn_start)
 }
 .rel.dyn : {
  *(.rel*)
 }
 .rel_dyn_end :
 {
  *(.__rel_dyn_end)
 }
 .end :
 {
  *(.__end)
 }
 _image_binary_end = .;
 . = ALIGN(4096);
 .mmutable : {
  *(.mmutable)
 }
 .bss_start __rel_dyn_start (OVERLAY) : {
  KEEP(*(.__bss_start));
  __bss_base = .;
 }
 .bss __bss_base (OVERLAY) : {
  *(.bss*)
   . = ALIGN(4);
   __bss_limit = .;
 }
 .bss_end __bss_limit (OVERLAY) : {
  KEEP(*(.__bss_end));
 }
 .dynsym _image_binary_end : { *(.dynsym) }
 .dynbss : { *(.dynbss) }
 .dynstr : { *(.dynstr*) }
 .dynamic : { *(.dynamic*) }
 .plt : { *(.plt*) }
 .interp : { *(.interp*) }
 .gnu.hash : { *(.gnu.hash) }
 .gnu : { *(.gnu*) }
 .ARM.exidx : { *(.ARM.exidx*) }
 .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
}

In the above link file may be determined as _start uboot inlet, which is defined in the arch / arm / lib / vectors.S file:

_start:

#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
    .word    CONFIG_SYS_DV_NOR_BOOT_CFG
#endif

    b    reset    //中断向量表,跳转到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

 After entering the _start, B run reset code to jump to the reset operation, reset back with B as defined in the interrupt vector table, the reset is not unreasonable for different architectures for the i.mx6ul NXP chip, which is defined in the arch /arm/cpu/armv7/start.S file:

    the RESET .globl 
    .globl save_boot_params_ret 

the RESET: 
    / * the Allow at The Board to the Save Important Registers * / 
    b save_boot_params     // skip save_boot_params 
save_boot_params_ret:
     / * 
     * disable interrupts (FIQ and IRQ), Also the CPU to the SET at The SVC32 the MODE, 
     * IF the except HYP mODE already in 
     * / 
    MRS r0, cpsr     // read values cpsr register r0 to register (cps: bit0 ~ bit4 saving mode of the processor) 
    and R1, r0, # 0x1F         @ mODE mask bits     // value of r0 0x1f phase and stores the result in register r1 
    TEQ r1, # 0x1A         @ Test for HYP MODE    // determine the current processor mode is a mode HYP 
    bicne r0, r0, # 0x1f         @ the Clear All the MODE bits     // If the CPU is not in the mode HYP, clear bit4 ~ bit0 
    orrne r0, r0, # 0x13         @ the SET SVC the MODE     // SVC mode is set to 
    ORR r0, r0, # 0xc0         @ disable IRQ and FIQ     // ban FIQ and IRQ 
    msr cpsr, r0         // will return the current value of the register r0 writes cpsr register 

/ * 
 * Setup the Vector: 
 * (SPL OMAP4 TEXT_BASE not 32 byte aligned IS. 
 * the Continue to use the Vector only in ROM code OMAP4 SPL) 
 * / 
#if ! (defined (CONFIG_OMAP44XX) && defined (CONFIG_SPL_BUILD))
    / * The Set V = 0 in SCTLR of CP15 Register - for Vbar to Point to Vector * / 
    MRC P15, 0 , r0 of, C1, cO, 0     @ SCTLR the Read the Register of CP15     // read register SCTLR 
    bic r0, #CR_V @ V = 0     // set = 0 V 
    mcr P15, 0 , r0 of, C1, cO, 0     @ SCTLR the Write the register of CP15 

    / * the set vector address in CP15 VBAR register * / 
    LDR r0 of, = _start     // set the vector address register CP15 VBAR 
    mcr P15, 0 , r0, c12, C0, 0     @set Vbar
 #endif 

    / *Should have have a ROM code mask The the PLL and the stable Others * / 
#ifndef CONFIG_SKIP_LOWLEVEL_INIT 
    BL cpu_init_cp15     // jump to cpu_init_cp15 
    BL cpu_init_crit     // jump to cpu_init_crit 
#endif 

    BL _main     // jump to _main

In the above code is the main arm processor operating mode is set, a number of register assignment for achieving cpu_init_crit function is as follows:

#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 //跳到lowlevel_init,设置pll、mux和memory
ENDPROC (cpu_init_crit)
 #endif

In cpu_init_crit function, jumped lowlevel_init function running, the next, detailed analysis lowlevel_init and _main function.

 

3, lowlevel_init function

 

 

4, _main function

 

 

Guess you like

Origin www.cnblogs.com/Cqlismy/p/12000889.html