u-boot 的 init_sequence解析

    start_armboot (void)是u-boot开始执行的第一个C函数,该 函数自然要进行各种初始化工作,而init_sequence则是进行各种初始化的 函数数组,该函数定义在/lib_arm/board.c中,如下所示:

typedef int (init_fnc_t) (void);    //init_fnc_t就是个返回值为int的函数,参数为空

init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
	arch_cpu_init,		/* basic arch cpu dependent setup */
#endif
	board_init,		/* basic board dependent setup */
#if defined(CONFIG_USE_IRQ)
	interrupt_init,		/* set up exceptions */
#endif
	timer_init,		/* initialize timer */
	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
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
	init_func_i2c,
#endif
	dram_init,		/* configure available RAM banks */
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
	arm_pci_init,
#endif
	display_dram_config,
	NULL,
};

    这些配置宏定义(CONFIG_xxx)一般在要移值的开发板的头文件里,比如/include/configs/mx28_evk.h中,去掉这些条件编译,该指针数组为:

init_fnc_t *init_sequence[] = {
	arch_cpu_init,		/* basic arch cpu dependent setup */
	board_init,		/* basic board dependent setup */
	timer_init,		/* initialize timer */
	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 */
	print_cpuinfo,		/* display cpu info (and speed) */
	init_func_i2c,
	dram_init,		   /* configure available RAM banks */
	display_dram_config,
	NULL,
};

下面就逐个分析上述包含的初始化函数:

1、arch_cpu_init,        /* basic arch cpu dependent setup */

//mx28/generic.c
//对cache的使能,寄存器层面,freescale官方提供
int arch_cpu_init(void)
{
	icache_enable();
	dcache_enable();

	return 0;
}


2、board_init,        /* basic board dependent setup */

//mx28/mx28_evk.c
//给gd->bd赋值,2个要传递给linux的参数:CPU架构,bi_boot_params
//bi_boot_params:表示传递给内核的参数位置
//初始化nand flash接口
//初始化看门狗
int board_init(void)
{
	/* Will change it for MX28 EVK later */
	gd->bd->bi_arch_number = MACH_TYPE_MX28EVK;
	/* Adress of boot parameters */
	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;

	setup_gpmi_nand();

	//watch dog init
    pin_set_type(PINID_GPMI_RDY1, PIN_GPIO);
    pin_gpio_direction(PINID_GPMI_RDY1, 1);
    pin_gpio_set(PINID_GPMI_RDY1, 0);

	return 0;
}


3、timer_init,        /* initialize timer */

//mx28/timer.c
//定时器初始化,freescale厂家提供
int timer_init(void)
{
	/*
	 * Reset Timers and Rotary Encoder module
	 */

	/* Clear SFTRST */
	REG_CLR(REGS_TIMROT_BASE, HW_TIMROT_ROTCTRL, 1 << 31);
	while (REG_RD(REGS_TIMROT_BASE, HW_TIMROT_ROTCTRL) & (1 << 31))
		;

	/* Clear CLKGATE */
	REG_CLR(REGS_TIMROT_BASE, HW_TIMROT_ROTCTRL, 1 << 30);

	/* Set SFTRST and wait until CLKGATE is set */
	REG_SET(REGS_TIMROT_BASE, HW_TIMROT_ROTCTRL, 1 << 31);
	while (!(REG_RD(REGS_TIMROT_BASE, HW_TIMROT_ROTCTRL) & (1 << 30)))
		;

	/* Clear SFTRST and CLKGATE */
	REG_CLR(REGS_TIMROT_BASE, HW_TIMROT_ROTCTRL, 1 << 31);
	REG_CLR(REGS_TIMROT_BASE, HW_TIMROT_ROTCTRL, 1 << 30);

	/*
	* Now initialize timer
	*/

	/* Set fixed_count to 0 */
	REG_WR(REGS_TIMROT_BASE, HW_TIMROT_FIXED_COUNTn(N), 0);

	/* set UPDATE bit and 1Khz frequency */
	REG_WR(REGS_TIMROT_BASE, HW_TIMROT_TIMCTRLn(N),
		BM_TIMROT_TIMCTRLn_RELOAD | BM_TIMROT_TIMCTRLn_UPDATE |
		BV_TIMROT_TIMCTRLn_SELECT__1KHZ_XTAL);

	/* Set fixed_count to maximal value */
	REG_WR(REGS_TIMROT_BASE, HW_TIMROT_FIXED_COUNTn(N), TIMER_LOAD_VAL);

	/* init the timestamp and lastdec value */
	reset_timer_masked();

	return 0;
}


