void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;
char *s;
int mmc_exist = 0;
/*全局数据结构初始化*/
ulong gd_base;
gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);//全局变量地址
gd = (gd_t*)gd_base;
typedef struct global_data {
bd_t *bd;//板子数据指针
unsigned long flags;//指示标志,如设备已经初始化标志等
unsigned long baudrate;//串口波特率
unsigned long have_console; /* serial_init() was called,串口初始化标志 */
unsigned long reloc_off; /* Relocation Offset,重定位偏移,就是实际定向的位置与编译连接时指定的位置之差,一般为0 */
unsigned long env_addr; /* Address of Environment struct,环境参数地址 */
unsigned long env_valid; /* Checksum of Environment valid? 环境参数CRC检验有效标志*/
unsigned long fb_base; /* base address of frame buffer,base address of frame buffe */
void **jt; /* jump table,跳转表 */
} gd_t;
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");
memset ((void*)gd, 0, sizeof (gd_t));//全局变量清零
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));//板子数据变量地址
typedef struct bd_info {
int bi_baudrate; /* serial console baudrate,串口波特率 */
unsigned long bi_ip_addr; /* IP Address,IP地址 */
unsigned char bi_enetaddr[6]; /* Ethernet adress,MAC地址 */
struct environment_s *bi_env;/*环境变量开始地址*/
ulong bi_arch_number; /* unique id for this board,板子唯一ID */
ulong bi_boot_params; /* where this board expects params,启动参数 */
struct /* RAM configuration,RAM配置 */
{
ulong start;
ulong size;
} bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;
typedef struct environment_s
{
unsigned long crc;
#ifdef CFG_REDUNDAND_ENVIRONMENT
unsigned char flags;
#endif
unsigned char data[ENV_SIZE];
} env_t;
memset (gd->bd, 0, sizeof (bd_t));//板子数据清零
monitor_flash_len = _bss_start - _armboot_start;//取boot长度
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
init_fnc_t *init_sequence[] = {
cpu_init, /* basic cpu dependent setup,基本的处理器相关配置 */
board_init, /* basic board dependent setup,基本的板级相关配置 */
interrupt_init, /* set up exceptions,初始化中断 */
env_init, /* initialize environment, 初始化环境变量 */
init_baudrate, /* initialze baudrate settings,初始化波特率设置 */
serial_init, /* serial communications setup,串口通讯设置 */
console_init_f, /* stage 1 init of console,控制台初始化阶段 */
display_banner, /* say that we are here, 打印u-boot信息 */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info,显示板子信息 */
#endif
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init, /* configure available RAM banks,配置可用的RAM */
display_dram_config,//显示RAM的配置大小
NULL,
};
void hang (void)
{
puts ("### ERROR ### Please RESET the board ###\n");
for (;;);
}
size = flash_init (); //配置可用flash
typedef struct {
ulong size; /* total bank size in bytes */
ushort sector_count; /* number of erase units */
ulong flash_id; /* combined device & manufacturer code */
ulong start[CFG_MAX_FLASH_SECT]; /* physical sector start addresses */
uchar protect[CFG_MAX_FLASH_SECT]; /* sector protection status */
#ifdef CFG_FLASH_CFI
uchar portwidth; /* the width of the port */
uchar chipwidth; /* the width of the chip */
ushort buffer_size; /* # of bytes in write buffer */
ulong erase_blk_tout; /* maximum block erase timeout */
ulong write_tout; /* maximum write timeout */
ulong buffer_write_tout; /* maximum buffer write timeout */
ushort vendor; /* the primary vendor id */
ushort cmd_reset; /* vendor specific reset command */
ushort interface; /* used for x8/x16 adjustments */
ushort legacy_unlock; /* support Intel legacy (un)locking */
uchar manufacturer_id; /* manufacturer id */
ushort device_id; /* device id */
ushort device_id2; /* extended device id */
ushort ext_addr; /* extended query table address */
ushort cfi_version; /* cfi version */
ushort cfi_offset; /* offset for cfi query */
ulong addr_unlock1; /* unlock address 1 for AMD flash roms */
ulong addr_unlock2; /* unlock address 2 for AMD flash roms */
const char *name; /* human-readable name */
#endif
} flash_info_t; //flash信息结构体
ulong flash_init (void)
{
int i, j;
ulong size = 0;
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
ulong flashbase = 0;
flash_info[i].flash_id = (MX_MANUFACT & FLASH_VENDMASK) | (MX_ID_LV640EB & FLASH_TYPEMASK);//flash_info[0].flash_id =0;
flash_info[i].size = FLASH_BANK_SIZE; //flash_info[0].size = 8M;
flash_info[i].sector_count = CFG_MAX_FLASH_SECT; //flash_info[i].sector_count =135;
memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); //清零
if (i == 0)
flashbase = CFG_FLASH_BASE; //flash基地址0x80000000
else
panic ("configured too many flash banks!\n");
for (j = 0; j < flash_info[i].sector_count; j++) {
#if defined(CONFIG_MX_LV640EB)
if (j <=7) { /* 1st ~ 8th sect size : 8 kb */
flash_info[i].start[j] = flashbase + j * BOOT_SECT_SIZE;
} else { /* 9th ~ 135th sect size : 64 kb */
flash_info[i].start[j] = flashbase + (j - 7) * MAIN_SECT_SIZE;
}
}
size += flash_info[i].size; //总大小
}
flash_protect (FLAG_PROTECT_SET,
CFG_FLASH_BASE,
CFG_FLASH_BASE + monitor_flash_len - 1,
&flash_info[0]);
flash_protect (FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
return size;
}
mem_malloc_init (CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE);//初始化堆空间
mmc_exist = mmc_initialize(gd->bd); //SD、MMC初始化
if (mmc_exist != 0);
nand_init(); //nand初始化
void nand_init(void)
{
nand_probe(CFG_NAND_BASE);
if (nand_dev_desc[0].ChipID != NAND_ChipID_UNKNOWN) {
print_size(nand_dev_desc[0].totlen, "\n");
}
}
/* initialize environment , 重新定位环境变量*/
env_relocate ();
void env_relocate (void)
{
DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__,
gd->reloc_off);
#ifdef ENV_IS_EMBEDDED
/*
* The environment buffer is embedded with the text segment,
* just relocate the environment pointer
*/
env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off);
DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
#endif
if (gd->env_valid == 0) {
set_default_env();
} else {
env_relocate_spec ();
}
gd->env_addr = (ulong)&(env_ptr->data);
}
serial_initialize(); //串口初始化
/*主要是从环境中读IP、MAC,然后赋给gd->bd对应域就OK*/
/* IP Address , 从环境变量中获取地址*/
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
/* MAC Address,从环境变量中获取IP地址 */
{
int i;
ulong reg;
char *s, *e;
char tmp[64];
i = getenv_r ("ethaddr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
}
/* 经过devices_init(),创建了devlist,但是只有一个串口设备注册在内。显然,devlist中的设备都是可以做为console的。*/
devices_init (); /* get the devices list going.设备初始化 */
int devices_init (void)
{
#ifndef CONFIG_ARM /* already relocated for current ARM implementation */
ulong relocation_offset = gd->reloc_off;
int i;
/* relocate device name pointers */
for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
relocation_offset);
}
#endif
/* Initialize the list */
devlist = ListCreate (sizeof (device_t)); //创建设备列表
if (devlist == NULL) {
eputs ("Cannot initialize the list of devices!\n");
return -1;
}
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);//初始化i2c接口,i2c没有注册到devlist中去
#endif
return (0);
}
jumptable_init (); //跳转初始化表
/*查看环境参数stdin,stdout,stderr中对标准IO的指定的设备名称,再按照环境指定的名称搜索devlist,将搜到的设备指针赋给标准IO数组stdio_devices[]。置gd->flag标志
console_init_r (); /* fully init console as a device, 完整地初始化控制台设备*/
/* enable exceptions ,使能外部中断,由于CONFIG_USE_IRQ没有定义,空实现*/
enable_interrupts ();
cs8900_get_enetaddr (gd->bd->bi_enetaddr); /*设置CS8900的MAC地址。*/
/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));
}
board_late_init ();
puts ("Net: ");
/*初始化以太网*/
eth_initialize(gd->bd);
debug ("Reset Ethernet PHY\n");
reset_phy();
puts("IDE: ");
ide_init();
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}