通过前面的分析,知道第2阶段代码主要是start_armboot,首先我们先介绍几个比较重要的结构体。这里主要是对start_armboot中的流程做具体的分析,我的uboot-2009-06.至于具体的代码分析将在后面的文章中介绍。
1.gd_t全局数据结构,主要保存了uboot的配置信息。include/asm-arm/global_data.h中定义:
typedef struct global_data {
bd_t *bd;//板子相关的结构体
unsigned long flags;//
unsigned long baudrate;//波特率
unsigned long have_console; /串口调用*/
unsigned long reloc_off; / Relocation Offset
重定位偏移*/
unsigned long env_addr; / 环境变量基址*/
unsigned long env_valid; / Checksum of
Environment valid? */
unsigned long fb_base; /帧缓冲基地址*/
#ifdef CONFIG_VFD
unsigned char vfd_type; / display type */
#endif
#if 0
unsigned long cpu_clk; / cpu频率!
*/
unsigned long bus_clk;/总线频率*/
phys_size_t ram_size; /RAM大小设置,64M*/
unsigned long reset_status; / 重新设置状态地址*/
#endif
void **jt; /
jump table 保存着些函数的入口地址,在common/Exports.c中进行填充*/
} gd_t;
#define
DECLARE_GLOBAL_DATA_PTR
register volatile gd_t *gd asm ("r8")
这个声明告诉编译器使用寄存器r8来存储gd_t类型的指针gd,即这个定义声明了一个指针,并且指明了它的存储位置。
register表示变量放在机器的寄存器
volatile用于指定变量的值可以由外部过程异步修改
这个指针在board.c中初始化。
2.bd_t板子数据结构体,主要保存与板子相关的信息。定义在include/asm-arm/u-boot.h中
typedef struct bd_info {
int bi_baudrate; / 串口频率*/
unsigned
long bi_ip_addr; /IP地址*/
struct
environment_s
*bi_env;环境变量指针
ulong
bi_arch_number; / 板子ID*/
ulong
bi_boot_params; / 启动参数存放地址*/
struct / RAM
configuration */
{
ulong start;
ulong size;
}
bi_dram[CONFIG_NR_DRAM_BANKS];//SDRAM的大小,此处的CONFIG_NR_DRAM_BANKS在smdk2410.h中宏定义
} bd_t;
3.初始化函数队列
typedef int (init_fnc_t) (void);定义函数指针;
下面是函数指针数组
init_fnc_t *init_sequence[] = {
cpu_init, /
CPU初始化,定义在cpu\arm920t\cpu.c*/
#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init,
/相关体系结构CPU初始化cpu/.../arch/cpu.c */
#endif
board_init, /
相关板子初始化board\sbc2410x\sbc2410.c*/
interrupt_init, /
中断初始化cpu\arm920t\ s3c24x0\interrupts.c*/
env_init, / 环境变量初始化*/
init_baudrate, / 初始化波特率*/
serial_init, *
串口初始化drivers\serial\serial.c*/
console_init_f, / stage 1 init
of console ???不知何意*/
display_banner, / say that we
are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, / 打印CPU信息
*/
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, / 显示板块信息*/
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,IIC初始化函数
#endif
dram_init, / configure
available RAM banks */
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
arm_pci_init,
#endif
display_dram_config,存储器件初始化
NULL,
}
OK现在开始分析start_armboot,这里只分析流程。
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;\\定义二级函数指针
char *s;
#if defined(CONFIG_VFD) ||
defined(CONFIG_LCD)\\如果定义了Lcd或者VFD,则指定帧缓冲的地址
unsigned long addr;
#endif
* Pointer is writable since we allocated a
register for it */
/定义了全局数据指针,见上1,_armboot_start的值位0x3ff80000,且CONFIG_SYS_MALLOC_LEN在smdk2410.h中定义,经过计算可知道config_sys_malloc_len大小为0x30000,sizeof(gd_t)=4+4*7+4=36=0x24.故gd所指向地址0x3ff80000-0x30000-0x24约为ox3ff50000*/
gd = (gd_t*)(_armboot_start -
CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
/下面这局话请参考内存屏障*/
__asm__ __volatile__("": : :"memory");
memset ((void*)gd, 0, sizeof (gd_t));
/对板块信息指针初始化*/
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
memset (gd->bd, 0, sizeof
(bd_t));
/设置当前uboot标志位已经重定位*/
gd->flags |= GD_FLG_RELOC;
monitor_flash_len = _bss_start -
_armboot_start;//uboot镜像文件大小
/初始化函数*/
for (init_fnc_ptr = init_sequence;
*init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
//flash初始化以及打印其信息
display_flash_config (flash_init ());
//malloc内存空间清零
mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN);
//如果定义了nandflash,则对nandflash初始化
#if defined(CONFIG_CMD_NAND)
puts ("NAND: ");
nand_init();
#endif
//环境初始化
env_relocate ();
serial_initialize();
//设置IP地址,以及设备初始化
gd->bd->bi_ip_addr = getenv_IPaddr
("ipaddr");
devices_init (); / get the devices list going.
*/
jumptable_init
();//初始化跳转表,对gd中的jt(函数跳转表)数组进行初始化,其中保存着一些函数的入口地址
console_init_r (); / fully init console as a device */
misc_init_r ();
//中断使能
enable_interrupts ();
//得到当前网卡物理地址
cs8900_get_enetaddr ();
//设置网卡
eth_initialize(gd->bd)
for (;;) {
main_loop ();
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fangbing007/archive/2009/10/03/4628402.aspx
|