4、env_init,        /* initialize environment */

//u-boot环境参数初始化
//将u-boot默认支持的环境参数指针赋值给gd->env_addr
int  env_init(void)
{
	gd->env_addr  = (ulong)&default_environment[0];
	gd->env_valid = 0;

	return (0);
}


5、init_baudrate,        /* initialze baudrate settings */

///lib_arm/board.c
//波特率初始化,主要是对bd->bi_baudrate的初始化赋值
//判断环境参数baudrate的值,如果不为0,则取env的值
//反之则取移值板子头文件mx28_evk.h中的默认配置宏定义CONFIG_BAUDRATE
//这里很显然取值为 CONFIG_BAUDRATE  115200
static int init_baudrate (void)
{
	char tmp[64];	/* long enough for environment variables */
	int i = getenv_r ("baudrate", tmp, sizeof (tmp));
	gd->bd->bi_baudrate = gd->baudrate = (i > 0)
			? (int) simple_strtoul (tmp, NULL, 10)
			: CONFIG_BAUDRATE;

	return (0);
}


6、serial_init,        /* serial communications setup */

///cpu/arm926ejs/mx28/serial.c
//串口的初始化,主要是对调试串口的初始化,也是能实现整个运行信息打印
int serial_init(void)
{
	/*Config the AUART0_CTS/RTS as the DUART.RX/TX*/
	//lolevel_init.s config the duart functin
//	pin_set_type(PINID_PWM0, PIN_FUN2);
//	pin_set_type(PINID_PWM1, PIN_FUN2);
//	pin_set_type(PINID_AUART0_CTS, PIN_FUN3);
//	pin_set_type(PINID_AUART0_RTS, PIN_FUN3);	
	
	/* Disable UART */
	REG_WR(REGS_UARTDBG_BASE, HW_UARTDBGCR, 0);

	/* Mask interrupts */
	REG_WR(REGS_UARTDBG_BASE, HW_UARTDBGIMSC, 0);

	/* Set default baudrate */
	serial_setbrg();

	/* Enable UART */
	REG_WR(REGS_UARTDBG_BASE, HW_UARTDBGCR,
		BM_UARTDBGCR_TXE | BM_UARTDBGCR_RXE | BM_UARTDBGCR_UARTEN);
	return 0;
}


7、console_init_f,        /* stage 1 init of console */

///common/console.c
/* Called before relocation - use serial functions */
// have_console = 1 表明将串口作为控制台的输入输出设备
int console_init_f(void)
{
	gd->have_console = 1;

#ifdef CONFIG_SILENT_CONSOLE
	if (getenv("silent") != NULL)
		gd->flags |= GD_FLG_SILENT;
#endif

	return 0;
}


8、display_banner,        /* say that we are here */

//lib/board.c
//显示debug信息,比如各种开始地址等。
static int display_banner (void)
{
	printf ("\n\n%s\n\n", version_string);
	debug ("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",
	       _armboot_start, _bss_start, _bss_end);
#ifdef CONFIG_MODEM_SUPPORT
	debug ("Modem Support enabled\n");
#endif
#ifdef CONFIG_USE_IRQ
	debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
	debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
#endif

	return (0);
}


9、print_cpuinfo,        /* display cpu info (and speed) */

//cpu/arm926ejs/mx28/generic.c
//打印cpu的各种信息,比如cpu时钟、cpu生产商信息等。
int print_cpuinfo(void)
{
	printf("Freescale i.MX28 family\n");
	printf("CPU:   %d MHz\n", mx28_get_pclk());
	printf("BUS:   %d MHz\n", mx28_get_hclk());
	printf("EMI:   %d MHz\n", mx28_get_emiclk());
	printf("GPMI:   %d MHz\n", mx28_get_gpmiclk());
	return 0;
}


