/*省去了一些没注释的部分 只贴上一些注释的主要的部分 有问题还望指正*/
typedef int (init_fnc_t) (void);
//typedif 起到一个替换的作用,
//init_fnc_t *init_sequence[] = {,}这句话解析开来就是
//int (*init_sequence[]={})(void);
//定义了一个指向函数的指针数组,并且每个函数的返回值为int
//在下面的函数中 会依次调用这个数组里面的函数。关于这几个函数的分析见下篇博客。
int print_cpuinfo (void); /* test-only */
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 */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
dram_init, /* configure available RAM banks */
display_dram_config,
NULL,
};
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;//和上面一样,解析开就是一个指向函数的指针的指针
char *s;
#ifndef CFG_NO_FLASH
ulong size;
#endif
#if defined(CONFIG_VFD) || defined(CONFIG_LCD) //vfd也是一种显示器 和lcd不是一个类型而已
unsigned long addr;
#endif
/* Pointer is writable since we allocated a register for it */
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
//armboot_start 在start.s里面有定义,里面放的是start,这样gd就指向了gd——t的首地址
//gd_t结构体在include/asm-arm/global_data.h 定义,里面有个类型为bd_t的结构体*bd;
//gd也是在include/asm-arm/global_data.h这个文件中定义,如下
//#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
//这句意思是 定义gd,并在寄存器r8中保存gd。
//先把计算后的值强制变换成gd_t类型的指针,然后再赋给gd
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");
//百度一下这句话就能搜到,意思就是让目前cache里面的数据无效,因为你还不知道里面是什么数据。
memset ((void*)gd, 0, sizeof (gd_t));//这个函数有三个变量:a,b,c
// 从a地址开始把b写入,一共写c个字节,这里就是清零
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
//bd类型为bd_t,这个结构体里面放了一些板子的信息,如波特率,IP地址等等。和上面类似,bd->bd就指向了bd_t这个结构体的首地址
memset (gd->bd, 0, sizeof (bd_t)); //清零
monitor_flash_len = _bss_start - _armboot_start;//根据韦东山书p260的图可知这就是代码段的长度。
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
//挨个执行init_sequence指向的函数,里面的每个函数返回值都是0,hang是一个死循环,如过哪个返回不是0,说明出错。
}
#ifndef CFG_NO_FLASH //这里的flash是指norflash nand指nandflash。
/* configure available FLASH banks */
size = flash_init (); //初始化norflash 并返回大小
display_flash_config (size); //输出norflash的信息。
#endif /* CFG_NO_FLASH */
#ifdef CONFIG_VFD //一种显示器 暂时用不到
# ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# endif
/*
* reserve memory for VFD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
size = vfd_setmem (addr);
gd->fb_base = addr;
#endif /* CONFIG_VFD */
#ifdef CONFIG_LCD
# ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# endif
/*
* reserve memory for LCD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
//addr指向lcd memory的起始地址,这个地址是4K,也就是页对齐。
size = lcd_setmem (addr);
gd->fb_base = addr;//fb-base是显示器帧地址首地址
#endif /* CONFIG_LCD */
/* armboot_start is defined in the board-specific linker script */
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);//分配堆空间,并清零
#if (CONFIG_COMMANDS & CFG_CMD_NAND)//如果支持nandflash 初始化nand
puts ("NAND: ");
nand_init(); /* go init the NAND */
#endif
#ifdef CONFIG_HAS_DATAFLASH //应该用不到
AT91F_DataflashInit();
dataflash_print_info();
#endif
/* initialize environment */
env_relocate ();//重定向环境变量 为了加快访问速度,将环境变量从flash拷贝到sdram中去。
#ifdef CONFIG_VFD
/* must do this after the framebuffer is allocated */
drv_vfd_init();
#endif /* CONFIG_VFD */
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");//读取环境变量给bd结构体。
//getenv_IPaddr 就是在getenv的基础上多了一个数据格式转换
/* MAC Address 读mac地址给bd结构体 */
{
int i;
ulong reg;
char *s, *e;
char tmp[64];
i = getenv_r ("ethaddr", tmp, sizeof (tmp));//getenv_r 返回i=64 tmp为mac地址
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;
}
//如果使用第二块网卡 获取第二块网卡地址并给bd结构体
#ifdef CONFIG_HAS_ETH1
i = getenv_r ("eth1addr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
#endif
}
devices_init (); /* 对IIC 键盘 声卡等一些设备初始化 */
#ifdef CONFIG_CMC_PU2 //应该不用
load_sernum_ethaddr ();
#endif /* CONFIG_CMC_PU2 */
jumptable_init ();
/*
上面是初始化跳转表,所谓跳转表,就是给gd结构体的jt赋值,以后调用jt【】就是调用这些函数。下面只是截取 了一部分,这个函数在commen/export.c
gd->jt[XF_get_version] = (void *) get_version;
gd->jt[XF_malloc] = (void *) malloc;
gd->jt[XF_free] = (void *) free;
gd->jt[XF_getenv] = (void *) getenv;
gd->jt[XF_setenv] = (void *) setenv;
gd->jt[XF_get_timer] = (void *) get_timer;
gd->jt[XF_simple_strtoul] = (void *) simple_strtoul;
*/
console_init_r (); /* fully init console as a device */
#if defined(CONFIG_MISC_INIT_R) //应该不用
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif
/* enable exceptions */
enable_interrupts ();
/* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_CS8900
cs8900_get_enetaddr (gd->bd->bi_enetaddr);//网卡 目前还没仔细看
#endif
#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
if (getenv ("ethaddr")) {
smc_set_mac_addr(gd->bd->bi_enetaddr);
}
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);//如果环境变量里面有loadaddr 则使用它
}
#if (CONFIG_COMMANDS & CFG_CMD_NET) //如果支持网络
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));//把文件名字给bootfile这个全局变量
}
#endif /* CFG_CMD_NET */
#ifdef BOARD_LATE_INIT
board_late_init ();//根据不同情况,继续初始化一些硬件,这个函数应该要自己写,因//为只找到 他的声明,没有找到实现
#endif
#if (CONFIG_COMMANDS & CFG_CMD_NET)//
#if defined(CONFIG_NET_MULTI)
puts ("Net: ");
#endif
eth_initialize(gd->bd);//网卡的东西 还没有仔细看
#endif
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();//在commen目录下main.c文件
}
/* NOTREACHED - no way out of command loop except booting */
}
void hang (void)
{
puts ("### ERROR ### Please RESET the board ###\n");
for (;;);
}
文章评论(0条评论)
登录后参与讨论