0K6410 learning Uboot_stage2
Alas, my old classmates called me to get together at the end of the month. I swear that this was my first time so cool, that is, just as before, I agreed without consideration. Because, I think I have a lot of important things to do. For students like me who are not preparing for postgraduate entrance exams, I have to seize the time of my vacation to charge myself. Sorry, old friends, please forgive me for this white lie, and I am not enough time to study at school. Please accept my apology. Okay, now that a pot of water has been burned, start with my uboot
Learn about stage2 !!
When the Assembly part in the first stage is completed and jumps to stage2, the c function start_armboot is executed. This function is the main function of the entire u-boot.
1. First declare a global pointer variable DECLARE_GLOBAL_DATA_PTR. This macro is defined in the header file.
# Define DECLARE_GLOBAL_DATA_PTR register volatilegd_t * gd asm ("r8") in include/asm-arm/global_data.h ")
Declare a register variable gd
Occupies r8. This macro references the Global Data Pointer gd_t * gd in all
Source
There are declarations in the code, this statement also avoids the compiler to r8
Other variables.
Therefore, gd is r8, and no memory is allocated for this pointer variable.
2、 /* Pointer is writable since weallocated 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) Forcibly converts the type, assigns an address to the pointer gd and gd for address allocation. The following is a classic uboot ing diagram. It is really good. It clearly describes the memory allocation during the Uboot startup process.
Monitor_flash_len = _ bss_start-_ armboot_start; as you can see, this is the uboot length.
3. A loop is followed to initialize the information of the Board and related functions.
for (init_fnc_ptr = init_sequence;*init_fnc_ptr; ++init_fnc_ptr) { if((*init_fnc_ptr)() != 0) { hang(); }}
4 ,/*
Initialize heap space */
/* Armboot_start is defined in theboard-specific linker script */mem_malloc_init (_ armboot_start-CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN ); /* configure flash */# ifndef CONFIG_SYS_NO_FLASH/* configure available FLASH banks */display_flash_config (flash_init (); # endif/* CONFIG_SYS_NO_FLASH */
5. The next step is a series of initialization tasks, which are not analyzed one by one. In fact, some functions cannot be analyzed, and the pointer indicates that I am dizzy ..
#ifdef CONFIG_VFD# ifndefPAGE_SIZE# define PAGE_SIZE 4096# endif /* * reserve memory for VFD display (always fullpages) */ /*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) {# ifndefPAGE_SIZE# define PAGE_SIZE 4096# endif /* * reserve memory for LCD display (always fullpages) */ /*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 be moved to board init */extern void davinci_eth_set_mac_addr (constu_int8_t *addr); if(getenv ("ethaddr")) { ucharenetaddr[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 be moved to board init */ if(getenv ("ethaddr")) { ucharenetaddr[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(); } /*NOTREACHED - no way out of command loop except booting */}
6. There is also an initialization function to configure some information.
nit_fnc_t *init_sequence[] = {#if defined(CONFIG_ARCH_CPU_INIT) arch_cpu_init, /* basic arch cpu dependent setup */#endif board_init, /* basic board dependent setup*/#if defined(CONFIG_USE_IRQ) interrupt_init, /* set up exceptions */#endif timer_init, /* initialize timer */#ifdef CONFIG_FSL_ESDHC get_clocks,#endif env_init, /* initialize environment */ init_baudrate, /* initialze baudrate settings */ serial_init, /* serial communications setup*/ console_init_f, /* stage 1 init of console */ display_banner, /* say that we are here */#if defined(CONFIG_DISPLAY_CPUINFO) print_cpuinfo, /* display cpu info (and speed) */#endif#if defined(CONFIG_DISPLAY_BOARDINFO) checkboard, /* display board info */#endif#if defined(CONFIG_HARD_I2C) ||defined(CONFIG_SOFT_I2C) init_func_i2c,#endif dram_init, /* configure available RAMbanks */#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI) arm_pci_init,#endif display_dram_config, NULL,};
Display_banner is the first piece of information printed on the serial port. If you are interested, you can enter this function and modify it. Unexpected results may occur.
The entire u-boot
The main_loop () function enters the endless loop where the user enters the command, parses and executes the command.
About some important data structures in uboot stage2 and some important points worth noting, wait for the next time. The stage2 analysis is now here.
To be continued, port uboot ....