uboot源码学习(11)u-boot初始化之board_init_f函数分析

一、在DDR初始化时,是由start.S中第155行

bl	cpu_init_crit

再跳转到第356行:

ENTRY(cpu_init_crit)
	b	lowlevel_init		@ go setup pll,mux,memory
ENDPROC(cpu_init_crit)

去到lowlevel_init.S文件初始化的,现在重新返回

bl	cpu_init_crit

执行之后的代码。

start.S第158行开始:

/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
	ldr	r0,=0x00000000
	bl	board_init_f
/*------------------------------------------------------------------------------*/

其中:

	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */

这两句是为了初始化堆栈,给c函数准备一个临时堆栈。因为后面要执行的函数 board_init_f 是一个c函数。c函数在调用之前必须先初始化堆栈,才能存入参数以及函数的局部变量。

bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */

这句代码的含义是:
将sp保存的地址向8个字节对齐,即可以被8整除。比如,sp保存的地址是0x80000013,经过此句代码后,就会把后三位不能被8整除的部分清0,得到0x80000000。

	ldr	r0,=0x00000000
	bl	board_init_f

r0一般放c函数的第一个传参。即将0x00000000当作第一个参数传给board_init_f函数。
board_init_f函数在\arm\arch\lib\board.c文件中定义。

通过arm-linux-objdump -S u-boot > dumpview.txt,查看u-boot中各个函数的地址,确认编译后board_init_f函数是否在前16K的范围内:
起始地址:34800000。
board_init_f函数地址:34801ccc。 0x1ccc=7372,所以在16K范围内。

二、board_init_f函数
board.c268-273行

void board_init_f(ulong bootflag)
{
	bd_t *bd;
	init_fnc_t **init_fnc_ptr;
	gd_t *id;
	ulong addr, addr_sp;

其中,bd_t 是一个结构体,存放板子的一些特性,波特率,ID以及DDR的起始地址和大小等,定义为:

typedef struct bd_info {
    int			bi_baudrate;	/* serial console baudrate */
    ulong	        bi_arch_number;	/* unique id for this board */
    ulong	        bi_boot_params;	/* where this board expects params */
	unsigned long	bi_arm_freq; /* arm frequency */
	unsigned long	bi_dsp_freq; /* dsp core frequency */
	unsigned long	bi_ddr_freq; /* ddr frequency */
    struct				/* RAM configuration */
    {
	ulong start;		//表示DDR的起始地址
	ulong size;			//表示DDR的大小
    }			bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;

gd_t 也是一个结构体,定义:

typedef	struct	global_data {
	bd_t		*bd;
	unsigned long	flags;
	unsigned long	baudrate;
	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	fb_base;	/* base address of frame buffer */
#ifdef CONFIG_FSL_ESDHC
	unsigned long	sdhc_clk;
#endif
#ifdef CONFIG_AT91FAMILY
	/* "static data" needed by at91's clock.c */
	unsigned long	cpu_clk_rate_hz;
	unsigned long	main_clk_rate_hz;
	unsigned long	mck_rate_hz;
	unsigned long	plla_rate_hz;
	unsigned long	pllb_rate_hz;
	unsigned long	at91_pllb_usb_init;
#endif
#ifdef CONFIG_ARM
	/* "static data" needed by most of timer.c on ARM platforms */
	unsigned long	timer_rate_hz;
	unsigned long	tbl;
	unsigned long	tbu;
	unsigned long long	timer_reset_value;
	unsigned long	lastinc;
#endif
#ifdef CONFIG_IXP425
	unsigned long	timestamp;
#endif
	unsigned long	relocaddr;	/* Start address of U-Boot in RAM */
	phys_size_t	ram_size;	/* RAM size */
	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;
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
	unsigned long	tlb_addr;
#endif
	const void	*fdt_blob;	/* Our device tree, NULL if none */
	void		**jt;		/* jump table */
	char		env_buf[32];	/* buffer for getenv() before reloc. */
#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
} gd_t;

#include 

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

#endif /* __ASM_GBL_DATA_H */

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")
//这个宏在include/global_data.h中。在board.c中27行声明了此宏。
//此句含义是:此全局变量使用频繁,故将其放在寄存器r8中。宏定义DECLARE_GLOBAL_DATA_PTR为gd_t* gd,
//将它设为register volitile类型,防止CPU对其优化,并将其放在寄存器r8中.

board.c 274-276行:

#ifdef CONFIG_PRAM
	ulong reg;
#endif

其中CONFIG_PRAM,如果有定义的话会在include/configs/s5p_goni.h文件中。以CONFIG_打头的宏定义一般都是和板子有关的宏定义,都在此文件中定义。和系统有关的宏定义一般都以CONFIG_SYS开头。此DEMO中,该宏未声明。

你可能感兴趣的:(Uboot,golang,开发语言,后端)