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)最终调用了arch/arm/lib/board.c
void board_init_r(gd_t *id, ulong dest_addr) { ulong malloc_start; #if !defined(CONFIG_SYS_NO_FLASH) ulong flash_size; #endif gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r"); monitor_flash_len = (ulong)&__rel_dyn_end - (ulong)_start; /* Enable caches */ enable_caches(); debug("monitor flash len: %08lX\n", monitor_flash_len); board_init(); /* Setup chipselects */ /* * 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 serial_initialize(); debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr); #ifdef CONFIG_LOGBUFFER logbuff_init_ptrs(); #endif #ifdef CONFIG_POST post_output_backlog(); #endif /* The Malloc area is immediately below the monitor copy in DRAM */ malloc_start = dest_addr - TOTAL_MALLOC_LEN; mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN); #ifdef CONFIG_ARCH_EARLY_INIT_R arch_early_init_r(); #endif power_init_board(); #if !defined(CONFIG_SYS_NO_FLASH) puts("Flash: "); flash_size = flash_init(); if (flash_size > 0) { # ifdef CONFIG_SYS_FLASH_CHECKSUM print_size(flash_size, ""); /* * Compute and print flash CRC if flashchecksum is set to 'y' * * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX */ if (getenv_yesno("flashchecksum") == 1) { printf(" CRC: %08X", crc32(0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size)); } putc('\n'); # else /* !CONFIG_SYS_FLASH_CHECKSUM */ print_size(flash_size, "\n"); # endif /* CONFIG_SYS_FLASH_CHECKSUM */ } else { puts(failed); hang(); } #endif #if defined(CONFIG_CMD_NAND) puts("NAND: "); nand_init(); /* go init the NAND */ #endif #if defined(CONFIG_CMD_ONENAND) onenand_init(); #endif #ifdef CONFIG_GENERIC_MMC puts("MMC: "); mmc_initialize(gd->bd); #endif #ifdef CONFIG_CMD_SCSI puts("SCSI: "); scsi_init(); #endif #ifdef CONFIG_HAS_DATAFLASH AT91F_DataflashInit(); dataflash_print_info(); #endif /* initialize environment */ if (should_load_env()) env_relocate(); else set_default_env(NULL); #if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI) arm_pci_init(); #endif <span style="color:#FF0000;">stdio_init(); /* get the devices list going. */</span> jumptable_init(); #if defined(CONFIG_API) /* Initialize API */ api_init(); #endif console_init_r(); /* fully init console as a device */ #ifdef CONFIG_DISPLAY_BOARDINFO_LATE # ifdef CONFIG_OF_CONTROL /* Put this here so it appears on the LCD, now it is ready */ display_fdt_model(gd->fdt_blob); # else checkboard(); # endif #endif #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 /* set up exceptions */ interrupt_init(); /* enable exceptions */ enable_interrupts(); /* Initialize from environment */ load_addr = getenv_ulong("loadaddr", 16, load_addr); #ifdef CONFIG_BOARD_LATE_INIT board_late_init(); #endif #ifdef CONFIG_FSL_FASTBOOT fastboot_setup(); #endif #ifdef CONFIG_BITBANGMII bb_miiphy_init(); #endif #if defined(CONFIG_CMD_NET) puts("Net: "); eth_initialize(gd->bd); #if defined(CONFIG_RESET_PHY_R) debug("Reset Ethernet PHY\n"); reset_phy(); #endif #endif #ifdef CONFIG_POST post_run(NULL, POST_RAM | post_bootmode_get(0)); #endif #if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) /* * Export available size of memory for Linux, * taking into account the protected RAM at top of memory */ { ulong pram = 0; uchar memsz[32]; #ifdef CONFIG_PRAM pram = getenv_ulong("pram", 10, CONFIG_PRAM); #endif #ifdef CONFIG_LOGBUFFER #ifndef CONFIG_ALT_LB_ADDR /* Also take the logbuffer into account (pram is in kB) */ pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024; #endif #endif sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram); setenv("mem", (char *)memsz); } #endif #ifdef CONFIG_FSL_FASTBOOT check_fastboot(); #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 */ }
这里重点研究一下stdio_init()函数,在函数在common/stdio.c中实现
int stdio_init(void) { stdio_init_tables(); <span style="color:#FF0000;">stdio_add_devices();</span> return 0; }
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;
最终调用video_init初始化屏幕并显示logo
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文件。
时间: 2024-11-09 00:45:29