一、在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中,该宏未声明。