crt0.S(_main)代码分析
crt0,S(_main)代码分析
1. 设置sp寄存器地址
//设置SP栈指针
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	ldr	sp, =(CONFIG_SPL_STACK)
#else
	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
//设置地址八位对齐
#if defined(CONFIG_CPU_V7M)	/* v7M forbids using SP as BIC destination*/
	mov	r3, sp
	bic	r3, r3, #7		   //* 后三位清零相当于堆栈地址八位对齐
	mov	sp, r3
#else
	bic	sp, sp, #7	/* 8-byte alignment for ABI compliance */
#endif
2. 在栈中为全局变量gd分配空间
// r0寄存器传递函数的参数
mov	r0, sp
bl	board_init_f_alloc_reserve	//在栈中为全局数据分配空间
mov	sp, r0
//函数调用后返回值在r0中,将其保存到sp寄存器中
//根据下面的board_init_f_alloc_reserve函数
//函数返回值为分配gb后的指针位置
board_init_f_alloc_reserve函数原型如下:
ulong board_init_f_alloc_reserve(ulong top)
{
	//将栈顶指针传进来,栈顶指针减去全局变量的长度意味着数据入栈,即在栈里预留变量存储空间。
	/* 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. 在栈中gd空间清零
	mov	r9, r0	//将栈顶指针存到r9寄存器里面,方便后续设置gd指针
	bl	board_init_f_init_reserve	//全局数据全部清零
board_init_f_init_reserve 函数定义如下:
void board_init_f_init_reserve(ulong base)
{
	struct global_data *gd_ptr;
#ifndef _USE_MEMCPY
	int *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_MEMCPY
	memset(gd_ptr, '\0', sizeof(*gd));	//全局数据区全部清零
#else
	for (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. 调用board_init_f,初始化各种硬件
	mov	r0, #0
	bl	board_init_f	// jump to ==> board_f.c
在board_init_f函数中所进行的主要操作如下,其中init_sequence_f[ ]是一个数组,其内容为一系列初始化函数,在函数initcall_run_list中依次调用init_sequence_f数组的各个初始化函数。
void board_init_f(ulong boot_flags)
{
	//此处省略多行代码
	gd->flags = boot_flags;
	gd->have_console = 0;
	//通过调用initcall_run_list函数,执行各项初始化
	if (initcall_run_list(init_sequence_f))
		hang();
}
initcall_run_list函数如下:
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;
		//此处省略很多代码
		//通过函数指针依次调用数组内函数
		ret = (*init_fnc_ptr)();
	}
return 0;
}
数组init_sequence_f[ ]定义如下,每个成员为一个函数指针,函数参数为void,返回类型为int
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 */
	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,
#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
	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) || defined(CONFIG_SH)
	checkcpu,
#endif
	print_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,
#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) || \
		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_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) || 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_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) && !defined(CONFIG_XTENSA)
	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_M68K) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || \
	defined(CONFIG_SH)
	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_XTENSA)
	clear_bss,
#endif
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
	jump_to_copy,
#endif
	NULL,
};
												
											crt0.S(_main)代码分析的更多相关文章
- Uboot代码分析
		
(1)确定链接脚本文件:uboot根目录下Makefile中的LDSCRIPT宏值,就是指定链接脚本(如:arch/arm/cpu/u-boot.lds)路径用的.(2)从脚本文件找入口: 在链接脚本 ...
 - MSVC CRT运行库启动代码分析
		
原文链接:http://www.programlife.net/msvc-crt-startup.html 在程序进入main/WinMain函数之前,需要先进行C运行库的初始化操作,通过在Visua ...
 - Android代码分析工具lint学习
		
1 lint简介 1.1 概述 lint是随Android SDK自带的一个静态代码分析工具.它用来对Android工程的源文件进行检查,找出在正确性.安全.性能.可使用性.可访问性及国际化等方面可能 ...
 - pmd静态代码分析
		
在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...
 - [Asp.net 5] DependencyInjection项目代码分析-目录
		
微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...
 - [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)
		
Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...
 - 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)
		
构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...
 - STM32启动代码分析 IAR   比较好
		
stm32启动代码分析 (2012-06-12 09:43:31) 转载▼ 最近开始使用ST的stm32w108芯片(也是一款zigbee芯片).开始看他的启动代码看的晕晕呼呼呼的. 还好在c ...
 - 常用 Java 静态代码分析工具的分析与比较
		
常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...
 
随机推荐
- Oracle以固定字符截取字符串
			
CREATE OR REPLACE FUNCTION "F_SPLIT" (p_str IN CLOB, p_delimiter IN VARCHAR2) RETURN ty_st ...
 - 【js】数组添加与删除
			
做个表格,就会容易记忆四种方法. 返回值 是否改变数组长度 位置 功能 push() 改变数组的长度 是 末位 添加 unshift() 改变数组的长度 是 首位 添加 pop( ...
 - c/c++面试指导---c语法总结
			
任何一门学科或者专业在学习的过程中都要把握总结框架,大家在面试c/c++职位过程中要应对各种企业的面试,回答企业面试官的各种技术问题.如何应对各种各样的关于c/c++的企业面试题目,从各种繁杂的题目中 ...
 - operator.itemgetter() 字典列表排序
			
## 字典列表排序 students = [ {"name": "Stanley", "age": 22, "score" ...
 - 能够还原jQuery1.8的toggle的功能的插件
			
下面这个jQuery插件能够还原1.8的toggle的功能,如果你需要,可以直接把下面这段代码拷贝到你的jQuery里面,然后跟平时一样使用toggle的功能即可. //toggle plugin f ...
 - php源码建博客1--搭建站点-实现登录页面
			
主要: 站点搭建 实现登录页面 分析及改进 站点搭建 1) 在apache安装目录下: [conf\extra\httpd-vhosts.conf]加入站点配置 <VirtualHost *: ...
 - STM32F407+STemwin学习笔记之STemwin移植
			
原文链接:http://www.cnblogs.com/NickQ/p/8748011.html 环境:keil5.20 STM32F407ZGT6 LCD(320*240) STemwin:S ...
 - flask的查询,一对多,多对多
			
模型的关联: 一对多 class Role(db.Model): us = db.relationship('User',backref='role',lazy='dynamic') class Us ...
 - 实验吧web加了料的报错注入
			
知识点: SQL注入中用到的Concat函数详解 http://www.sohu.com/a/219966085_689961 http分割注入 直接根据提示,提交post请求的用户名和密码 结 ...
 - DOM中的事件傳播機制
			
要講到事件傳播機制之前,首先要瞭解的是 什麼是事件? 事件,發生在靜態頁面與動態行為之間的交互行為.是JavaScript 和 HTML的交互是通过事件实现的.比如,按鈕的點擊,鼠標的滑過,鍵盤的輸入 ...