10、init_func_i2c

///lib_arm/board.c
//初始化I2C接口,对各种I2C接口
static int init_func_i2c (void)
{
	puts ("I2C:   ");
	i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
	puts ("ready\n");
	return (0);
}


11、dram_init,           /* configure available RAM banks */

//board/freescale/mx28_evk.c
//这里不是对内存设备的初始化,因为freescale已经有了SDRAM_Prep,
//这里是对 全局变量 gd->bd-bi_dram[0]的初始化,这个是要传递给内核kernel的
//bi_dram[0]是一个结构体,包含了内存起始地址和、内存大小
//zlg移值为了兼容性,所以支持2种内存大小。
int dram_init(void)
{
	int iSizeMb = ddr2SizeDetect();         //Modify by zhangzhanwei

       	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;

	//Modify by zhangzhanwei
	if (iSizeMb == 128) {
		gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
	} else {
		gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE >> 1;
	}

	return 0;
}


12、display_dram_config,

//lib_arm/board.c
//打印显示DRAM的配置信息
static int display_dram_config (void)
{
	int i;

#ifdef DEBUG
	puts ("RAM Configuration:\n");

	for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
		printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
		print_size (gd->bd->bi_dram[i].size, "\n");
	}
#else
	ulong size = 0;
	for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
		size += gd->bd->bi_dram[i].size;
	}
	puts("DRAM:  ");
	print_size(size, "\n");
#endif

	return (0);
}

小结:从上可知,上述多数初始化函数还是要求 移值者去编写对应的具体函数的,这也是“移值”的本质,也就是u-boot提供整体框架和各种函数,而移值者根据具体情况编写对应的函数。比如在freescale中,移值主要的工作是要编写2个文件夹中的文件,分别为/board/freescale/mx28和/cpu/arm926ejs/mx28,当然也少不了/include/configs/mx28_evk.h 这个重要的配置头文件,前者是上述函数的实现,后者则是参数、函数编译等配置头文件。

def encode(self, source_padded: torch.Tensor, source_lengths: List[int]) -> Tuple[ torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: enc_hiddens, dec_init_state = None, None """ add your code here -- 5 目标: 1. 将编码器应用于源句子以获得编码器的隐藏状态。 2. 将编码器的最终状态投射到解码器,以获得解码器的初始状态。 步骤: 1. 使用 self.model_embeddings 在 src sentences 上构建一个 Tensor `X`, shape (max_sent_len, batch_size, embedding_size) 注意, encoder和 decoder 不同, encoder是没有初始的 hidden state和cell state的. 2. 把 self.encoder 作用到 X 上 得到 `enc_hiddens`, `last_hidden`, `last_cell`. - 首先 使用 pack_padded_sequence 函数到 X 上, 把处理后的 Tensor 送进 self.encoder中. - 使用 pad_packed_sequence 函数到 enc_hiddens. - 注意: 编码器的输出是shape (max_src_sent_len, batch_size, hidden_size*2), 需要permute 成 (batch_size, max_src_sent_len, hidden_size*2) - 注意: 使用 pad_packed_sequence 时, batch 中的每一个元素应该是相同的shape 3. 获得解码器的初始状态: `dec_init_state` = (init_decoder_hidden, init_decoder_cell): - `init_decoder_hidden`: 解码器 初始hidden-state - 编码器的`last_hidden` 的 shape (2, batch_size, hidden_size), 因为编码器是双向的. - Concatenate 双向的hidden—state 得到 shape (batch_size, 2*hidden_size). - 使用 self.h_projection, 得到 init_decoder_hidden. - `init_decoder_cell`: 解码器 初始 cell-state - 编码器的`last_cell` 的 shape (2, batch_size, hidden_size), 因为编码器是双向的. - Concatenate 双向的hidden—state 得到 shape (batch_size, 2*hidden_size).. - 使用 self.c_projection 得到 init_decoder_cell.
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值