1 Set Interrupt vector table
After the CPU is power up, first executes the program from the 0x0000 0000 address, after Uboot compiles, at the beginning address of the program holds the interrupt vector table, the part code is written in assembly language, the code is stored in the ARCH\ARM\CPU\ARMV7 directory of start. s, as shown below:
/*************************************************************************
*
* Startup Code (reset vector)
*
* Do important init only if we don ' t Startfrom memory!
* Setup memory and board specific BITS Priorto relocation.
* Relocate Armboot to RAM. Setup stack.
*
*************************************************************************/
. GLOBL Reset
. Globl Save_boot_params_ret
#ifdefCONFIG_ARMV7_LPAE
. Global Switch_to_hypervisor_ret
#endif
Reset
/* Allow the board to save Importantregisters */
b save_boot_params
Save_boot_params_ret:
#ifdefCONFIG_ARMV7_LPAE
/*
* Check for Hypervisor support
*/
MRC p15,0, R0, C0, C1, 1 @ READID_PFR1
and r0,r0, #CPUID_ARM_VIRT_MASK @ maskvirtualization bits
CMP r0,# (1 << cpuid_arm_virt_shift)
BEQ Switch_to_hypervisor
Switch_to_hypervisor_ret:
#endif
In line 32nd, the program starts by declaring three global three tag Reset,ave_boot_params_ret,switch_to_hypervisor_ret, then starts executing the code at the reset label, b save_boot_params, Jump to Save_boot_params, as shown here:
/*************************************************************************
*
* void Save_boot_params (u32 r0, u32 R1, U32R2, U32 R3)
* __ATTRIBUTE__ ((weak));
*
* Stack pointer is not yet initialized at Thismoment
* Don ' t save anything to stack even ifcompiled with-o0
*
*************************************************************************/
ENTRY (Save_boot_params)
b Save_boot_params_ret @ back to my caller
Endproc (Save_boot_params)
. Weak Save_boot_params
#ifdefCONFIG_ARMV7_LPAE
ENTRY (Switch_to_hypervisor)
b Switch_to_hypervisor_ret
Endproc (Switch_to_hypervisor)
. Weak Switch_to_hypervisor
#endif
Line 115th, called the Save_boot_params_ret function in Save_boot_params, is declared here as a weak function, and the external function with the same name is called when there is a function with the same name. Then decide whether to support the hypervisor function, and if so, call the Switch_to_hypervisor function, and the function is declared here as a weak function.
Line 56th, turn off Fiq and IRQ interrupts as shown below, unless in HYP mode, set the CPU to SVC32 mode,
/*
*disable interrupts (FIQ and IRQ), also set the CPU to SVC32 mode,
* Exceptif 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 Modebits
Orrne r0,r0, #0x13 @ set SVC mode
Orr r0,r0, #0xc0 @ disable Fiqand IRQ
MSR Cpsr,r0
Line 69th, set the interrupt vector table as shown below, if you define the SPL to compile, the interrupt vector table address is written to the coprocessor CP15 Register,
/*
* Setup Vector:
* (OMAP4 SPL text_base is not a byte aligned.
* Continue to use ROM code vector only inOMAP4 SPL)
*/
#if! (Defined (CONFIG_OMAP44XX) && defined (config_spl_build))
/* Set v=0 in CP15 sctlr register-for vbar topoint to vector */
MRC p15,0, R0, C1, C0, 0 @ Read CP15 sctlrregister
BIC r0, #CR_V @ V = 0
MCR p15,0, R0, C1, C0, 0 @ Write CP15 sctlrregister
/* Set vector address in CP15 vbar Register */
LDR R0,=_start
MCR p15,0, R0, C12, C0, 0 @Set Vbar
#endif
Line 81st, as shown below, to determine whether to skip lowlevel_init initialization and lowlevel_init_only, do not skip the call CPU_INIT_CP15 and Cpu_init_crit, respectively, after the completion of the two functions, then jump to _ The main function.
/* The Mask ROM code should has a PLL and othersstable */
#ifndefCONFIG_SKIP_LOWLEVEL_INIT
BL CPU_INIT_CP15
#ifndefCONFIG_SKIP_LOWLEVEL_INIT_ONLY
BL Cpu_init_crit
#endif
#endif
BL _main
In the CPU_INIT_CP15 function, close L1 I/d,mmu and caches are completed, and I-cache is turned on unless Config_sys_icache_off is defined.
In the Cpu_init_crit function, line No. 317 jumps to the Lowlevel_init function, which is defined in different initialization functions of different board.
#if!defined (config_skip_lowlevel_init) && \
!defined (config_skip_lowlevel_init_only)
/*************************************************************************
*
* Cpu_init_critical Registers
*
* Setup Important Registers
* Setup Memory Timing
*
*************************************************************************/
ENTRY (Cpu_init_crit)
/*
* JUMPTO Board Specific initialization ...
* Themask ROM would have already initialized
* Basicmemory. Go bump up clock rate and handle
* Wakeup conditions.
*/
b lowlevel_init @ Go setup pll,mux,memory
Endproc (Cpu_init_crit)
#endif
The Lowlevel_init function is implemented in Lowlevel under the board\samsung\smdkc100 directory. s, line 19th, this function, the main implementation of the following functions:
A, close the watchdog;
b, set SRAM;
C, set up three sets of interrupt source;
D. Close all interrupts;
E, set all interrupts as IRQ;
F, clear the interrupt suspend bit;
G, call uart_asm_init function;
h, call tzpc_asm_init function;
I, initialize the clock of the kernel and bus.
Line 124th, in the Uart_asm_init function, initializes the pin of the UART, line 136th, in the Tzpc_asm_init function, initializes the TZPC.
The _main function is implemented in CRT0 under the Arch\arm\lib directory. s, in line 67th, specifies that the entry (_main) entry function is named, which primarily implements the initialization of the C language's operating environment and calls the Board_init_f (0) function.
The following is a detailed description of the implementation of the function:
#ifdefined (config_spl_build) && defined (config_spl_stack)
Ldr r0,= (Config_spl_stack)
#else
Ldr r0,= (CONFIG_SYS_INIT_SP_ADDR)
#endif
Bic R0,r0, #7/* 8-byte alignment for Abicompliance */
MOV sp,r0
BL Board_init_f_alloc_reserve
MOV sp,r0
/* Set up GD here, outside any C code */
MOV r9,r0
BL Board_init_f_init_reserve
mov r0, #0
BL Board_init_f
First, determine if the Config_spl_build and config_spl_stack two macro definitions are defined, and if so, complete the following actions:
Load Config_spl_stack macro data to R0 register, otherwise use CONFIG_SYS_INIT_SP_ADDR this macro definition, then through the Mov SP, R0 set up the stack, and then call BOARD_INIT_F_ALLOC_ The reserve function immediately calls the Board_init_f_init_reserve function, then the R0 register is assigned a value of 0, and the Board_init_f function is called, passing in a parameter of R0, that is, passing in 0 as a parameter.
If no config_spl_build is defined, do the following:
#if!defined (Config_spl_build)
/*
* Set up Intermediate environment (new SP ANDGD) and call
* Relocate_code (Addr_moni). Trick here is Thatwe ' ll return
* "Here" but relocated.
*/
Ldr R0,[r9, #GD_START_ADDR_SP]/* SP =GD->START_ADDR_SP */
Bic R0,r0, #7/* 8-byte alignment for Abicompliance */
MOV sp,r0
Ldr R9,[r9, #GD_BD]/* R9 =GD->BD */
Sub R9,r9, #GD_SIZE/* NEW GD isbelow BD */
ADR Lr,here
Ldr R0,[r9, #GD_RELOC_OFF]/* r0 =gd->reloc_off */
Add Lr,lr, R0
#ifdefined (config_cpu_v7m)
Orr LR, #1/* asrequired by Thumb-only */
#endif
Ldr R0,[r9, #GD_RELOCADDR]/* r0= GD->RELOCADDR */
b Relocate_code
Here
/*
* Now relocate vectors
*/
BL relocate_vectors
/* Set up final (FULL) environment */
BL C_runtime_cpu_setup/* We still call old routine here * *
#endif
Load the GD_START_ADDR_SP macro definition to the stack address, SP =GD->START_ADDR_SP, where several externally defined macros GD_BD, gd_size, Gd_reloc_off, gd_relocaddr are used, The Relocate_code function is then called, followed by a call to Relocate_vectors to redirect the Interrupt vector table, and finally calls the C_runtime_cpu_setup to complete the build of the C language operating environment without using SPL.
#if!defined (config_spl_build) | | Defined (config_spl_framework)
# Ifdefconfig_spl_build
/* Use a DRAM stack for the rest of SPL, ifrequested */
BL SPL_RELOCATE_STACK_GD
CMP R0, #0
Movne sp,r0
Movne r9,r0
# endif
LDR R0,=__bss_start/* This is auto-relocated!*/
#ifdefCONFIG_USE_ARCH_MEMSET
LDR r3,=__bss_end/* This isauto-relocated! */
mov r1, #0x00000000/* Prepare zero toclear BSS */
Subs R2,R3, r0/* r2 = memset Len */
BL memset
#else
LDR r1,=__bss_end/* This isauto-relocated! */
mov r2, #0x00000000/* Prepare zero toclear BSS */
clbss_l:cmp R0, R1/*while not at end of BSS */
#ifdefined (config_cpu_v7m)
ITT Lo
#endif
Strlo R2,[r0]/* Clear 32-bit Bssword */
Addlo r0,r0, #4/* Move to Next */
Blo clbss_l
#endif
#if! Defined (config_spl_build)
Blcoloured_led_init
blred_led_on
#endif
Line 122th, as shown above, if you do not define CONFIG_SPL_BUILD this macro, or define Config_spl_framework, do the above, specifically, if config_spl_build is defined, it will be called Spl_ The RELOCATE_STACK_GD function, if necessary, can use the DRAM stack. The BSS segment is then initialized to 0. Then, if you do not define the macro Config_spl_build, call the Coloured_led_init and red_led_on two functions.
Line 155th, as shown below, finally calls the Board_init_r function, which gd_relocaddr the macro definition as the second parameter of a function.
/* Call Board_init_r (gd_t *id, ulongdest_addr) */
mov r0, r9/* gd_t */
Ldr R1,[r9, #GD_RELOCADDR]/* DEST_ADDR */
/* Call Board_init_r */
#ifCONFIG_IS_ENABLED (Sys_thumb_build)
LDR Lr,=board_init_r/* This is auto-relocated!*/
BX LR
#else
LDR Pc,=board_init_r/* This is auto-relocated!*/
#endif
/* We should not return here. */
#endif
Endproc (_main)
At this point, the assembly portion of the Uboot startup process ends, and the next step is to parse the C-language part of the code.