uboot入口
arch/arm/lib/crt0.S
#include <config.h> #include <asm-offsets.h> #include <linux/linkage.h> /* * This file handles the target-independent stages of the U-Boot * start-up where a C runtime environment is needed. Its entry point * is _main and is branched into from the target's start.S file. * * _main execution sequence is: * * 1. Set up initial environment for calling board_init_f(). * This environment only provides a stack and a place to store * the GD ('global data') structure, both located in some readily * available RAM (SRAM, locked cache...). In this context, VARIABLE * global data, initialized or not (BSS), are UNAVAILABLE; only * CONSTANT initialized data are available. * * 2. Call board_init_f(). This function prepares the hardware for * execution from system RAM (DRAM, DDR...) As system RAM may not * be available yet, , board_init_f() must use the current GD to * store any data which must be passed on to later stages. These * data include the relocation destination, the future stack, and * the future GD location. * * (the following applies only to non-SPL builds) * * 3. Set up intermediate environment where the stack and GD are the * ones allocated by board_init_f() in system RAM, but BSS and * initialized non-const data are still not available. * * 4. Call relocate_code(). This function relocates U-Boot from its * current location into the relocation destination computed by * board_init_f(). * * 5. Set up final environment for calling board_init_r(). This * environment has BSS (initialized to 0), initialized non-const * data (initialized to their intended value), and stack in system * RAM. GD has retained values set by board_init_f(). Some CPUs * have some work left to do at this point regarding memory, so * call c_runtime_cpu_setup. * * 6. Branch to board_init_r(). */ /* * entry point of crt0 sequence */ ENTRY(_main) /* * Set up initial C runtime environment and call board_init_f(0). */ #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr sp, =(CONFIG_SPL_STACK) #else ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #endif bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ mov r2, sp sub sp, sp, #GD_SIZE /* allocate one GD above SP */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ mov r9, sp /* GD is above SP */ mov r1, sp mov r0, #0 clr_gd: cmp r1, r2 /* while not at end of GD */ strlo r0, [r1] /* clear 32-bit GD word */ addlo r1, r1, #4 /* move to next */ blo clr_gd #if defined(CONFIG_SYS_MALLOC_F_LEN) sub sp, sp, #CONFIG_SYS_MALLOC_F_LEN str sp, [r9, #GD_MALLOC_BASE] #endif /* mov r0, #0 not needed due to above code */ bl board_init_f #if ! defined(CONFIG_SPL_BUILD) /* * Set up intermediate environment (new sp and gd) and call * relocate_code(addr_moni). Trick here is that we'll return * 'here' but relocated. */ ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ sub r9, r9, #GD_SIZE /* new GD is below bd */ adr lr, here ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ add lr, lr, r0 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 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK) # ifdef CONFIG_SPL_BUILD /* Use a DRAM stack for the rest of SPL, if requested */ bl spl_relocate_stack_gd cmp r0, #0 movne sp, r0 # endif ldr r0, =__bss_start /* this is auto-relocated! */ #ifdef CONFIG_USE_ARCH_MEMSET ldr r3, =__bss_end /* this is auto-relocated! */ mov r1, #0x00000000 /* prepare zero to clear BSS */ subs r2, r3, r0 /* r2 = memset len */ bl memset #else ldr r1, =__bss_end /* this is auto-relocated! */ mov r2, #0x00000000 /* prepare zero to clear BSS */ clbss_l:cmp r0, r1 /* while not at end of BSS */ strlo r2, [r0] /* clear 32-bit BSS word */ addlo r0, r0, #4 /* move to next */ blo clbss_l #endif #if ! defined(CONFIG_SPL_BUILD) bl coloured_LED_init bl red_led_on #endif /* call board_init_r(gd_t *id, ulong dest_addr) */ mov r0, r9 /* gd_t */ ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */ /* call board_init_r */ ldr pc, =<span style="color:#FF0000;">board_init_r</span> /* this is auto-relocated! */ /* we should not return here. */ #endif
board/freescale/mx6sabresd下的mx6sabresd.c
void board_init_f(ulong dummy) { /* setup AIPS and disable watchdog */ arch_cpu_init(); ccgr_init(); gpr_init(); /* iomux and setup of i2c */ board_early_init_f(); /* setup GP timer */ timer_init(); /* UART clocks enabled and gd valid - init serial console */ preloader_console_init(); /* DDR initialization */ spl_dram_init(); /* Clear the BSS. */ memset(__bss_start, 0, __bss_end - __bss_start); /* load/boot image from boot device */ <span style="color:#FF0000;">board_init_r(NULL, 0);</span> }
函数board_init_r(NULL, 0)最终调用了common/board_r.c
void board_init_r(gd_t *new_gd, ulong dest_addr) { #ifdef CONFIG_NEEDS_MANUAL_RELOC int i; #endif #ifdef CONFIG_AVR32 mmu_init_r(dest_addr); #endif #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) gd = new_gd; #endif #ifdef CONFIG_NEEDS_MANUAL_RELOC for (i = 0; i < ARRAY_SIZE(init_sequence_r); i++) init_sequence_r[i] += gd->reloc_off; #endif if (initcall_run_list(<span style="color:#FF0000;">init_sequence_r</span>)) hang(); /* NOTREACHED - run_main_loop() does not return */ hang(); }
这里看看数组init_sequence_r的内容。
init_fnc_t init_sequence_r[] = { initr_trace, initr_reloc, /* TODO: could x86/PPC have this also perhaps? */ #ifdef CONFIG_ARM initr_caches, #endif initr_reloc_global_data, #if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500) initr_unlock_ram_in_cache, #endif initr_barrier, initr_malloc, #ifdef CONFIG_SYS_NONCACHED_MEMORY initr_noncached, #endif bootstage_relocate, #ifdef CONFIG_DM initr_dm, #endif #ifdef CONFIG_ARM board_init, /* Setup chipselects */ #endif /* * TODO: printing of the clock inforamtion of the board is now * implemented as part of bdinfo command. Currently only support for * davinci SOC's is added. Remove this check once all the board * implement this. */ #ifdef CONFIG_CLOCKS set_cpu_clk_info, /* Setup clock information */ #endif stdio_init_tables, initr_serial, initr_announce, INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_NEEDS_MANUAL_RELOC initr_manual_reloc_cmdtable, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K) initr_trap, #endif #ifdef CONFIG_ADDR_MAP initr_addr_map, #endif #if defined(CONFIG_BOARD_EARLY_INIT_R) board_early_init_r, #endif INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_LOGBUFFER initr_logbuffer, #endif #ifdef CONFIG_POST initr_post_backlog, #endif INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_SYS_DELAYED_ICACHE initr_icache_enable, #endif #if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT) /* * Do early PCI configuration _before_ the flash gets initialised, * because PCU ressources are crucial for flash access on some boards. */ initr_pci, #endif #ifdef CONFIG_WINBOND_83C553 initr_w83c553f, #endif #ifdef CONFIG_ARCH_EARLY_INIT_R arch_early_init_r, #endif power_init_board, #ifndef CONFIG_SYS_NO_FLASH initr_flash, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_PPC) || defined(CONFIG_M68K) /* initialize higher level parts of CPU like time base and timers */ cpu_init_r, #endif #ifdef CONFIG_PPC initr_spi, #endif #if defined(CONFIG_X86) && defined(CONFIG_SPI) init_func_spi, #endif #ifdef CONFIG_CMD_NAND initr_nand, #endif #ifdef CONFIG_CMD_ONENAND initr_onenand, #endif #ifdef CONFIG_GENERIC_MMC initr_mmc, #endif #ifdef CONFIG_HAS_DATAFLASH initr_dataflash, #endif initr_env, #ifdef CONFIG_SYS_BOOTPARAMS_LEN initr_malloc_bootparams, #endif INIT_FUNC_WATCHDOG_RESET initr_secondary_cpu, #ifdef CONFIG_SC3 initr_sc3_read_eeprom, #endif #if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET) mac_read_from_eeprom, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_PCI) && !defined(CONFIG_SYS_EARLY_PCI_INIT) /* * Do pci configuration */ initr_pci, #endif <span style="color:#FF0000;">stdio_add_devices,</span> initr_jumptable, #ifdef CONFIG_API initr_api, #endif console_init_r, /* fully init console as a device */ #ifdef CONFIG_DISPLAY_BOARDINFO_LATE show_board_info, #endif #ifdef CONFIG_ARCH_MISC_INIT arch_misc_init, /* miscellaneous arch-dependent init */ #endif #ifdef CONFIG_MISC_INIT_R misc_init_r, /* miscellaneous platform-dependent init */ #endif INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_CMD_KGDB initr_kgdb, #endif interrupt_init, #if defined(CONFIG_ARM) || defined(CONFIG_AVR32) initr_enable_interrupts, #endif #if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) \ || defined(CONFIG_M68K) timer_init, /* initialize timer */ #endif #if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT) initr_status_led, #endif /* PPC has a udelay(20) here dating from 2002. Why? */ #ifdef CONFIG_CMD_NET initr_ethaddr, #endif #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif #ifdef CONFIG_FSL_FASTBOOT initr_fastboot_setup, #endif #ifdef CONFIG_CMD_SCSI INIT_FUNC_WATCHDOG_RESET initr_scsi, #endif #ifdef CONFIG_CMD_DOC INIT_FUNC_WATCHDOG_RESET initr_doc, #endif #ifdef CONFIG_BITBANGMII initr_bbmii, #endif #ifdef CONFIG_CMD_NET INIT_FUNC_WATCHDOG_RESET initr_net, #endif #ifdef CONFIG_POST initr_post, #endif #if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE) initr_pcmcia, #endif #if defined(CONFIG_CMD_IDE) initr_ide, #endif #ifdef CONFIG_LAST_STAGE_INIT INIT_FUNC_WATCHDOG_RESET /* * Some parts can be only initialized if all others (like * Interrupts) are up and running (i.e. the PC-style ISA * keyboard). */ last_stage_init, #endif #ifdef CONFIG_CMD_BEDBUG INIT_FUNC_WATCHDOG_RESET initr_bedbug, #endif #if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) initr_mem, #endif #ifdef CONFIG_PS2KBD initr_kbd, #endif #ifdef CONFIG_FSL_FASTBOOT initr_check_fastboot, #endif run_main_loop, };
int stdio_add_devices(void) { #ifdef CONFIG_SYS_I2C i2c_init_all(); #else #if defined(CONFIG_HARD_I2C) i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); #endif #endif #ifdef CONFIG_LCD drv_lcd_init (); #endif #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) <span style="color:#FF0000;">drv_video_init ();</span> #endif #ifdef CONFIG_KEYBOARD drv_keyboard_init (); #endif #ifdef CONFIG_LOGBUFFER drv_logbuff_init (); #endif drv_system_init (); serial_stdio_init (); #ifdef CONFIG_USB_TTY drv_usbtty_init (); #endif #ifdef CONFIG_NETCONSOLE drv_nc_init (); #endif #ifdef CONFIG_JTAG_CONSOLE drv_jtag_console_init (); #endif #ifdef CONFIG_CBMEM_CONSOLE cbmemc_init(); #endif return 0; }
int drv_video_init(void) { int skip_dev_init; struct stdio_dev console_dev; /* Check if video initialization should be skipped */ <span style="color:#FF0000;">if (board_video_skip())</span> return 0; /* Init video chip - returns with framebuffer cleared */ <span style="color:#FF0000;">skip_dev_init = (video_init() == -1);</span> if (board_cfb_skip()) return 0; #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE) debug("KBD: Keyboard init ...\n"); skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1); #endif if (skip_dev_init) return 0; /* Init vga device */ memset(&console_dev, 0, sizeof(console_dev)); strcpy(console_dev.name, "vga"); console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */ console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM; console_dev.putc = video_putc; /* 'putc' function */ console_dev.puts = video_puts; /* 'puts' function */ #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE) /* Also init console device */ console_dev.flags |= DEV_FLAGS_INPUT; console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */ console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */ #endif /* CONFIG_VGA_AS_SINGLE_DEVICE */ if (stdio_register(&console_dev) != 0) return 0; /* Return success */ return 1; }
board_video_skip获取要初始化的屏幕参数arch/arm/imx-common/video.c
int board_video_skip(void) { int i; int ret; char const *panel = getenv("panel"); if (!panel) { for (i = 0; i < display_count; i++) { struct display_info_t const *dev = displays+i; if (dev->detect && dev->detect(dev)) { panel = dev->mode.name; printf("auto-detected panel %s\n", panel); break; } } if (!panel) { panel = displays[0].mode.name; printf("No panel detected: default to %s\n", panel); i = 2; } } else { for (i = 0; i < display_count; i++) { if (!strcmp(panel, displays[i].mode.name)) break; } } if (i < display_count) { ret = <span style="color:#FF0000;">ipuv3_fb_init</span>(&displays[i].mode, 0, displays[i].pixfmt); if (!ret) { if (displays[i].enable) displays[i].enable(displays + i); printf("Display: %s (%ux%u)\n", displays[i].mode.name, displays[i].mode.xres, displays[i].mode.yres); } else printf("LCD %s cannot be configured: %d\n", displays[i].mode.name, ret); } else { printf("unsupported panel %s\n", panel); return -EINVAL; } return 0;
void video_inti(void)
{
------
video_hw_init //屏幕初始化(根据上面获取到的参数)
video_logo();//刷logo(位于tools/logos/xxx.bmp,该bmp位图被编译成数组,最终被刷出来)
------
}
在刷logo的过程中会调用flush_cache刷新一下缓冲区,否则图像会变得离散。
if (cfb_do_flush_cache)
flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
VIDEO_FB_ADRS显示基地址
VIDEO_SIZE显示的大小
在uboot中有很多debug函数,打开debug函数可以看到uboot中函数的调用过程。
dedug函数(include/common.h)的定义为
#ifdef DEBUG #define _DEBUG 1 #else #define _DEBUG 0 #endif #ifndef pr_fmt #define pr_fmt(fmt) fmt #endif /* * Output a debug text when condition "cond" is met. The "cond" should be * computed by a preprocessor in the best case, allowing for the best * optimization. */ #define debug_cond(cond, fmt, args...) \ do { \ if (cond) \ printf(pr_fmt(fmt), ##args); \ } while (0) #define debug(fmt, args...) \ debug_cond(_DEBUG, fmt, ##args)只需在前面添加#define DEBUG即可打开该函数。
另外,查找函数调用关系时,如果有多个地方被定义,不确定具体的定义位置时,只需到该目录下,ls -al *.o,即可确认真正被调用的函数。因为该函数被编译了,就会
生成.o文件。