Mini2440之uboot移植之源码分析board_init_f(二)
一、board_init_f(common/board_f.c)
该函数位于common/board_f.c文件:
void board_init_f(ulong boot_flags) { #ifdef CONFIG_SYS_GENERIC_GLOBAL_DATA /* * For some archtectures, global data is initialized and used before * calling this function. The data should be preserved. For others, * CONFIG_SYS_GENERIC_GLOBAL_DATA should be defined and use the stack * here to host global data until relocation. */ gd_t data; gd = &data; /* * Clear global data before it is accessed at debug print * in initcall_run_list. Otherwise the debug print probably * get the wrong vaule of gd->have_console. */ zero_global_data(); #endif gd->flags = boot_flags; #0x00 gd->have_console = 0; #0x00 if (initcall_run_list(init_sequence_f)) hang(); #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \ !defined(CONFIG_EFI_APP) /* NOTREACHED - jump_to_copy() does not return */ hang(); #endif }
填充了flags和have_console字段后就执行一个初始化列表循环,这个循环里面有很多的函数,只要其中一个出错,u-boot启动就会停止。
initcall_run_list位于lib/initcall.c文件中:
int initcall_run_list(const init_fnc_t init_sequence[]) { const init_fnc_t *init_fnc_ptr; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { unsigned long reloc_ofs = 0; int ret; if (gd->flags & GD_FLG_RELOC) reloc_ofs = gd->reloc_off; #ifdef CONFIG_EFI_APP reloc_ofs = (unsigned long)image_base; #endif debug("initcall: %p", (char *)*init_fnc_ptr - reloc_ofs); if (gd->flags & GD_FLG_RELOC) debug(" (relocated to %p)\n", (char *)*init_fnc_ptr); else debug("\n"); ret = (*init_fnc_ptr)(); if (ret) { printf("initcall sequence %p failed at call %p (err=%d)\n", init_sequence, (char *)*init_fnc_ptr - reloc_ofs, ret); return -1; } } return 0; }
这里我们记录gd_t这个数据结构:
typedef struct global_data { bd_t *bd; unsigned long flags; unsigned int baudrate; unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long bus_clk; /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */ unsigned long pci_clk; unsigned long mem_clk; #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) unsigned long fb_base; /* Base address of framebuffer mem */ #endif #if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) unsigned long post_log_word; /* Record POST activities */ unsigned long post_log_res; /* success of POST test */ unsigned long post_init_f_time; /* When post_init_f started */ #endif #ifdef CONFIG_BOARD_TYPES unsigned long board_type; #endif unsigned long have_console; /* serial_init() was called */ #ifdef CONFIG_PRE_CONSOLE_BUFFER unsigned long precon_buf_idx; /* Pre-Console buffer index */ #endif unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long ram_top; /* Top address of RAM used by U-Boot */ unsigned long relocaddr; /* Start address of U-Boot in RAM */ phys_size_t ram_size; /* RAM size */ #ifdef CONFIG_SYS_MEM_RESERVE_SECURE #define MEM_RESERVE_SECURE_SECURED 0x1 #define MEM_RESERVE_SECURE_MAINTAINED 0x2 #define MEM_RESERVE_SECURE_ADDR_MASK (~0x3) /* * Secure memory addr * This variable needs maintenance if the RAM base is not zero, * or if RAM splits into non-consecutive banks. It also has a * flag indicating the secure memory is marked as secure by MMU. * Flags used: 0x1 secured * 0x2 maintained */ phys_addr_t secure_ram; #endif unsigned long mon_len; /* monitor len */ unsigned long irq_sp; /* irq stack pointer */ unsigned long start_addr_sp; /* start_addr_stackpointer */ unsigned long reloc_off; struct global_data *new_gd; /* relocated global data */ #ifdef CONFIG_DM struct udevice *dm_root; /* Root instance for Driver Model */ struct udevice *dm_root_f; /* Pre-relocation root instance */ struct list_head uclass_root; /* Head of core tree */ #endif #ifdef CONFIG_TIMER struct udevice *timer; /* Timer instance for Driver Model */ #endif const void *fdt_blob; /* Our device tree, NULL if none */ void *new_fdt; /* Relocated FDT */ unsigned long fdt_size; /* Space reserved for relocated FDT */ struct jt_funcs *jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ #ifdef CONFIG_TRACE void *trace_buff; /* The trace buffer */ #endif #if defined(CONFIG_SYS_I2C) int cur_i2c_bus; /* current used i2c bus */ #endif #ifdef CONFIG_SYS_I2C_MXC void *srdata[10]; #endif unsigned long timebase_h; unsigned long timebase_l; #ifdef CONFIG_SYS_MALLOC_F_LEN unsigned long malloc_base; /* base address of early malloc() */ unsigned long malloc_limit; /* limit address */ unsigned long malloc_ptr; /* current address */ #endif #ifdef CONFIG_PCI struct pci_controller *hose; /* PCI hose for early use */ phys_addr_t pci_ram_top; /* top of region accessible to PCI */ #endif #ifdef CONFIG_PCI_BOOTDELAY int pcidelay_done; #endif struct udevice *cur_serial_dev; /* current serial device */ struct arch_global_data arch; /* architecture-specific data */ #ifdef CONFIG_CONSOLE_RECORD struct membuff console_out; /* console output */ struct membuff console_in; /* console input */ #endif #ifdef CONFIG_DM_VIDEO ulong video_top; /* Top of video frame buffer area */ ulong video_bottom; /* Bottom of video frame buffer area */ #endif } gd_t; #endif /* * Global Data Flags - the top 16 bits are reserved for arch-specific flags */ #define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ #define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ #define GD_FLG_SILENT 0x00004 /* Silent mode */ #define GD_FLG_POSTFAIL 0x00008 /* Critical POST test failed */ #define GD_FLG_POSTSTOP 0x00010 /* POST seqeunce aborted */ #define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ #define GD_FLG_ENV_READY 0x00080 /* Env. imported into hash table */ #define GD_FLG_SERIAL_READY 0x00100 /* Pre-reloc serial console ready */ #define GD_FLG_FULL_MALLOC_INIT 0x00200 /* Full malloc() is ready */ #define GD_FLG_SPL_INIT 0x00400 /* spl_init() has been called */ #define GD_FLG_SKIP_RELOC 0x00800 /* Don't relocate */ #define GD_FLG_RECORD 0x01000 /* Record console */ #endif /* __ASM_GENERIC_GBL_DATA_H */
二、 init_sequence_f
init_sequence_f是一个函数指针数组,里面存放着各种初始化的函数指针,其中大部分函数只有定义了指定了宏才会生效,后面会针对其中比较重要的函数进行一一介绍。
static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_SANDBOX setup_ram_buf, #endif setup_mon_len, #ifdef CONFIG_OF_CONTROL fdtdec_setup, #endif #ifdef CONFIG_TRACE trace_early_init, #endif initf_malloc, initf_console_record, #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) /* TODO: can this go into arch_cpu_init()? */ probecpu, #endif #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) x86_fsp_init, #endif arch_cpu_init, /* basic arch cpu dependent setup */ initf_dm, arch_cpu_init_dm, mark_bootstage, /* need timer, go after init dm */ #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif /* TODO: can any of this go into arch_cpu_init()? */ #if defined(CONFIG_PPC) && !defined(CONFIG_8xx_CPUCLK_DEFAULT) get_clocks, /* get CPU and bus clocks (etc.) */ #if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \ && !defined(CONFIG_TQM885D) adjust_sdram_tbs_8xx, #endif /* TODO: can we rename this to timer_init()? */ init_timebase, #endif #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \ defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \ defined(CONFIG_SPARC) timer_init, /* initialize timer */ #endif #ifdef CONFIG_SYS_ALLOC_DPRAM #if !defined(CONFIG_CPM2) dpram_init, #endif #endif #if defined(CONFIG_BOARD_POSTCLK_INIT) board_postclk_init, #endif #if defined(CONFIG_SYS_FSL_CLK) || defined(CONFIG_M68K) get_clocks, #endif env_init, /* initialize environment */ #if defined(CONFIG_8xx_CPUCLK_DEFAULT) /* get CPU and bus clocks according to the environment variable */ get_clocks_866, /* adjust sdram refresh rate according to the new clock */ sdram_adjust_866, init_timebase, #endif init_baud_rate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ #ifdef CONFIG_SANDBOX sandbox_early_getopt_check, #endif #ifdef CONFIG_OF_CONTROL fdtdec_prepare_fdt, #endif display_options, /* say that we are here */ display_text_info, /* show debugging info if required */ #if defined(CONFIG_MPC8260) prt_8260_rsr, prt_8260_clks, #endif /* CONFIG_MPC8260 */ #if defined(CONFIG_MPC83xx) prt_83xx_rsr, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K) checkcpu, #endif print_cpuinfo, /* display cpu info (and speed) */ #if defined(CONFIG_MPC5xxx) prt_mpc5xxx_clks, #endif /* CONFIG_MPC5xxx */ #if defined(CONFIG_DISPLAY_BOARDINFO) show_board_info, #endif INIT_FUNC_WATCHDOG_INIT #if defined(CONFIG_MISC_INIT_F) misc_init_f, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) init_func_i2c, #endif #if defined(CONFIG_HARD_SPI) init_func_spi, #endif announce_dram_init, /* TODO: unify all these dram functions? */ #if defined(CONFIG_ARM) || defined(CONFIG_X86) || defined(CONFIG_NDS32) || \ defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) dram_init, /* configure available RAM banks */ #endif #if defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_M68K) init_func_ram, #endif #ifdef CONFIG_POST post_init_f, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_SYS_DRAM_TEST) testdram, #endif /* CONFIG_SYS_DRAM_TEST */ INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_POST init_post, #endif INIT_FUNC_WATCHDOG_RESET /* * Now that we have DRAM mapped and working, we can * relocate the code and continue running from DRAM. * * Reserve memory at end of RAM for (top down in that order): * - area that won't get touched by U-Boot and Linux (optional) * - kernel log buffer * - protected RAM * - LCD framebuffer * - monitor code * - board info struct */ setup_dest_addr, #if defined(CONFIG_BLACKFIN) /* Blackfin u-boot monitor should be on top of the ram */ reserve_uboot, #endif #if defined(CONFIG_SPARC) reserve_prom, #endif #if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR) reserve_logbuffer, #endif #ifdef CONFIG_PRAM reserve_pram, #endif reserve_round_4k, #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) && \ defined(CONFIG_ARM) reserve_mmu, #endif #ifdef CONFIG_DM_VIDEO reserve_video, #else # ifdef CONFIG_LCD reserve_lcd, # endif /* TODO: Why the dependency on CONFIG_8xx? */ # if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \ !defined(CONFIG_ARM) && !defined(CONFIG_X86) && \ !defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K) reserve_legacy_video, # endif #endif /* CONFIG_DM_VIDEO */ reserve_trace, #if !defined(CONFIG_BLACKFIN) reserve_uboot, #endif #ifndef CONFIG_SPL_BUILD reserve_malloc, reserve_board, #endif setup_machine, reserve_global_data, reserve_fdt, reserve_arch, reserve_stacks, setup_dram_config, show_dram_config, #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) setup_board_part1, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K) INIT_FUNC_WATCHDOG_RESET setup_board_part2, #endif display_new_sp, #ifdef CONFIG_SYS_EXTBDINFO setup_board_extra, #endif INIT_FUNC_WATCHDOG_RESET reloc_fdt, setup_reloc, #if defined(CONFIG_X86) || defined(CONFIG_ARC) copy_uboot_to_ram, clear_bss, do_elf_reloc_fixups, #endif #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) jump_to_copy, #endif NULL, };
函数指针类型:
typedef int (*init_fnc_t)(void);
由于这个数组太长了,下面列出定义函数(如何知道哪些函数被定义了呢,查看反汇编代码u-boot.map和u-boot.dis)
然后我们打开u-boot.dis文件,找到init_sequence_f定义:
0007217c <init_sequence_f>: 7217c: 0000e70c .word 0x0000e70c 72180: 00014964 .word 0x00014964 72184: 0000e894 .word 0x0000e894 72188: 0000e72c .word 0x0000e72c 7218c: 0000e89c .word 0x0000e89c 72190: 0000e8ac .word 0x0000e8ac 72194: 0000ea78 .word 0x0000ea78 72198: 00000fd8 .word 0x00000fd8 7219c: 00000634 .word 0x00000634 721a0: 00010610 .word 0x00010610 721a4: 0000ea4c .word 0x0000ea4c 721a8: 0002ea38 .word 0x0002ea38 721ac: 000144d0 .word 0x000144d0 721b0: 0005a428 .word 0x0005a428 721b4: 0000e704 .word 0x0000e704 721b8: 000003b0 .word 0x000003b0 721bc: 0000ea34 .word 0x0000ea34 721c0: 000010e4 .word 0x000010e4 721c4: 0000e9b4 .word 0x0000e9b4 721c8: 0000e750 .word 0x0000e750 721cc: 0000e768 .word 0x0000e768 721d0: 0000e7a0 .word 0x0000e7a0 721d4: 0000e7a8 .word 0x0000e7a8 721d8: 0000e7d8 .word 0x0000e7d8 721dc: 0000e97c .word 0x0000e97c 721e0: 0000e7ec .word 0x0000e7ec 721e4: 0000e7f4 .word 0x0000e7f4 721e8: 0000e810 .word 0x0000e810 721ec: 0000e8a4 .word 0x0000e8a4 721f0: 0000e870 .word 0x0000e870 721f4: 0000ea24 .word 0x0000ea24 721f8: 0000e944 .word 0x0000e944 721fc: 0000e88c .word 0x0000e88c 72200: 0000e908 .word 0x0000e908 72204: 0000e8dc .word 0x0000e8dc 72208: 00000000 .word 0x00000000
然后我们找到每个函数指针地址,就可以看到对应的函数,最终得到如下函数:
/*虽然未定义的都删除了,但是还是有这么多*/ static const init_fnc_t init_sequence_f[] = { setup_mon_len, initf_malloc, initf_console_record, arch_cpu_init, /* basic arch cpu dependent setup */ initf_dm, arch_cpu_init_dm, mark_bootstage, board_early_init_f, timer_init, /* initialize timer */ env_init, /* initialize environment */ init_baud_rate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, display_options, display_text_info, print_cpuinfo, announce_dram_init, dram_init, /* configure available RAM banks *//* * Now that we have DRAM mapped and working, we can * relocate the code and continue running from DRAM. * * Reserve memory at end of RAM for (top down in that order): * - area that won't get touched by U-Boot and Linux (optional) * - kernel log buffer * - protected RAM * - LCD framebuffer * - monitor code * - board info struct */ setup_dest_addr, reserve_round_4k, reserve_mmu, reserve_trace, reserve_uboot, reserve_malloc, reserve_board, setup_machine, reserve_global_data, reserve_fdt, reserve_arch, reserve_stacks, setup_dram_config, show_dram_config, display_new_sp, reloc_fdt, setup_reloc, NULL, };
三、各个函数指针
3.1 setup_mon_len(common/board_f.c)
static int setup_mon_len(void) { #if defined(__ARM__) || defined(__MICROBLAZE__) gd->mon_len = (ulong)&__bss_end - (ulong)_start; #elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP) gd->mon_len = (ulong)&_end - (ulong)_init; #elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2) gd->mon_len = CONFIG_SYS_MONITOR_LEN; #elif defined(CONFIG_NDS32) gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start); #else /* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */ gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE; #endif return 0; }
- _start为我们的.text的首地址;
- _bss_end为我们uboot包含所有段的结束地址;
设置gd->mon_len为uboot的大小;
3.2 initf_malloc(common/dlmalloc.c)
CONFIG_SYS_MALLOC_F_LEN没有在顶层.config文件定义:
int initf_malloc(void) { #ifdef CONFIG_SYS_MALLOC_F_LEN assert(gd->malloc_base); /* Set up by crt0.S */ gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN; gd->malloc_ptr = 0; #endif return 0; }
3.3 initf_console_record(common/board_f.c)
static int initf_console_record(void) { #if defined(CONFIG_CONSOLE_RECORD) && defined(CONFIG_SYS_MALLOC_F_LEN) return console_record_init(); #else return 0; #endif }
3.4 arch_cpu_init(common/board_f.c)
__weak int arch_cpu_init(void) { return 0; }
3.5 initf_dm(common/board_f.c)
动模型相关的初始化,新版的u-boot引入的。
static int initf_dm(void) { #if defined(CONFIG_DM) && defined(CONFIG_SYS_MALLOC_F_LEN) int ret; ret = dm_init_and_scan(true); if (ret) return ret; #endif #ifdef CONFIG_TIMER_EARLY ret = dm_timer_init(); if (ret) return ret; #endif return 0; }
3.6 arch_cpu_init_dm(common/board_f.c)
__weak int arch_cpu_init_dm(void) { return 0; }
3.7 mark_bootstage(common/board_f.c)
/* Record the board_init_f() bootstage (after arch_cpu_init()) */ static int mark_bootstage(void) { bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f"); return 0; }
3.8 board_early_init_f(board/samsung/smdk2440/smdk2440.c)系统时钟初始化FCLK = 400MHz,HCLK = 100MHz, PCLK = 50MHz, UPLL=48MHz
int board_early_init_f(void) { struct s3c24x0_clock_power * const clk_power = s3c24x0_get_base_clock_power(); struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio(); /* to reduce PLL lock time, adjust the LOCKTIME register */ writel(0xFFFFFF, &clk_power->locktime); /* configure MPLL */ writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV, &clk_power->mpllcon); /* some delay between MPLL and UPLL */ pll_delay(4000); /* configure UPLL */ writel((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV, &clk_power->upllcon); /* some delay between MPLL and UPLL */ pll_delay(8000); /* set up the I/O ports */ writel(0x007FFFFF, &gpio->gpacon); writel(0x00044555, &gpio->gpbcon); writel(0x000007FF, &gpio->gpbup); writel(0xAAAAAAAA, &gpio->gpccon); writel(0x0000FFFF, &gpio->gpcup); writel(0xAAAAAAAA, &gpio->gpdcon); writel(0x0000FFFF, &gpio->gpdup); writel(0xAAAAAAAA, &gpio->gpecon); writel(0x0000FFFF, &gpio->gpeup); writel(0x000055AA, &gpio->gpfcon); writel(0x000000FF, &gpio->gpfup); writel(0xFF95FFBA, &gpio->gpgcon); writel(0x0000FFFF, &gpio->gpgup); writel(0x002AFAAA, &gpio->gphcon); writel(0x000007FF, &gpio->gphup); return 0; }
这块代码主要是用来初始化系统时钟和各种IO。
3.9 timer_init(arch/arm/cpu/arm920t/s3c24x0/time.c)
int timer_init(void) { struct s3c24x0_timers *timers = s3c24x0_get_base_timers(); ulong tmr; /* use PWM Timer 4 because it has no output */ /* prescaler for Timer 4 is 16 */ writel(0x0f00, &timers->tcfg0); if (gd->arch.tbu == 0) { /* * for 10 ms clock period @ PCLK with 4 bit divider = 1/2 * (default) and prescaler = 13. Should be 10390 * @33.25MHz and 15625 @ 50 MHz */ gd->arch.tbu = get_PCLK() / (2 * 16 * 100); gd->arch.timer_rate_hz = get_PCLK() / (2 * 16); } /* load value for 10 ms timeout */ writel(gd->arch.tbu, &timers->tcntb4); /* auto load, manual update of timer 4 */ tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000; writel(tmr, &timers->tcon); /* auto load, start timer 4 */ tmr = (tmr & ~0x0700000) | 0x0500000; writel(tmr, &timers->tcon); gd->arch.lastinc = 0; gd->arch.tbl = 0; return 0; }
3.10 env_init设置环境变量存储地址
env_init函数在多个文件中定义,比如使用mmc、nand、nor初始化环境变量:
具体编译时使用哪个文件,我么可以查看common/Makefile文件中的定义:
可以看到具体编译哪个文件,取决于宏的定义,查找smdk2440.h中配置的宏配置:
发现默认使用NOR FLASH去初始化环境变量,定位到common/env_flash文件:
int env_init(void) { if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { gd->env_addr = (ulong)&(env_ptr->data); gd->env_valid = 1; return 0; } gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 0; return 0; }
这里首先进行crc32校验,如果校验成功,设置gd->env_valid=1,否者设置gd->env_valid=0,也就是使用默认环境变量初始化。
env_ptr由crc校验值和环境变量字符串组成,如果没有向NOR FLASH地址CONFIG_ENV_ADDR处写入环境变量信息,这里是不可能校验成功的。这里是不可能校验成功的。
那crc32什么时候会校验成功呢,只有我们向env_ptr指向的地址(CONFIG_ENV_ADDR)写入正确的环境变量信息,才能进行crc32校验才会成功。
typedef struct environment_s { uint32_t crc; /* CRC32 over data bytes */ #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT unsigned char flags; /* active/obsolete flags */ #endif unsigned char data[ENV_SIZE]; /* Environment data */ } env_t
default_environment 是一个全局字符数组,这里使用字符串常量来初始化字符数组,各个环境变量之间使用\0分隔:
#ifdef DEFAULT_ENV_INSTANCE_EMBEDDED env_t environment __PPCENV__ = { ENV_CRC, /* CRC Sum */ #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT 1, /* Flags: valid */ #endif { #elif defined(DEFAULT_ENV_INSTANCE_STATIC) static char default_environment[] = { #else const uchar default_environment[] = { #endif #ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0" #endif #ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0" #endif #ifdef CONFIG_BOOTARGS "bootargs=" CONFIG_BOOTARGS "\0" #endif #ifdef CONFIG_BOOTCOMMAND "bootcmd=" CONFIG_BOOTCOMMAND "\0" #endif #ifdef CONFIG_RAMBOOTCOMMAND "ramboot=" CONFIG_RAMBOOTCOMMAND "\0" #endif #ifdef CONFIG_NFSBOOTCOMMAND "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0" #endif #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) "bootdelay=" __stringify(CONFIG_BOOTDELAY) "\0" #endif #if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0) "baudrate=" __stringify(CONFIG_BAUDRATE) "\0" #endif #ifdef CONFIG_LOADS_ECHO "loads_echo=" __stringify(CONFIG_LOADS_ECHO) "\0" #endif #ifdef CONFIG_ETHPRIME "ethprime=" CONFIG_ETHPRIME "\0" #endif #ifdef CONFIG_IPADDR "ipaddr=" __stringify(CONFIG_IPADDR) "\0" #endif #ifdef CONFIG_SERVERIP "serverip=" __stringify(CONFIG_SERVERIP) "\0" #endif #ifdef CONFIG_SYS_AUTOLOAD "autoload=" CONFIG_SYS_AUTOLOAD "\0" #endif #ifdef CONFIG_PREBOOT "preboot=" CONFIG_PREBOOT "\0" #endif #ifdef CONFIG_ROOTPATH "rootpath=" CONFIG_ROOTPATH "\0" #endif #ifdef CONFIG_GATEWAYIP "gatewayip=" __stringify(CONFIG_GATEWAYIP) "\0" #endif #ifdef CONFIG_NETMASK "netmask=" __stringify(CONFIG_NETMASK) "\0" #endif #ifdef CONFIG_HOSTNAME "hostname=" __stringify(CONFIG_HOSTNAME) "\0" #endif #ifdef CONFIG_BOOTFILE "bootfile=" CONFIG_BOOTFILE "\0" #endif #ifdef CONFIG_LOADADDR "loadaddr=" __stringify(CONFIG_LOADADDR) "\0" #endif #ifdef CONFIG_CLOCKS_IN_MHZ "clocks_in_mhz=1\0" #endif #if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0) "pcidelay=" __stringify(CONFIG_PCI_BOOTDELAY)"\0" #endif #ifdef CONFIG_ENV_VARS_UBOOT_CONFIG "arch=" CONFIG_SYS_ARCH "\0" "cpu=" CONFIG_SYS_CPU "\0" "board=" CONFIG_SYS_BOARD "\0" "board_name=" CONFIG_SYS_BOARD "\0" #ifdef CONFIG_SYS_VENDOR "vendor=" CONFIG_SYS_VENDOR "\0" #endif #ifdef CONFIG_SYS_SOC "soc=" CONFIG_SYS_SOC "\0" #endif #endif #ifdef CONFIG_EXTRA_ENV_SETTINGS CONFIG_EXTRA_ENV_SETTINGS #endif "\0" #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED } #endif };
3.11 init_baud_rate(common/board_f.c)
static int init_baud_rate(void) { gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); return 0; }
设置波特率值为CONFIG_BAUDRATE=115200.
3.12 serial_init(drivers/serial/serial.c)初始化串口
int serial_init(void) { gd->flags |= GD_FLG_SERIAL_READY; return get_current()->start(); }
设置串口准备就绪标志位。然后初始化串口0:
/** * get_current() - Return pointer to currently selected serial port * * This function returns a pointer to currently selected serial port. * The currently selected serial port is altered by serial_assign() * function. * * In case this function is called before relocation or before any serial * port is configured, this function calls default_serial_console() to * determine the serial port. Otherwise, the configured serial port is * returned. * * Returns pointer to the currently selected serial port on success, * NULL on error. */ static struct serial_device *get_current(void) { struct serial_device *dev; if (!(gd->flags & GD_FLG_RELOC)) dev = default_serial_console(); else if (!serial_current) dev = default_serial_console(); else dev = serial_current; /* We must have a console device */ if (!dev) { #ifdef CONFIG_SPL_BUILD puts("Cannot find console\n"); hang(); #else panic("Cannot find console\n"); #endif } return dev; }
在drivers/serial/serial_s3c24x0.h文件中定义default_serial_console:
__weak struct serial_device *default_serial_console(void) { #if defined(CONFIG_SERIAL1) return &s3c24xx_serial0_device; #elif defined(CONFIG_SERIAL2) return &s3c24xx_serial1_device; #elif defined(CONFIG_SERIAL3) return &s3c24xx_serial2_device; #else #error "CONFIG_SERIAL? missing." #endif }
宏CONFIG_SERIAL1在include/configs/smdk2410.h文件中有定义。
struct serial_device s3c24xx_serial0_device = INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0");
#define INIT_S3C_SERIAL_STRUCTURE(port, __name) { \ .name = __name, \ .start = s3serial##port##_init, \ .stop = NULL, \ .setbrg = s3serial##port##_setbrg, \ .getc = s3serial##port##_getc, \ .tstc = s3serial##port##_tstc, \ .putc = s3serial##port##_putc, \ .puts = s3serial##port##_puts, \ }
然后执行start()方法,即运行s3serial##0##_init():
/* Multi serial device functions */ #define DECLARE_S3C_SERIAL_FUNCTIONS(port) \ int s3serial##port##_init(void) \ { \ return serial_init_dev(port); \ } \ void s3serial##port##_setbrg(void) \ { \ serial_setbrg_dev(port); \ } \ int s3serial##port##_getc(void) \ { \ return serial_getc_dev(port); \ } \ int s3serial##port##_tstc(void) \ { \ return serial_tstc_dev(port); \ } \ void s3serial##port##_putc(const char c) \ { \ serial_putc_dev(port, c); \ } \ void s3serial##port##_puts(const char *s) \ { \ serial_puts_dev(port, s); \ }
/* Initialise the serial port. The settings are always 8 data bits, no parity, * 1 stop bit, no start bits. */ static int serial_init_dev(const int dev_index) { struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); /* FIFO enable, Tx/Rx FIFO clear */ writel(0x07, &uart->ufcon); writel(0x0, &uart->umcon); /* Normal,No parity,1 stop,8 bit */ writel(0x3, &uart->ulcon); /* * tx=level,rx=edge,disable timeout int.,enable rx error int., * normal,interrupt or polling */ writel(0x245, &uart->ucon); _serial_setbrg(dev_index); return (0); }
这里首先获取串口寄存器基地址,然后配置串口相关寄存器:
- UFCON:FIFO寄存器;
- UMCON:MODEM控制寄存器;
- UCON:控制寄存器;
然后通过_serial_setbrg设置波特率:
static void _serial_setbrg(const int dev_index) { struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); unsigned int reg = 0; int i; /* value is calculated so : (int)(PCLK/16./baudrate) -1 */ reg = get_PCLK() / (16 * gd->baudrate) - 1; writel(reg, &uart->ubrdiv); for (i = 0; i < 100; i++) /* Delay */ ; }
这里通过公式动态计算UBRDIV寄存器的值。其中get_PCLK(arch/arm/cpu/arm920t/s3c24x0/speed.c)通过读取系统时钟相关寄存器的值获取PCLK频率:
/* * (C) Copyright 2001-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * (C) Copyright 2002 * David Mueller, ELSOFT AG, d.mueller@elsoft.ch * * SPDX-License-Identifier: GPL-2.0+ */ /* This code should work for both the S3C2400 and the S3C2410 * as they seem to have the same PLL and clock machinery inside. * The different address mapping is handled by the s3c24xx.h files below. */ #include <common.h> #ifdef CONFIG_S3C24X0 #include <asm/io.h> #include <asm/arch/s3c24x0_cpu.h> #define MPLL 0 #define UPLL 1 /* ------------------------------------------------------------------------- */ /* NOTE: This describes the proper use of this file. * * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. * * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of * the specified bus in HZ. */ /* ------------------------------------------------------------------------- */ static ulong get_PLLCLK(int pllreg) { struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); ulong r, m, p, s; if (pllreg == MPLL) r = readl(&clk_power->mpllcon); else if (pllreg == UPLL) r = readl(&clk_power->upllcon); else hang(); m = ((r & 0xFF000) >> 12) + 8; p = ((r & 0x003F0) >> 4) + 2; s = r & 0x3; #if defined(CONFIG_S3C2440) if (pllreg == MPLL) return 2 * m * (CONFIG_SYS_CLK_FREQ / (p << s)); #endif return (CONFIG_SYS_CLK_FREQ * m) / (p << s); } /* return FCLK frequency */ ulong get_FCLK(void) { return get_PLLCLK(MPLL); } /* return HCLK frequency */ ulong get_HCLK(void) { struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); #ifdef CONFIG_S3C2440 switch (readl(&clk_power->clkdivn) & 0x6) { default: case 0: return get_FCLK(); case 2: return get_FCLK() / 2; case 4: return (readl(&clk_power->camdivn) & (1 << 9)) ? get_FCLK() / 8 : get_FCLK() / 4; case 6: return (readl(&clk_power->camdivn) & (1 << 8)) ? get_FCLK() / 6 : get_FCLK() / 3; } #else return (readl(&clk_power->clkdivn) & 2) ? get_FCLK() / 2 : get_FCLK(); #endif } /* return PCLK frequency */ ulong get_PCLK(void) { struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); return (readl(&clk_power->clkdivn) & 1) ? get_HCLK() / 2 : get_HCLK(); } /* return UCLK frequency */ ulong get_UCLK(void) { return get_PLLCLK(UPLL); } #endif /* CONFIG_S3C24X0 */
3.13 console_init_f(common/console.c)
int console_init_f(void) { gd->have_console = 1; #ifdef CONFIG_SILENT_CONSOLE if (getenv("silent") != NULL) gd->flags |= GD_FLG_SILENT; #endif print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL); return 0; }
3.14 display_options(lib/display_options.c)
int display_options (void) { #if defined(BUILD_TAG) printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG); #else printf ("\n\n%s\n\n", version_string); #endif return 0; }
打印版本信息,你可以修改include/version.h中的CONFIG_IDENT_STRING选项, * 加入你的身份信息
3.15 display_text_info(common/board_f.c)
static int display_text_info(void) { #if !defined(CONFIG_SANDBOX) && !defined(CONFIG_EFI_APP) ulong bss_start, bss_end, text_base; bss_start = (ulong)&__bss_start; bss_end = (ulong)&__bss_end; #ifdef CONFIG_SYS_TEXT_BASE text_base = CONFIG_SYS_TEXT_BASE; #else text_base = CONFIG_SYS_MONITOR_BASE; #endif debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", text_base, bss_start, bss_end); #endif #ifdef CONFIG_USE_IRQ debug("IRQ Stack: %08lx\n", IRQ_STACK_START); debug("FIQ Stack: %08lx\n", FIQ_STACK_START); #endif return 0; }
如果定义了#define DEBUG,打印bss段信息及text_base。
3.16 print_cpuinfo(arch/arm/cpu/arm920t/s3c24x0/cpu_info.c)
int print_cpuinfo(void) { int i; char buf[32]; /* the S3C2400 seems to be lacking a CHIP ID register */ #ifndef CONFIG_S3C2400 ulong cpuid; struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio(); cpuid = readl(&gpio->gstatus1); printf("CPUID: %8lX\n", cpuid); #endif for (i = 0; i < ARRAY_SIZE(freq_f); i++) printf("%cCLK: %8s MHz\n", freq_c[i], strmhz(buf, freq_f[i]())); return 0; }
打印CPUID和时钟频率。默认只打印FCLK、HCLK、PCLK,如果想打印UCLK,修改全局变量freq_f、freq_c为:
static const getfreq freq_f[] = { get_FCLK, get_HCLK, get_PCLK, get_UCLK, }; static const char freq_c[] = { 'F', 'H', 'P','U' };
3.17 announce_dram_init(common/board_f.c)
static int announce_dram_init(void) { puts("DRAM: "); return 0; }
输出"DRAM: " 然后在下面进行SDRAM参数设置。
3.18 dram_init(board/samsung/smdk2410/smdk2410.c)
int dram_init(void) { /* dram_init must store complete ramsize in gd->ram_size */ gd->ram_size = PHYS_SDRAM_1_SIZE; return 0; }
设置SDRAM大小,PHYS_SDRAM_1_SIZE =64MB。
3.19 setup_dest_addr(common/board_f.c)
static int setup_dest_addr(void) { debug("Monitor len: %08lX\n", gd->mon_len); /* * Ram is setup, size stored in gd !! */ debug("Ram size: %08lX\n", (ulong)gd->ram_size); #ifdef CONFIG_SYS_MEM_RESERVE_SECURE /* Reserve memory for secure MMU tables, and/or security monitor */ gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE; /* * Record secure memory location. Need recalcuate if memory splits * into banks, or the ram base is not zero. */ gd->secure_ram = gd->ram_size; #endif /* * Subtract specified amount of memory to hide so that it won't * get "touched" at all by U-Boot. By fixing up gd->ram_size * the Linux kernel should now get passed the now "corrected" * memory size and won't touch it either. This has been used * by arch/powerpc exclusively. Now ARMv8 takes advantage of * thie mechanism. If memory is split into banks, addresses * need to be calculated. */ gd->ram_size = board_reserve_ram_top(gd->ram_size); //ram_size=64MB #ifdef CONFIG_SYS_SDRAM_BASE gd->ram_top = CONFIG_SYS_SDRAM_BASE; //在smdk2410.h定义的0x30000000 #endif gd->ram_top += get_effective_memsize(); // gd->ram_top+gd->ram_size gd->ram_top = board_get_usable_ram_top(gd->mon_len); //return gd->ram_top gd->relocaddr = gd->ram_top; debug("Ram top: %08lX\n", (ulong)gd->ram_top); #if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500)) /* * We need to make sure the location we intend to put secondary core * boot code is reserved and not used by any part of u-boot */ if (gd->relocaddr > determine_mp_bootpg(NULL)) { gd->relocaddr = determine_mp_bootpg(NULL); debug("Reserving MP boot page to %08lx\n", gd->relocaddr); } #endif return 0; }
将gd->relocaddr、gd->ram_top指向SDRAM最顶端0x30000000+64MB。
3.20 reserve_round_4k(common/board_f.c)
/* Round memory pointer down to next 4 kB limit */ static int reserve_round_4k(void) { gd->relocaddr &= ~(4096 - 1); return 0; }
gd->relocaddr 4k向下对齐。
3.21 reserve_mmu(common/board_f.c)
static int reserve_mmu(void) { /* reserve TLB table */ gd->arch.tlb_size = PGTABLE_SIZE; gd->relocaddr -= gd->arch.tlb_size; /* round down to next 64 kB limit */ gd->relocaddr &= ~(0x10000 - 1); //64k向下对齐 gd->arch.tlb_addr = gd->relocaddr; debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr, gd->arch.tlb_addr + gd->arch.tlb_size); return 0; }
预留MMU空间,PGTABLE_SIZE大小为16kb。这里又64kb向下对齐。
#define PGTABLE_SIZE (4096 * 4)
3.22 reserve_trace(common/board_f.c)
static int reserve_trace(void) { #ifdef CONFIG_TRACE gd->relocaddr -= CONFIG_TRACE_BUFFER_SIZE; gd->trace_buff = map_sysmem(gd->relocaddr, CONFIG_TRACE_BUFFER_SIZE); debug("Reserving %dk for trace data at: %08lx\n", CONFIG_TRACE_BUFFER_SIZE >> 10, gd->relocaddr); #endif return 0; }
3.23 reserve_uboot(common/board_f.c)
static int reserve_uboot(void) { /* * reserve memory for U-Boot code, data & bss * round down to next 4 kB limit */ gd->relocaddr -= gd->mon_len; // 减去u-boot总长度 gd->relocaddr &= ~(4096 - 1); //4k对齐 #ifdef CONFIG_E500 /* round down to next 64 kB limit so that IVPR stays aligned */ gd->relocaddr &= ~(65536 - 1); #endif debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, gd->relocaddr); gd->start_addr_sp = gd->relocaddr; return 0; }
预留u-boot空间,并设置relocaddr向下k对齐。
3.24 reserve_malloc(common/board_f.c)
/* reserve memory for malloc() area */ static int reserve_malloc(void) { gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN; debug("Reserving %dk for malloc() at: %08lx\n", TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp); return 0; }
预留一段malloc的空间,大小为4MB。在./include/common.h和./include/configs/smdk2410.h中定义有:
#define TOTAL_MALLOC_LEN CONFIG_SYS_MALLOC_LEN
/* * Size of malloc() pool * BZIP2 / LZO / LZMA need a lot of RAM */ #define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)
3.25 reserve_board(common/board_f.c)
/* (permanently) allocate a Board Info struct */ static int reserve_board(void) { if (!gd->bd) { gd->start_addr_sp -= sizeof(bd_t); gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t)); memset(gd->bd, '\0', sizeof(bd_t)); debug("Reserving %zu Bytes for Board Info at: %08lx\n", sizeof(bd_t), gd->start_addr_sp); } return 0; }
保留gd->bd的空间,大小为bd_t结构体大小。
3.26 setup_machine(common/board_f.c)
static int setup_machine(void) { #ifdef CONFIG_MACH_TYPE gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */ #endif return 0; }
3.27 reserve_global_data(common/board_f.c)
static int reserve_global_data(void) { gd->start_addr_sp -= sizeof(gd_t); gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t)); debug("Reserving %zu Bytes for Global Data at: %08lx\n", sizeof(gd_t), gd->start_addr_sp); return 0; }
3.28 reserve_fdt(common/board_f.c)
static int reserve_fdt(void) { #ifndef CONFIG_OF_EMBED /* * If the device tree is sitting immediately above our image then we * must relocate it. If it is embedded in the data section, then it * will be relocated with other data. */ if (gd->fdt_blob) { gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); gd->start_addr_sp -= gd->fdt_size; gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size); debug("Reserving %lu Bytes for FDT at: %08lx\n", gd->fdt_size, gd->start_addr_sp); } #endif return 0; }
3.29 reserve_arch(common/board_f.c)
__weak int reserve_arch(void) { return 0; }
3.30 reserve_stacks(common/board_f.c)
static int reserve_stacks(void) { /* make stack pointer 16-byte aligned */ gd->start_addr_sp -= 16; gd->start_addr_sp &= ~0xf; /* * let the architecture-specific code tailor gd->start_addr_sp and * gd->irq_sp */ return arch_reserve_stacks(); }
预留栈空间。
3.31 setup_dram_config(common/board_f.c)
static int setup_dram_config(void) { /* Ram is board specific, so move it to board code ... */ dram_init_banksize(); return 0; }
设置sdram地址和大小。gd->bd->bi_dram[i].start = addr,gd->bd->bi_dram[i].size = size。
3.32 show_dram_config(common/board_f.c)
static int show_dram_config(void) { unsigned long long size; #ifdef CONFIG_NR_DRAM_BANKS int i; debug("\nRAM Configuration:\n"); for (i = size = 0; i < CONFIG_NR_DRAM_BANKS; i++) { size += gd->bd->bi_dram[i].size; debug("Bank #%d: %llx ", i, (unsigned long long)(gd->bd->bi_dram[i].start)); #ifdef DEBUG print_size(gd->bd->bi_dram[i].size, "\n"); #endif } debug("\nDRAM: "); #else size = gd->ram_size; #endif print_size(size, ""); board_add_ram_info(0); putc('\n'); return 0; }
打印SDRAM大小,与上面的announce_dram_init相对应。
3.33 display_new_sp(common/board_f.c)
static int display_new_sp(void) { debug("New Stack Pointer is: %08lx\n", gd->start_addr_sp); return 0; }
若 #define DEBUG 则打印新的栈地址。
3.34 reloc_fdt(common/board_f.c)
static int reloc_fdt(void) { #ifndef CONFIG_OF_EMBED if (gd->flags & GD_FLG_SKIP_RELOC) return 0; if (gd->new_fdt) { memcpy(gd->new_fdt, gd->fdt_blob, gd->fdt_size); gd->fdt_blob = gd->new_fdt; } #endif return 0; }
GD_FLG_SKIP_RELOC 定义为0x00800。gd->flags & GD_FLG_SKIP_RELOC=0x100&0x800=0。gd->new_fdt未初始化,为0。
3.35 setup_reloc(common/board_f.c)
static int setup_reloc(void) { if (gd->flags & GD_FLG_SKIP_RELOC) { debug("Skipping relocation due to flag\n"); return 0; } #ifdef CONFIG_SYS_TEXT_BASE gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; /* 得到新旧u-boot的偏移 */ #ifdef CONFIG_M68K /* * On all ColdFire arch cpu, monitor code starts always * just after the default vector table location, so at 0x400 */ gd->reloc_off = gd->relocaddr - (CONFIG_SYS_TEXT_BASE + 0x400); #endif #endif memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); /* 拷贝gd_t */ debug("Relocation Offset is: %08lx\n", gd->reloc_off); debug("Relocating to %08lx, new gd at %08lx, sp at %08lx\n", gd->relocaddr, (ulong)map_to_sysmem(gd->new_gd), gd->start_addr_sp); return 0; }
将gd数据从旧地址拷贝到新地址。
以上所有初始化函数执行完毕,内存空间分布如下:
其中gd成员变量如下:
bd |
开发板数据指针 |
CONFIG_SYS_SDRAM_BASE+PHYS_SDRAM_1_SIZE-uboot-64kb-malloc-sizeof(bd_t) 0x30000000 + 64MB-uboot-64kb-malloc-sizeof(bd_t) |
flags |
指示标志,如设备已经初始化啦 |
GD_FLG_SERIAL_READY 0x00100 |
baudrate |
串口波特率 |
115200 |
cpu_clk |
CPU clock in Hz |
|
bus_clk |
|
|
pci_clk |
|
|
mem_clk |
|
|
have_console |
serial_init() was called |
1 |
env_addr |
环境变量的起始地址 |
|
env_valid |
校验环境变量是否有效 |
0 |
ram_top |
Top address of RAM used by U-Boot |
CONFIG_SYS_SDRAM_BASE+PHYS_SDRAM_1_SIZE 0x30000000 + 64MB |
relocaddr |
Start address of U-Boot in RAM |
CONFIG_SYS_SDRAM_BASE+PHYS_SDRAM_1_SIZE-uboot-64kb 0x30000000 + 64MB-uboot-64KB |
ram_size |
RAM size |
PHYS_SDRAM_1_SIZE 64MB |
mon_len |
u-boot总长度 |
(ulong)&__bss_end - (ulong)_start; |
irq_sp |
irq stack pointer |
|
start_addr_sp |
start_addr_stackpointer |
CONFIG_SYS_SDRAM_BASE+PHYS_SDRAM_1_SIZE-uboot-64kb-malloc-sizeof(bd_t)-sizeof(gd_t)-16 0x30000000 + 64MB-uboot-64kb-malloc-sizeof(bd_t)-sizeof(gd_t)-16 然后 向下16字节对齐 |
reloc_off |
|
gd->relocaddr - CONFIG_SYS_TEXT_BASE 其中CONFIG_SYS_TEXT_BASE=0 |
new_gd |
relocated global data |
CONFIG_SYS_SDRAM_BASE+PHYS_SDRAM_1_SIZE-uboot-64kb-malloc-sizeof(bd_t)-sizeof(gd_t) 0x30000000 + 64MB-uboot-64kb-malloc-sizeof(bd_t)-sizeof(gd_t) |
fdt_blob |
Our device tree, NULL if none |
|
new_fdt |
Relocated FDT |
|
fdt_size |
Space reserved for relocated FDT |
|
jt |
jump table |
|
env_buf |
buffer for getenv() before reloc |
|
timebase_h |
|
|
timebase_l |
|
|
cur_serial_dev |
|
|
arch |
|
四、总结
看完这部分代码,你会发现这部分代码并不复杂,大部分工作主要是对u-boot之后重定位进行内存的规划,也就是初始化gd成员变量。除了这些以外,当然还做了以下事情:
- 初始化系统时钟和基本IO;
- 初始化定时器;
- 初始化环境变量,指定环境变量存放地址(指向一个字符数组);
- 初始化串口0,作为控制台输出;
- 打印版本信息;
- 打印bss段信息及text_base;
- 打印CPUID和系统时钟信息;
- 打印DRAM信息;
- 打印新的栈地址;
参考文章: