crt0.S(_main)代码分析
生活随笔
收集整理的這篇文章主要介紹了
crt0.S(_main)代码分析
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
crt0,S(_main)代碼分析
---
1. 設(shè)置sp寄存器地址
//設(shè)置SP棧指針 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)ldr sp, =(CONFIG_SPL_STACK) #elseldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #endif//設(shè)置地址八位對(duì)齊 #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination*/mov r3, sp bic r3, r3, #7 //* 后三位清零相當(dāng)于堆棧地址八位對(duì)齊mov sp, r3 #elsebic sp, sp, #7 /* 8-byte alignment for ABI compliance */ #endif2. 在棧中為全局變量gd分配空間
// r0寄存器傳遞函數(shù)的參數(shù) mov r0, sp bl board_init_f_alloc_reserve //在棧中為全局?jǐn)?shù)據(jù)分配空間 mov sp, r0 //函數(shù)調(diào)用后返回值在r0中,將其保存到sp寄存器中 //根據(jù)下面的board_init_f_alloc_reserve函數(shù) //函數(shù)返回值為分配gb后的指針位置board_init_f_alloc_reserve函數(shù)原型如下:
ulong board_init_f_alloc_reserve(ulong top) {//將棧頂指針傳進(jìn)來,棧頂指針減去全局變量的長度意味著數(shù)據(jù)入棧,即在棧里預(yù)留變量存儲(chǔ)空間。/* Reserve early malloc arena */ #if defined(CONFIG_SYS_MALLOC_F)top -= CONFIG_SYS_MALLOC_F_LEN; #endif/* LAST : reserve GD (rounded up to a multiple of 16 bytes) */top = rounddown(top-sizeof(struct global_data), 16);return top; }3. 在棧中g(shù)d空間清零
mov r9, r0 //將棧頂指針存到r9寄存器里面,方便后續(xù)設(shè)置gd指針bl board_init_f_init_reserve //全局?jǐn)?shù)據(jù)全部清零board_init_f_init_reserve 函數(shù)定義如下:
void board_init_f_init_reserve(ulong base) {struct global_data *gd_ptr; #ifndef _USE_MEMCPYint *ptr; #endif/** clear GD entirely and set it up.* Use gd_ptr, as gd may not be properly set yet.* 清除GD分配空間*/gd_ptr = (struct global_data *)base;/* zero the area */ #ifdef _USE_MEMCPYmemset(gd_ptr, '\0', sizeof(*gd)); //全局?jǐn)?shù)據(jù)區(qū)全部清零 #elsefor (ptr = (int *)gd_ptr; ptr < (int *)(gd_ptr + 1); )*ptr++ = 0; #endif/* set GD unless architecture did it already */ #if !defined(CONFIG_ARM)arch_setup_gd(gd_ptr); #endif/* next alloc will be higher by one GD plus 16-byte alignment */base += roundup(sizeof(struct global_data), 16);/** record early malloc arena start.* Use gd as it is now properly set for all architectures.*/#if defined(CONFIG_SYS_MALLOC_F)/* go down one 'early malloc arena' */gd->malloc_base = base;/* next alloc will be higher by one 'early malloc arena' size */base += CONFIG_SYS_MALLOC_F_LEN; #endif }4. 調(diào)用board_init_f,初始化各種硬件
mov r0, #0bl board_init_f // jump to ==> board_f.c在board_init_f函數(shù)中所進(jìn)行的主要操作如下,其中init_sequence_f[ ]是一個(gè)數(shù)組,其內(nèi)容為一系列初始化函數(shù),在函數(shù)initcall_run_list中依次調(diào)用init_sequence_f數(shù)組的各個(gè)初始化函數(shù)。
void board_init_f(ulong boot_flags) {//此處省略多行代碼gd->flags = boot_flags;gd->have_console = 0;//通過調(diào)用initcall_run_list函數(shù),執(zhí)行各項(xiàng)初始化 if (initcall_run_list(init_sequence_f)) hang(); }initcall_run_list函數(shù)如下:
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) {int ret;//此處省略很多代碼//通過函數(shù)指針依次調(diào)用數(shù)組內(nèi)函數(shù)ret = (*init_fnc_ptr)(); } return 0; }數(shù)組init_sequence_f[ ]定義如下,每個(gè)成員為一個(gè)函數(shù)指針,函數(shù)參數(shù)為void,返回類型為int
static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_SANDBOXsetup_ram_buf, #endifsetup_mon_len, #ifdef CONFIG_OF_CONTROLfdtdec_setup, #endif #ifdef CONFIG_TRACEtrace_early_init, #endifinitf_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, #endifarch_cpu_init, /* basic arch cpu dependent setup */mach_cpu_init, /* SoC/machine dependent CPU 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_SH) || 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, #endifenv_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, #endifinit_baud_rate, /* initialze baudrate settings */serial_init, /* serial communications setup */console_init_f, /* stage 1 init of console */ #ifdef CONFIG_SANDBOXsandbox_early_getopt_check, #endifdisplay_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) || defined(CONFIG_SH)checkcpu, #endifprint_cpuinfo, /* display cpu info (and speed) */ #if defined(CONFIG_MPC5xxx)prt_mpc5xxx_clks, #endif /* CONFIG_MPC5xxx */ #if defined(CONFIG_DTB_RESELECT)embedded_dtb_select, #endif #if defined(CONFIG_DISPLAY_BOARDINFO)show_board_info, #endifINIT_FUNC_WATCHDOG_INIT #if defined(CONFIG_MISC_INIT_F)misc_init_f, #endifINIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)init_func_i2c, #endif #if defined(CONFIG_HARD_SPI)init_func_spi, #endifannounce_dram_init,/* TODO: unify all these dram functions? */ #if defined(CONFIG_ARM) || defined(CONFIG_X86) || defined(CONFIG_NDS32) || \defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) || \defined(CONFIG_SH)dram_init, /* configure available RAM banks */ #endif #if defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_M68K)init_func_ram, #endif #ifdef CONFIG_POSTpost_init_f, #endifINIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_SYS_DRAM_TEST)testdram, #endif /* CONFIG_SYS_DRAM_TEST */INIT_FUNC_WATCHDOG_RESET#ifdef CONFIG_POSTinit_post, #endifINIT_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) || defined(CONFIG_XTENSA)/* 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_PRAMreserve_pram, #endifreserve_round_4k, #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) && \defined(CONFIG_ARM)reserve_mmu, #endif #ifdef CONFIG_DM_VIDEOreserve_video, #else # ifdef CONFIG_LCDreserve_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) && !defined(CONFIG_XTENSA)reserve_uboot, #endif #ifndef CONFIG_SPL_BUILDreserve_malloc,reserve_board, #endifsetup_machine,reserve_global_data,reserve_fdt,reserve_arch,reserve_stacks,setup_dram_config,show_dram_config, #if defined(CONFIG_M68K) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || \defined(CONFIG_SH)setup_board_part1, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K)INIT_FUNC_WATCHDOG_RESETsetup_board_part2, #endifdisplay_new_sp, #ifdef CONFIG_SYS_EXTBDINFOsetup_board_extra, #endifINIT_FUNC_WATCHDOG_RESETreloc_fdt,setup_reloc, #if defined(CONFIG_X86) || defined(CONFIG_ARC)copy_uboot_to_ram,clear_bss,do_elf_reloc_fixups, #endif #if defined(CONFIG_XTENSA)clear_bss, #endif #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)jump_to_copy, #endifNULL, };轉(zhuǎn)載于:https://www.cnblogs.com/gexin/p/7281633.html
總結(jié)
以上是生活随笔為你收集整理的crt0.S(_main)代码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 性能测试相关名词解释
- 下一篇: 02替换空格