致远i.mx287开发板u-boot移值(三)start_armboot函数分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012351051/article/details/86601249

    接上述(二)分析,start.S进行关键 外围初始化后, 主要包括SDAM、调试串口、堆栈,代码搬迁后,会 跳转到start_armboot函数中,简单的总结是:

   (1)进行各种板级初始化。

   (2)环境变量初始化。

   (3)Nand Flash初始化,这里还是有点存疑的,因为采用Nand flash进行存储代码的话,CPU上电后,有一个内部RAM,不大,有的是4K,有的是更大,CPU会将内部RAM的地址映射为0,而且会自动的与Nand Flash进行通信,将4K或者更多的代码,先自动搬迁到内部RAM中执行,这是必然的,要不然程序如何去执行,从这一点来看,这部分的nand flash读驱动,是CPU自带的,但是我们目前只能理解为这个读驱动,厂家是没有对用户开放的,如果用户想要做nand flash的读写,是需要用户自己去编写nand flash初始化驱动的。

   (4) 以太网接口初始化。

    (5)其他硬件初始化。

    (6)进入main_loop循环执行,这个main_loop是无法自己跳出的,除非boot,也是在这个步骤进行u-boot的  

各种命令执行,当然也包括,引导 选项去kernel,

     去掉编译条件后,分析如下:

void start_armboot (void)
{
	init_fnc_t **init_fnc_ptr;    //初始化函数数组指针,包含了很多初始化函数
	char *s;
    //init_fnc_ptr指向init_sequence,包含板子初始化、环境变量、控制台等初始化

	unsigned long addr;

	/* Pointer is writable since we allocated a register for it */
	gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
	/* compiler optimization barrier needed for GCC >= 3.4 */
	__asm__ __volatile__("": : :"memory");
    //gd为u-boot中定义的全局变量,这个变量是一个结构体,用于程序间的同步
    //主要包含板级参数指针,代码搬迁标志、波特率、重定位补偿值、环境变量地址等
    //先初始化gd,即清空
	memset ((void*)gd, 0, sizeof (gd_t));
	gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
	memset (gd->bd, 0, sizeof (bd_t));
    
	gd->flags |= GD_FLG_RELOC;
    //u-boot镜像大小
	monitor_flash_len = _bss_start - _armboot_start;
    //各种外围初始化执行
	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
		if ((*init_fnc_ptr)() != 0) {
			hang ();
		}
	}

	/* armboot_start is defined in the board-specific linker script */
	mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN);


	/* bss_end is defined in the board-specific linker script */
	addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
	vfd_setmem (addr);
	gd->fb_base = addr;



	/* board init may have inited fb_base */
	if (!gd->fb_base) {
		/*
		 * 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);
		lcd_setmem (addr);
		gd->fb_base = addr;
	}


    //NAND Flash初始化,会有对应的输出信息
	puts ("NAND:  ");
	nand_init();		/* go init the NAND */
    //onenand初始化
	onenand_init();


	AT91F_DataflashInit();
	dataflash_print_info();
    //mmc初始化
	puts ("MMC:   ");
	mmc_initialize (gd->bd);

	//初始化环境变量
	env_relocate ();
	/* must do this after the framebuffer is allocated */
	drv_vfd_init();

	serial_initialize();

	//此处是致远电子自己修改增加的一个初始化函数,主要是为了自动识别
    //sdram的大小,来区别他们的开发板型号,因为他们有283,还有287
	getddr2_information();

	/* IP Address */
	gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

	stdio_init ();	/* get the devices list going. */

	jumptable_init ();

	/* Initialize API */
	api_init ();

	console_init_r ();	/* fully init console as a device */

    //一些通用标准的外围初始化
	/* miscellaneous arch dependent initialisations */
	arch_misc_init ();
	/* miscellaneous platform dependent initialisations */
	misc_init_r ();

    //使能中断
	/* enable exceptions */
	enable_interrupts ();
    //以太网初始化
	/* Perform network card initialisation if necessary */
	/* XXX: this needs to be moved to board init */
extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
	if (getenv ("ethaddr")) {
		uchar enetaddr[6];
		eth_getenv_enetaddr("ethaddr", enetaddr);
		davinci_eth_set_mac_addr(enetaddr);
	}

	cs8900_get_enetaddr ();

	/* XXX: this needs to be moved to board init */
	if (getenv ("ethaddr")) {
		uchar enetaddr[6];
		eth_getenv_enetaddr("ethaddr", enetaddr);
		smc_set_mac_addr(enetaddr);
	}

	extern void enc_set_mac_addr (void);
	enc_set_mac_addr ();

	/* 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 ();

	check_recovery_mode();

	puts ("Net:   ");
	eth_initialize(gd->bd);
	debug ("Reset Ethernet PHY\n");
	reset_phy();
    //进入main_loop循环,
	/* main_loop() can return to retry autoboot, if so just run it again. */
	for (;;) {
		main_loop ();
	}
    //一旦进入main_loop函数后,是无法跳出的,除非重新boot
	/* NOTREACHED - no way out of command loop except booting */
}

猜你喜欢

转载自blog.csdn.net/u012351051/article/details/86601249