Program from start. s start start
Start_code:
/*
* Set the CPU to SVC32 mode settings management mode
*/
Mrs R0, CPSR
Bic R0, R0, #0x1f
Orr R0, R0, #0xd3
MSR CPSR, R0
#ifdef config_s3c24x0
/* Turn off the watchdog */
/* off watchdog off interrupt */
# if defined (config_s3c2400)
# define Pwtcon 0x15300000
# define INTMSK 0x14400008/* Interupt-controller Base addresses * *
# define CLKDIVN 0x14800014 */clock divisor register */
#else
# define Pwtcon 0x53000000
# define INTMSK 0x4a000008/* Interupt-controller Base addresses * *
# define INTSUBMSK 0x4a00001c
# define CLKDIVN 0x4c000014 */clock divisor register */
# endif
Ldr R0, =pwtcon
mov r1, #0x0
STR R1, [R0]
/*
* Mask all IRQs by setting all bits in the Intmr-default
*/
mov r1, #0xffffffff
Ldr R0, =intmsk
STR R1, [R0]
# if defined (config_s3c2410)//shut up all interrupt
LDR R1, =0X3FF
Ldr R0, =intsubmsk
STR R1, [R0]
# endif
/* FCLK:HCLK:PCLK = 1:2:4 */
/* Default FCLK is to + MHz! */
Ldr R0, =CLKDIVN
mov r1, #3
STR R1, [R0]
#endif/* config_s3c24x0 */
#ifndef Config_skip_lowlevel_init
BL Cpu_init_crit #跳转到cpu_init_crit处 Initialize the CPU Cashe MMU off
#endif
#ifndef config_skip_relocate_uboot
relocate: /* relocate u-boot to RAM * * #加载uboot到RAM对于nor Flash startup boot//can run directly but is inefficient so load into RAM to run
adr r0, _start /* R0 <-Current position of code */ #加载运行起始地址到r0 If starting from nor flash here is 0x0
ldr R1, _text_base /* Test if we run from flash or RAM */#加载_TEXT_BASE到r1 _text_base in SDRAM default to 0X33F80
cmp r0, r1 /* don ' t reloc during debug */ #比较r0 and R1 to determine whether the program starts from Flash or starts from Ram
beq stack_setup /* if R0 = = R1 jumps to stack_up*/ #如果相等 means boot from RAM then the following code moves to the RAM step. Jump directly to Stack_setup run
ldr r2, _armboot_start #代码搬运
LDR&NBSP;R3, _bss_start /*u-boot.lds defines the end address of the Uboot code */
&NBSP;SUB&NBSP;R2, R3, r2 /* R2 <-size of armboot */ #得到代码长度
add r2, r0, r2 /* R2 <-source End address & nbsp; */ #r2中存放uboot结束代码地址
Copy_loop:/* Move data from Norflash to SDRAM R0 to _start program start address R1 to _text_base belongs to the address in SDRAM 0x33f80000 so our uboot 512kb*/
Ldmia r0!, {r3-r10}/* Copy from source address [r0] */#从起始地址开始搬_start
Stmia r1!, {r3-r10}/* Copy to target address [R1]/#搬到目的地址 starting from _text_base
CMP r0, r2/* until source end ADDREEE [R2]/#判断是否搬完 that is, the value in r0 is = = above R2 middle value
Ble copy_loop
#endif/* Config_skip_relocate_uboot */
/* Set up the stack */
Stack_setup: #搬完了后设置栈 said before the judging program start address if you start from RAM directly to set up the stack, there is a stack to use the C language ...
LDR R0, _text_base/* Upper kib:relocated Uboot * * #栈为向下生长 set aside some space before determining the stack pointer sp
Sub R0, R0, #CONFIG_SYS_MALLOC_LEN/* malloc area */#1 length of the malloc segment
Sub R0, R0, #CONFIG_SYS_GBL_DATA_SIZE/* bdinfo * * #2 a length of time to place GBL segments
#ifdef CONFIG_USE_IRQ
Sub R0, R0, # (Config_stacksize_irq+config_stacksize_fiq) #3 also leave a length of time to place the IRQ FIQ Interrupt State Save segment
#endif
Sub sp, R0, #12/* Leave 3 words for abort-stack */
Bic sp, SP, #7/* 8-byte alignment for ABI compliance */#接下来就是sp指针的位置了
CLEAR_BSS: #做完了后在开始跳到uboot第二 Phase C code cleared BSS This puts a number of global # variables initialized to 0 or uninitialized local variables can be cleared before being assigned when they are called.
LDR R0, _bss_start/* Find start of BSS segment */
LDR R1, _bss_end/* stop here */
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 #将指针指向_start_armboot Here's the entrance to the second-stage C function.
_start_armboot:. Word start_armboot
void Start_armboot (void)
{
init_fnc_t **init_fnc_ptr;
Char *s;
#if defined (config_vfd) | | Defined (CONFIG_LCD)
unsigned long addr;
#endif
/* Pointer is writable since we allocated a register for it */
GD = (gd_t*) (_armboot_start-config_sys_malloc_len-sizeof (gd_t));
/* Compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__ (""::: "Memory");
memset ((void*) GD, 0, sizeof (gd_t));
GD->BD = (bd_t*) ((char*) gd-sizeof (bd_t));
memset (gd->bd, 0, sizeof (bd_t));
Gd->flags |= Gd_flg_reloc;
Monitor_flash_len = _bss_start-_armboot_start;
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {//Here for the invocation of a series of initialization functions specifically see Uboot Source code, is the first The serial port of each peripheral module is started. GPIO USB
if ((*INIT_FNC_PTR) ()! = 0) {
Hang ();
}
}
/* Armboot_start is defined in the BOARD-SPECIFIC linker script */
Mem_malloc_init (_armboot_start-config_sys_malloc_len,
Config_sys_malloc_len);
#ifndef Config_sys_no_flash
/* Configure available FLASH banks */
Display_flash_config (Flash_init ());
#endif/* Config_sys_no_flash */
#ifdef CONFIG_VFD
# ifndef Page_size
# define Page_size 4096
# endif
/*
* Reserve Memory for VFD display (always full pages)
*/
/* Bss_end is defined in the BOARD-SPECIFIC linker script */
Addr = (_bss_end + (page_size-1)) & ~ (page_size-1);
Vfd_setmem (addr);
Gd->fb_base = addr;
#endif/* CONFIG_VFD */
#ifdef CONFIG_LCD
/* Board Init may have inited fb_base */
if (!gd->fb_base) {
# ifndef Page_size
# define Page_size 4096
# endif
/*
* Reserve Memory for LCD display (always full pages)
*/
/* Bss_end is defined in the BOARD-SPECIFIC linker script */
Addr = (_bss_end + (page_size-1)) & ~ (page_size-1);
Lcd_setmem (addr);
Gd->fb_base = addr;
}
#endif/* CONFIG_LCD */
#if defined (Config_cmd_nand)
Puts ("NAND:");
Nand_init (); /* Go init the NAND */
#endif
#if defined (Config_cmd_onenand)
Onenand_init ();
#endif
#ifdef Config_has_dataflash
At91f_dataflashinit ();
Dataflash_print_info ();
#endif
/* Initialize Environment */
Env_relocate ();
#ifdef CONFIG_VFD
/* Must do this after the framebuffer is allocated */
Drv_vfd_init ();
#endif/* CONFIG_VFD */
#ifdef Config_serial_multi
Serial_initialize ();
#endif
/* IP Address */
GD->BD->BI_IP_ADDR = getenv_ipaddr ("ipaddr");
Stdio_init (); /* Get the devices list going. */
Jumptable_init ();
#if defined (CONFIG_API)
/* Initialize API */
Api_init ();
#endif
Console_init_r (); /* Fully init console as a device */
#if defined (config_arch_misc_init)
/* Miscellaneous Arch dependent initialisations */
Arch_misc_init ();
#endif
#if defined (config_misc_init_r)
/* Miscellaneous Platform Dependent initialisations */
Misc_init_r ();
#endif
/* Enable exceptions */
Enable_interrupts ();
/* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_TI_EMAC
/* Xxx:this needs to being moved to board INIT */
extern void Davinci_eth_set_mac_addr (const u_int8_t *ADDR);
if (getenv ("ethaddr")) {
Uchar Enetaddr[6];
ETH_GETENV_ENETADDR ("Ethaddr", enetaddr);
DAVINCI_ETH_SET_MAC_ADDR (ENETADDR);
}
#endif
#if defined (config_driver_smc91111) | | Defined (config_driver_lan91c96)
/* Xxx:this needs to being moved to board INIT */
if (getenv ("ethaddr")) {
Uchar Enetaddr[6];
ETH_GETENV_ENETADDR ("Ethaddr", enetaddr);
SMC_SET_MAC_ADDR (ENETADDR);
}
#endif/* config_driver_smc91111 | | CONFIG_DRIVER_LAN91C96 * *
/* Initialize from Environment */
if ((s = getenv ("loadaddr"))! = NULL) {
LOAD_ADDR = Simple_strtoul (S, NULL, 16);
}
#if defined (config_cmd_net)
if ((s = getenv ("Bootfile"))! = NULL) {
Copy_filename (Bootfile, S, sizeof (Bootfile));
}
#endif
#ifdef Board_late_init
Board_late_init ();
#endif
#ifdef CONFIG_GENERIC_MMC
Puts ("MMC:");
Mmc_initialize (GD->BD);
#endif
#ifdef CONFIG_BITBANGMII
Bb_miiphy_init ();
#endif
#if defined (config_cmd_net)
#if defined (CONFIG_NET_MULTI)
Puts ("Net:");
#endif
Eth_initialize (GD->BD);
#if defined (config_reset_phy_r)
Debug ("Reset Ethernet phy\n");
Reset_phy ();
#endif
#endif
/* Main_loop () can return to retry autoboot, if so just run it again. */
for (;;) {
Main_loop (); After initialization of each board level peripheral is completed, enter Main_loop () dead loop
}
/* Notreached-no-out-of-command loop except booting */
}
void Main_loop (void)
s = getenv ("BootDelay");
BootDelay = s? (int) Simple_strtol (s, NULL, ten): Config_bootdelay; If you define a delay load this article deals with an important function getenv () Get environment variables
Run_command (s, 0); Running command functions in a dead loop we enter various commands on the serial port by this function to parse