1. At the beginning of the document there is such a comment
/* *************************************************************************
*
* startup code (called by ARM's reset, Do not include interrupts) *
* Only do important initialization when not starting from memory
* Relocation code to RAM
* Set Stack
* Jump to start second stage
*
****************** *******************************************************
*/
This start has been broadly explained above. s file to do things in the U-boot.lds file indicates that the entry is the _start label, so the beginning will load _start content, and this function is inside the VECTOR.S (different from the previous kernel). It will set the interrupt vector table and so on, of course, these have been loaded at the time of compilation, the chip reset will jump to reset to continue executing code # 2. First set up CPU in admin mode
Reset:
/
* * Set the CPU to SVC32 mode
*/
Mrs R0, CPSR
Bic r0, R0, #0x1f
Orr r0, R0, #0xd3
MSR CPSR, R0
# 3. Off watchdog, shielded interrupt
# define Pwtcon 0x53000000
# define INTMSK 0x4a000008/ * Interrupt-controller Base Addresses */
# define Intsubmsk 0x4a00001c
# define CLKDIVN 0x4c000014 * clock divisor Register */
# endif/
* off watchdog */
LDR r0, =pwtcon
mov r1, #0x0
str R1, [r0]/
* Mask all interrupts */
M OV R1, #0xffffffff
ldr r0, =intmsk
str R1, [r0]
# if defined (config_s3c2410)
ldr R1, =0x3ff
LDR R0, =intsubmsk
str R1, [r0]
# endif
# 4. Initialize the clock divider factor
/* FCLK:HCLK:PCLK = 1:2:4 *///
* Default FCLK is
----*/LDR R0, =CLKDIVN
mov r1, #3
str R1, [R0]
# 5.CPU Initialization
/* Erase Dcache with Icache */
mov r0, #0
mcr p15, 0, R0, C7, C7, 0/ * Flush V3/V4 Cache */
MCR P15, 0, R0, C8, C7, 0/ * Flush v4 TLB *
//* Prohibit MMU and cache */
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 (I) I-cache
MCR p15, 0, R0, C1, C0, 0/
* before repositioning, via Lowlevel_init letter Number set RAM Time parameter */
mov IP, lr
bl lowlevel_init
mov lr, IP
mov pc, LR
# 6. Call \_main here began a little doubt, how no memory settings and relocation code directly started \_main, sourceinsight Global search **_main** found in crt0. S has **_main** function body * * We first look at the introduction of the _main function * *
/* 1. To set the initialization environment for calling Board_init_f () C functions The environment only provides the stack and the storage space of the GD (' Global data ') data structure, only the static variables that have been initialized can be used at that stage
*< c4/>* 2. Call Board_init_f (). To prepare the hardware environment for the system to boot from RAM, Board_init_f () must use GD to store the data needed for the final stage. The data includes the target address of the relocation, the stack to be used in the future, and the new address of GD to be used in the future
*
3. Set the staging environment for Stack and GD *
4. Call Relocate_code (). function Relocation U-bo OT to Board_init_f () specified position
*
* 5. Set up the latest environment for calling Board_init_r (). Initialize BSS, non-static global variables and stack in system RAM
* GD retains the value set by Board_init_f (). Some CPUs also have some memory-related operations that are not performed, so call C_runtime_cpu_setup
*
6. Jump to Board_init_r ().
*/
7. Set the C run environment and call Board_init_f (0)
Ldr sp, = (CONFIG_SYS_INIT_SP_ADDR)/ * config_sys_init_sp_addr = 0x30000000 + 0x1000-generated_gbl_data_size = 0x300 00F50 */
bic sp, SP, #7/ * 8-byte alignment */
mov r2, SP
Sub sp, SP, #GD_SIZE/ * Allocate GD space above the stack, gd_size = 168 */
bic sp, SP, #7/ * 8-byte alignment */
mov r9, SP/ * GD is above SP */
mov r1, SP
mov r0, #0/
* Empty GD space to stay Re-assignment *
/CLR_GD:
cmp R1, R2
Strlo r0, [R1]/ * Clear 32-bit GD word */
addlo R1, R1, #4 c20/>/* move to Next */
blo clr_gd
bl board_init_f/ * Call Board_init_f to initialize GD and so on, SP = 30000E80 */
It is worth saying that the above Generated_gbl_data_size macro definition, it is by define (Generated_gbl_data_size, (sizeof (struct global_data) +) & ~15); obtained, which is equivalent to the # define generated_gbl_data_size (sizeof (struct global_data) + & ~15).
#define Define (Sym, Val) \
asm volatile ("\n.ascii \", "#sym"%0 "#val" \ "":: "I" (val))
This statement is converted to an. h file at compile time for inclusion in other files, and this macro definition should probably be shaped like # define generated_gbl_data_size (sizeof (struct global_data) +) & ~15) can be used with the definition (there are questions here, why not directly macro definition), add: This macro can make the global variable gd_t can be in the. s files are directly accessed using assembly code, similar to Ldr sp, [R9, #GD_START_ADDR_SP]/* SP = GD->START_ADDR_SP */Such statement
In addition, because of MOV r9, SP this sentence function, later to want to u-boot other files inside the SP (that is, the location of GD), you need to add declare_global_data_ptr to the head of the file, the prototype is
#define DECLARE_GLOBAL_DATA_PTR Register volatile gd_t *gd asm ("R9")
//In version 2015 using the following function, the principle is the same
static inline gd_t *get_gd (void)
{
gd_t *gd_ptr;
__asm__ volatile ("mov%0, r9\n": "=r" (gd_ptr));
return gd_ptr;
}
8. Single Board initialization board_init_f
(It should be noted that the Board_init_f selected for the board.c inside, but from 2014 after the default compilation is Board_f inside the function, here for learning convenience, Choose BOARD.C inside the function for analysis, and then to analyze another branch code, switch the code into the BOARD.C inside the method in the future of the real transplant will be said to initialize the global variable GD, call function queue
memset (void *) GD, 0, sizeof (gd_t)); /* Initialize GD fill to 0 */
Gd->mon_len = (ULONG) &__bss_end-(ULONG) _start; /* Overall U-boot code and the total size of the data segment can be obtained by the U-boot.lds file *
/* Call an initialization function queue *
/for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++INIT_FNC_PTR) {
if ((*INIT_FNC_PTR) ()! = 0) {hang
();}
}
here is the function of the Init_sequence function on the column
Board_early_init_f/ * clock initialization, pin initialization, different boards to be set differently */
timer_init/ * Timer initialization */
Env_init,/ * Initialize environment */
init_baudrate,/ * baud rate initialization, default config_baudrate = 115200 */
gd->baudrate = getenv_ ULONG ("BaudRate", ten, config_baudrate);
Serial_init,/ * Serial initialization */
Console_init_f,/ * Console initialization */
Display_banner,/ * Indicates the code is running here */
Print_cpuinfo,/ * Print CPU information */
Dram_init,/ * Configure available RAM size, default phys_sdram_1_size is 64M */
The initialization program eventually holds the address addr
Addr = Config_sys_sdram_base + get_effective_memsize (); /* Addr point to the end of the SDRAM, 0x34000000, get_effective_memsize () = 64M */* reserved TLB table,pgtable_size default to 4K */gd->arch.tlb_size
= Pgtable_size; Addr-= gd->arch.tlb_size;
/* Addr minus tlb Size */* Move down to the next 64K start, equivalent to 64KB alignment */addr &= ~ (0x10000-1); gd->arch.tlb_addr = addr;
/* The TLB points to the current addr */* 4KB alignment */addr &= ~ (4096-1);
Debug ("Top of RAM usable for u-boot at:%08lx\n", addr);
/* For U-boot Code, data and BSS reserved space,gd->mon_len; at the beginning of the function is assigned, size is u-boot the entire compiled file size * 4KB Alignment */addr-= gd->mon_len;
Addr &= ~ (4096-1); /* Save heap area for malloc () function */addr_sp = Addr-total_malloc_len;
/* addr stack equals addr minus heap Size */* * Keep Board Info struct space with a copy of gd_t */addr_sp = sizeof (bd_t);
BD = (bd_t *) addr_sp;
GD->BD = BD; /* Set stack pointer */ADDR_SP-= sizeof (gd_t); /* stack minus gd_t copy space */id = (gd_t *) addr_sp;
/* ID is assigned the value of the current ADDR_SP */gd->irq_sp = ADDR_SP;
/* Leave 3 bytes for interrupt stack */addr_sp-= 12;
/* 8-byte alignment */addr_sp &= ~0x07; Gd->relocaddr = addr; /* The destination address for the relocation is the start address of the code area */gd->start_addr_sp = ADDR_SP; /* Stack address is above addr_sp */Gd->reloc_off = addr-(ULONG) &_start; /* The offset of the relocation is the code area store address minus 0 address */memcpy (ID, (void *) GD, sizeof (gd_t)); /* Copy gd_t to the address of the reserved gd_t copy after relocation */
Preparation before relocating the code
Ldr sp, [R9, #GD_START_ADDR_SP]/* SP = GD->START_ADDR_SP,SP start address for redirection code stack */
bic sp, SP, #7/ * 8-byte alignment */
LDR R9, [R9, #GD_BD]/ * R9 = GD->BD */
Sub R9, R9, #GD_SIZE/ * New GD under BD, see memory Map */
ADR LR, here
LDR R0 , [R9, #GD_RELOC_OFF]/ * r0 = gd->reloc_off,r0 REDIRECT Offset */
add LR, LR, r0/ * Relocation Code return address */
LDR r0, [ R9, #GD_RELOCADDR]/ * R0 = gd->relocaddr,r0 target Address for redirection */
b relocate_code
Start Relocation Code
LDR R1, =__image_copy_start/* R1 <-SRC &__image_copy_start */Subs R4, R0, r1/* R4 <-Relocation Offs
ET/beq relocate_done/* Skip Relocation */LDR R2, =__image_copy_end/* R2 <-SRC &__image_copy_end */ /* Until now, the values of the more important registers are * R0 = Gd->reloc_off,r0 for the relocation offset, this is the destination address * r1 = __IMAGE_COPY_START,R1 is the current start address of the code that needs to be relocated, that is, the code snippet is open Start 0 * R4 = R0-R1,R4 offset value for relocation, offset value minus 0 or 0 * R2 =__IMAGE_COPY_END,R2 is the end address where the code needs to be relocated, R2-R1 is the need to reposition the code length */copy_loop:ld
Mia r1!, {r10-r11}/* Start copy from source address [R1], pop to R10 and R11, 8 bytes at a time */Stmia r0!, {r10-r11}/* Copy to Destination address [r0] */ CMP R1, r2/* until [R1] equals [R2], the end of the code copy/* Blo copy_loop/* * reposition fix. Rel.dyn */L Dr R2, =__rel_dyn_start/* R2 <-src &__rel_dyn_start */LDR R3, =__rel_dyn_end/* R3 <-SRC &__rel_ Dyn_end */Fixloop:ldmia r2!, {R0-R1}/* (R0,R1) <-(SRC location,fixup) */and R1, R1, #0xff CMP R1, #23/* Relative fixup? */bne fixnext/* Relative fix:increase location by offset */add r0, R0, R4 LDR R1, [r0] add R1, r1 , R4 str R1, [r0] fixnext:cmp R2, R3 blo Fixloop
9. Jump Run second stage code
Here we have completed the relocation of the entire uboot and the initialization of some basic devices, and then call Board_init_r, which is the second phase of the Uboot launch, including the initialization of NAND flash, nor flash and so on device initialization, as well as the initialization of various commands.
The final memory is planned as follows (although different versions of Uboot memory distributions vary, but are generally the same):