嵌入式开发(S5PV210)——u-boot中如何确定启动方式

1、嵌入式设备确认启动方式

设备确认启动方式分为硬件方式和软件方式,硬件方式是通过芯片某几个引脚的高低电平来决定启动方式;软件方式就是通过代码设置来决定启动方式。
(1)硬件方式:比如S5PV210芯片,通过拨码开关去设置芯片引脚的高低电平来设置启动方式,要改启动方式必须要硬件上进行设置,芯片在启动时检查引脚的电平从而决定去何种启动介质中读取启动代码;
(2)软件方式:比如X86架构的芯片用bios启动,在设备启动时进入bios界面,可以修改启动顺序。PC电脑也是用的bios,感兴趣可以去看看关于启动顺序的设置。

2、uboot中对启动方式的判断

2.1、汇编部分代码

		/* 读取启动方式,也就是读取om引脚的状态*/
        ldr	r0, =PRO_ID_BASE
        ldr	r1, [r0,#OMR_OFFSET]
        bic	r2, r1, #0xffffffc1
		
		/* NAND BOOT */
		省略掉NAND BOOT部分的判断

		/* SD/MMC BOOT */
		cmp     r2, #0xc
		moveq   r3, #BOOT_MMCSD	

		/* NOR BOOT */
		cmp     r2, #0x14
		moveq   r3, #BOOT_NOR
		
		/* Uart BOOTONG failed */
		cmp     r2, #(0x1<<4)
		moveq   r3, #BOOT_SEC_DEV
		
		/*将r3寄存器的值保存到[INF_REG_BASE+INF_REG3_OFFSET]地址处*/
		ldr	r0, =INF_REG_BASE
		str	r3, [r0, #INF_REG3_OFFSET]  
		
		#if defined(CONFIG_EVT1)
		/* If BL1 was copied from SD/MMC CH2 */
		ldr	r0, =0xD0037488
		ldr	r1, [r0]
		ldr	r2, =0xEB200000
		cmp	r1, r2
		beq     mmcsd_boot
		#endif

		ldr	r0, =INF_REG_BASE
		ldr	r1, [r0, #INF_REG3_OFFSET]
		cmp	r1, #BOOT_NAND		/* 0x0 => boot device is nand */
		beq	nand_boot
		cmp	r1, #BOOT_ONENAND	/* 0x1 => boot device is onenand */
		beq	onenand_boot
		cmp     r1, #BOOT_MMCSD
		beq     mmcsd_boot
		cmp     r1, #BOOT_NOR
		beq     nor_boot
		cmp     r1, #BOOT_SEC_DEV
		beq     mmcsd_boot
		mmcsd_boot:
		bl      movi_bl2_copy
		b       after_copy

1.读取[PRO_ID_BASE+ OMR_OFFSET]地址处的数据,然后取bit1-bit5赋值给r2;(假设r2的值是0xc,SD卡启动方式)
2.将r2做比较从而判断当前是哪种启动方式,于是得知当前是 SD/MMC BOOT,r3=#BOOT_MMCSD;
3.将r3的数据写到[INF_REG_BASE+INF_REG3_OFFSET]地址处保存起来;
4.将0xD0037488地址处的数据读取出来,如果值为0xEB200000就跳转到mmcsd_boot处执行,跳过后面的步骤;
5.将第三步保存在[INF_REG_BASE+INF_REG3_OFFSET]地址处的数据读取出来保存在r1;
6.r1的值为#BOOT_MMCSD,于是最终跳转到mmcsd_boot处执行;
7.movi_bl2_copy是一个C语言函数,主要作用就是重定位BL2;
8.after_copy就是启动代码的剩余部分;

2.2、特殊地址[PRO_ID_BASE+ OMR_OFFSET]

[PRO_ID_BASE+ OMR_OFFSET]=0xE0000004,是一个寄存器的地址,该寄存器的值是硬件根据OM引脚的设置而自动填充的,这个值反映的是OM引脚的接法,也就是当前我们选择的启动介质是什么。通过判断该寄存器的bit1-bit5就可以知道该去何种启动介质读取启动代码。

2.3、特殊地址[D0037488]和[0xD0037F98]

这两个地址是SD卡启动相关的,参考博客《ARM芯片开发(S5PV210芯片)——SD卡启动》

2.4、movi_bl2_copy函数详解

typedef u32(*copy_sd_mmc_to_mem)(u32 channel, u32 start_block, u16 block_size, u32 *trg, u32 init);

void movi_bl2_copy(void)
{
    
    
	ulong ch;
	ch = *(volatile u32 *)(0xD0037488);
	copy_sd_mmc_to_mem copy_bl2 =
	    (copy_sd_mmc_to_mem) (*(u32 *) (0xD0037F98));

	#if defined(CONFIG_SECURE_BOOT)
	ulong rv;
	#endif

	u32 ret;
	if (ch == 0xEB000000) {
    
    
		ret = copy_bl2(0, MOVI_BL2_POS, MOVI_BL2_BLKCNT,
			CFG_PHY_UBOOT_BASE, 0);
	}
	else if (ch == 0xEB200000) {
    
    
		ret = copy_bl2(2, MOVI_BL2_POS, MOVI_BL2_BLKCNT,
			CFG_PHY_UBOOT_BASE, 0);
	}
	else
		return;

	if (ret == 0)
		while (1);
	else
		return;
}

该函数作用是重定位bl2:
1.将0xD0037488地址处的数据赋值给ch,;
2.将0xD0037F98强制转换成函数指针,这是从SD/MMC中拷贝数据到内存的函数;
3.通过比较ch的值判断出当前是从SD卡通道2还是通道0启动,从而去对应的通道读取数据;
4.copy_bl2函数功能就是从SD卡某个通道的某个扇区开始读取n个块到某个地址处,具体都可以在函数参数里指定。

Guess you like

Origin blog.csdn.net/weixin_42031299/article/details/120983884