2022版u-boot启动分析笔记之二(

2022版u-boot启动分析笔记之二(,第1张

2022版u-boot启动分析笔记之二(

u-boot-2022.01-rc4启动分析笔记之二(_main与board_init_f)
  • U-Boot启动流程概要
  • 跳转到_main
  • 跳转到board_init_f
    • do_lowlevel_init()
      • 修改set_ps_hold_ctrl
    • copy_uboot_to_ram()
      • 分析修改spl_boot.c的原因
      • 修改arch/arm/mach-exynos/spl_boot.c支持copy_uboot_to_ram
    • (*uboot)();

U-Boot启动流程概要

2022版u-boot启动分析笔记之一(start.S与lowlevel_init.S)

跳转到_main

_main函数在arch/arm/lib/crt0.S中,没有需要移植的。main函数的作用在注释中有详细的说明,可以自己翻译:

 
跳转到board_init_f 

移植uboot先做一个最精简版本,很多配置选项都没有打开,比如fb mmc等硬件都默认不打开,只配置基本的ddr serial,这样先保证uboot能正常启动进入命令行,然后再去添加其他。

我们这里分析就是按最精简版本来,这样可以更加简洁的说明uboot的启动流程。

在arch/arm/lib/目录下有spl.c,其中定义了弱函数board_init_f(),是空函数,代码如下:

void __weak board_init_f(ulong dummy)
{
}

在arch/arm/mach-exynos/目录下的spl_boot.c中,定义了函数board_init_f(),board_init_f()函数主要是根据配置对全局信息结构体gd进行初始化。代码如下:

static void setup_global_data(gd_t *gdp)
{
	set_gd(gdp);
	memzero((void *)gd, sizeof(gd_t));
	gd->flags |= GD_FLG_RELOC;
	gd->baudrate = CONFIG_BAUDRATE;
	gd->have_console = 1;
}
void board_init_f(unsigned long bootflag)
{
	__aligned(8) gd_t local_gd;
	__attribute__((noreturn)) void (*uboot)(void);

	setup_global_data(&local_gd);

	if (do_lowlevel_init())
		power_exit_wakeup();

	copy_uboot_to_ram();

	
	uboot = (void *)CONFIG_SYS_TEXT_base;
	(*uboot)();
	
}
do_lowlevel_init()

在arch/arm/mach-exynos/目录下的lowlevel_init.c中,定义了do_lowlevel_init(void)函数,代码如下:

int do_lowlevel_init(void)
{
	uint32_t reset_status;
	int actions = 0;

	arch_cpu_init();

	reset_status = get_reset_status();

	switch (reset_status) {
	case S5P_CHECK_SLEEP:
		actions = DO_CLOCKS | DO_WAKEUP;
		break;
	case S5P_CHECK_DIDLE:
	case S5P_CHECK_LPA:
		actions = DO_WAKEUP;
		break;
	default:
		
		actions = DO_CLOCKS | DO_MEM_RESET | DO_POWER;
	}

	if (actions & DO_POWER)
		set_ps_hold_ctrl();

	if (actions & DO_CLOCKS) {
		system_clock_init();
#ifdef CONFIG_DEBUG_UART
#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL)) || 
    !defined(CONFIG_SPL_BUILD)
    
#ifdef CONFIG_CBT4412
		exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE);
#else
		exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
#endif		
		debug_uart_init();
#endif
#endif
		mem_ctrl_init(actions & DO_MEM_RESET);
		tzpc_init();
	}

	return actions & DO_WAKEUP;
}

1)get_reset_status()函数获取复位之后的状态.该函数在archarmmach-exynospower.c中定义。

2)判断复位的类型1

复位分为多种情况,如冷启动、休眠唤醒等。
判断复位类型的意义在于:冷启动需要重新初始化DDR,而休眠唤醒不需要再次初始化DDR。

3)set_ps_hold_ctrl()拉高电源管理芯片引脚

4)system_clock_init()系统时钟初始化
该函数在archarmmach-exynosclock_init_exynos4.c中定义。

5)mem_ctrl_init()初始化DMC
该函数在archarmmach-exynosdmc_init_exynos4.c中定义。

6)tzpc_init()
该函数在archarmmach-exynostzpc.c中定义。

修改set_ps_hold_ctrl

set_ps_hold_ctrl()函数在arch/arm/mach-exynos/power.c中。2

ps_hold引脚为电源管理芯片引脚,需要拉高,否则会掉电。power.c代码如下:

#ifdef CONFIG_CBT4412
static void exynos4x12_set_ps_hold_ctrl(void)
{
	struct exynos4x12_power *power = 
		(struct exynos4x12_power *)samsung_get_base_power();

	
	setbits_le32(&power->ps_hold_control, EXYNOS_PS_HOLD_CONTROL_DATA_HIGH);

	
	writel(0x3, (unsigned int *)0x11000c08);
}
#endif


void set_ps_hold_ctrl(void)
{
	if (cpu_is_exynos5())
		exynos5_set_ps_hold_ctrl();
#ifdef CONFIG_CBT4412
	else if (cpu_is_exynos4())
		exynos4x12_set_ps_hold_ctrl();
#endif
}

static uint32_t exynos4_get_reset_status(void)
{
#ifdef CONFIG_CBT4412
	struct exynos4x12_power *power =
		(struct exynos4x12_power *)samsung_get_base_power();
#else
	struct exynos4_power *power =
		(struct exynos4_power *)samsung_get_base_power();
#endif

	return power->inform1;
}

还没修改完,对应的4x12寄存器结构体也得对应上。
修改 arch/arm/mach-exynos/include/mach/power.h
添加4x12的电源芯片结构体定义

power.h代码如下:

struct exynos4x12_power {
	unsigned int	om_stat;
	unsigned char	res1[0xc];
	unsigned int	rtc_clko_sel;
	unsigned int	gnss_rtc_out_ctrl;
	unsigned int	lpi_denial_mask0;
	unsigned int	lpi_denial_mask1;
	unsigned int	lpi_denial_mask2;
	unsigned int	c2c_ctrl;
	unsigned char	res2[0x1d8];
	unsigned int	central_seq_config;
	unsigned int	res3;
	unsigned int	central_seq_option;
	unsigned char	res4[0x1f4];
	unsigned int	swreset;
	unsigned int	rst_stat;
	unsigned int	auto_wdt_reset_disable;
	unsigned int	mask_wdt_reset_request;
	unsigned char	res5[0x1f0];
	unsigned int	wakeup_stat;
	unsigned int	eint_wakeup_mask;
	unsigned int	wakeup_mask;
	unsigned char	res6[0xf4];
	unsigned int	hdmi_phy_control;
	unsigned int	usbdevice_phy_control;
	unsigned int	hsic_1_phy_control;
	unsigned int	hsic_2_phy_control;
	unsigned int	mipi_phy0_control;
	unsigned int	mipi_phy1_control;
	unsigned int	adc_phy_control;
	unsigned char	res7[0x64];
	unsigned int	body_bias_con0;
	unsigned int	body_bias_con1;
	unsigned int	body_bias_con2;
	unsigned int	body_bias_con3;
	unsigned char	res8[0x70];
	unsigned int	inform0;
	unsigned int	inform1;
	unsigned int	inform2;
	unsigned int	inform3;
	unsigned int	inform4;
	unsigned int	inform5;
	unsigned int	inform6;
	unsigned int	inform7;
	unsigned char	res9[0x1e0];
	unsigned int	pmu_debug;
	unsigned char	res10[0x5fc];
	unsigned int	arm_core0_sys_pwr_reg;
	unsigned char	res11[0xc];
	unsigned int	arm_core1_sys_pwr_reg;
	unsigned char	res12[0x6c];
	unsigned int	arm_common_sys_pwr_reg;
	unsigned char	res13[0x3c];
	unsigned int	arm_cpu_l2_0_sys_pwr_reg;
	unsigned int	arm_cpu_l2_1_sys_pwr_reg;
	unsigned char	res14[0x38];
	unsigned int	cmu_aclkstop_sys_pwr_reg;
	unsigned int	cmu_sclkstop_sys_pwr_reg;
	unsigned char	res15[0x4];
	unsigned int	cmu_reset_sys_pwr_reg;
	unsigned char	res16[0x10];
	unsigned int	apll_sysclk_sys_pwr_reg;
	unsigned int	mpll_sysclk_sys_pwr_reg;
	unsigned int	vpll_sysclk_sys_pwr_reg;
	unsigned int	epll_sysclk_sys_pwr_reg;
	unsigned char	res17[0x8];
	unsigned int	cmu_clkstop_gps_alive_sys_pwr_reg;
	unsigned int	cmu_reset_gps_alive_sys_pwr_reg;
	unsigned int	cmu_clkstop_cam_sys_pwr_reg;
	unsigned int	cmu_clkstop_tv_sys_pwr_reg;	
	unsigned int	cmu_clkstop_mfc_sys_pwr_reg;
	unsigned int	cmu_clkstop_g3d_sys_pwr_reg;
	unsigned int	cmu_clkstop_lcd0_sys_pwr_reg;
	unsigned int	cmu_clkstop_isp_sys_pwr_reg;
	unsigned int	cmu_clkstop_maudio_sys_pwr_reg;
	unsigned int	cmu_clkstop_gps_sys_pwr_reg;
	unsigned int	cmu_reset_cam_sys_pwr_reg;
	unsigned int	cmu_reset_tv_sys_pwr_reg;
	unsigned int	cmu_reset_mfc_sys_pwr_reg;
	unsigned int	cmu_reset_g3d_sys_pwr_reg;
	unsigned int	cmu_reset_lcd0_sys_pwr_reg;
	unsigned int	cmu_reset_isp_sys_pwr_reg;
	unsigned int	cmu_reset_maudio_sys_pwr_reg;
	unsigned int	cmu_reset_gps_sys_pwr_reg;
	unsigned int	top_bus_sys_pwr_reg;
	unsigned int	top_retention_sys_pwr_reg;
	unsigned int	top_pwr_sys_pwr_reg;
	unsigned char	res18[0x14];
	unsigned int	logic_reset_sys_pwr_reg;
	unsigned char	res19[0x1c];
	unsigned int	onenandxl_mem_sys_pwr_reg;
	unsigned int	hsi_mem_sys_pwr_reg;
	unsigned char	res20[0x4];	
	unsigned int	usbotg_mem_sys_pwr_reg;
	unsigned int	sdmmc_mem_sys_pwr_reg;
	unsigned int	cssys_mem_sys_pwr_reg;
	unsigned int	secss_mem_sys_pwr_reg;
	unsigned int	potator_mem_sys_pwr_reg;
	unsigned char	res21[0x20];
	unsigned int	pad_retention_dram_sys_pwr_reg;
	unsigned int	pad_retention_maudio_sys_pwr_reg;
	unsigned char	res22[0x18];
	unsigned int	pad_retention_gpio_sys_pwr_reg;
	unsigned int	pad_retention_uart_sys_pwr_reg;
	unsigned int	pad_retention_mmca_sys_pwr_reg;
	unsigned int	pad_retention_mmcb_sys_pwr_reg;
	unsigned int	pad_retention_ebia_sys_pwr_reg;
	unsigned int	pad_retention_ebib_sys_pwr_reg;
	unsigned char	res23[0x8];
	unsigned int	pad_isolation_sys_pwr_reg;
	unsigned char	res24[0x1c];
	unsigned int	pad_alv_sel_sys_pwr_reg;
	unsigned char	res25[0x1c];
	unsigned int	xusbxti_sys_pwr_reg;
	unsigned int	xxti_sys_pwr_reg;
	unsigned char	res26[0x38];
	unsigned int	ext_regulator_sys_pwr_reg;
	unsigned char	res27[0x3c];
	unsigned int	gpio_mode_sys_pwr_reg;
	unsigned char	res28[0x3c];
	unsigned int	gpio_mode_maudio_sys_pwr_reg;
	unsigned char	res29[0x3c];
	unsigned int	cam_sys_pwr_reg;
	unsigned int	tv_sys_pwr_reg;
	unsigned int	mfc_sys_pwr_reg;
	unsigned int	g3d_sys_pwr_reg;
	unsigned int	lcd0_sys_pwr_reg;
	unsigned int	isp_sys_pwr_reg;
	unsigned int	maudio_sys_pwr_reg;
	unsigned int	gps_sys_pwr_reg;
	unsigned int	gps_alive_sys_pwr_reg;
	unsigned char	res30[0xc5c];
	unsigned int	arm_core0_configuration;
	unsigned int	arm_core0_status;
	unsigned int	arm_core0_option;
	unsigned char	res31[0x74];
	unsigned int	arm_core1_configuration;
	unsigned int	arm_core1_status;
	unsigned int	arm_core1_option;
	unsigned char	res32[0x37c];
	unsigned int	arm_common_option;
	unsigned char	res33[0x1f4];
	unsigned int	arm_cpu_l2_0_configuration;
	unsigned int	arm_cpu_l2_0_status;
	unsigned char	res34[0x18];
	unsigned int	arm_cpu_l2_1_configuration;
	unsigned int	arm_cpu_l2_1_status;
	unsigned char	res35[0xa00];
	unsigned int	pad_retention_maudio_option;
	unsigned char	res36[0xdc];
	unsigned int	pad_retention_gpio_option;
	unsigned char	res37[0x1c];
	unsigned int	pad_retention_uart_option;
	unsigned char	res38[0x1c];
	unsigned int	pad_retention_mmca_option;
	unsigned char	res39[0x1c];
	unsigned int	pad_retention_mmcb_option;
	unsigned char	res40[0x1c];
	unsigned int	pad_retention_ebia_option;
	unsigned char	res41[0x1c];
	unsigned int	pad_retention_ebib_option;
	unsigned char	res42[0x160];
	unsigned int	ps_hold_control;
	unsigned char	res43[0xf0];
	unsigned int	xusbxti_configuration;
	unsigned int	xusbxti_status;
	unsigned char	res44[0x14];
	unsigned int	xusbxti_duration;
	unsigned int	xxti_configuration;
	unsigned int	xxti_status;
	unsigned char	res45[0x14];
	unsigned int	xxti_duration;
	unsigned char	res46[0x1dc];
	unsigned int	ext_regulator_duration;
	unsigned char	res47[0x5e0];
	unsigned int	cam_configuration;
	unsigned int	cam_status;
	unsigned int	cam_option;
	unsigned char	res48[0x14];
	unsigned int	tv_configuration;
	unsigned int	tv_status;
	unsigned int	tv_option;
	unsigned char	res49[0x14];
	unsigned int	mfc_configuration;
	unsigned int	mfc_status;
	unsigned int	mfc_option;
	unsigned char	res50[0x14];
	unsigned int	g3d_configuration;
	unsigned int	g3d_status;
	unsigned int	g3d_option;
	unsigned char	res51[0x14];
	unsigned int	lcd0_configuration;
	unsigned int	lcd0_status;
	unsigned int	lcd0_option;
	unsigned char	res52[0x14];
	unsigned int	isp_configuration;
	unsigned int	isp_status;
	unsigned int	isp_option;
	unsigned char	res53[0x34];
	unsigned int	gps_configuration;
	unsigned int	gps_status;
	unsigned int	gps_option;
	unsigned char	res54[0x14];
	unsigned int	gps_alive_configuration;
	unsigned int	gps_alive_status;
	unsigned int	gps_alive_option;
};

struct exynos4412_power {
	unsigned char	res1[0x0704];
	unsigned int	usbhost_phy_control;
	unsigned int	hsic1_phy_control;
	unsigned int	hsic2_phy_control;
};
copy_uboot_to_ram()

该函数在archarmmach-exynosspl_boot.c中定义。

分析修改spl_boot.c的原因

假设需要从SD卡启动U-Boot,保留SD卡启动的代码如下:

enum index {
	MMC_INDEX,
	EMMC44_INDEX,
	EMMC44_END_INDEX,
	SPI_INDEX,
	USB_INDEX,
};


u32 irom_ptr_table[] = {
	[MMC_INDEX] = 0x02020030,	
	[EMMC44_INDEX] = 0x02020044,	
	[EMMC44_END_INDEX] = 0x02020048,
	[SPI_INDEX] = 0x02020058,	
	[USB_INDEX] = 0x02020070,	
	};

void *get_irom_func(int index)
{
	return (void *)*(u32 *)irom_ptr_table[index];
}

void copy_uboot_to_ram(void)
{
	unsigned int bootmode = BOOT_MODE_OM;

	u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL;
	u32 offset = 0, size = 0;

	if (bootmode == BOOT_MODE_OM)
		bootmode = get_boot_mode();

	switch (bootmode) {
	case BOOT_MODE_SD:
		offset = BL2_START_OFFSET;
		size = BL2_SIZE_BLOC_COUNT;
		copy_bl2 = get_irom_func(MMC_INDEX);
		break;

	if (copy_bl2)
		copy_bl2(offset, size, CONFIG_SYS_TEXT_base);
}

由代码可以看出,复制BL2到iRAM的源代码是固化在iROM中的,并且将函数接口的函数指针存放到irom_ptr_table[]数组中,通过调用get_irom_func()函数调用复制BL2函数。所以,不知道也不能修改iROM中是如何实现复制BL2的。
有博主已经说明该代码不能实现复制BL23,并修改了spl_bool.c。基本原理是:先将U-Boot从SD卡复制到iRAM的保留地址区,再从iRAM复制到DRAM中。

如果有大牛分享Exynos4412-iROM-ApplicationNote之类的文档就更好了!

修改arch/arm/mach-exynos/spl_boot.c支持copy_uboot_to_ram

修改spl_boot.c代码如下:4

-   if (copy_bl2)
+#ifdef CONFIG_TARGET_CBT4412
+   if (copy_bl2) {
+       
+           unsigned int i, count = 0;
+           unsigned char *buffer = (unsigned char *)0x02050000;
+           unsigned char *dst = (unsigned char *)CONFIG_SYS_TEXT_base;
+           unsigned int step = (0x10000 / 512);
+   
+           for (count = 0; count < BL2_SIZE_BLOC_COUNT; count += step) {
+               
+               copy_bl2((u32)(BL2_START_OFFSET+count), (u32)step, (u32)buffer);
+               
+               for (i = 0; i < 0x10000; i++) {
+                   *dst++ = buffer[i];
+               }
+           }
+   }
+#else
+   if (copy_bl2) {
        copy_bl2(offset, size, CONFIG_SYS_TEXT_base);
+   }
+#endif
(*uboot)();
    uboot = (void *)CONFIG_SYS_TEXT_base;
// uboot函数设置为BL2的加载地址上
    (*uboot)();
// 调用uboot函数,也就跳转到BL2的代码中

到此,SPL的任务就完成了,也已经跳到了BL2也就是uboot里面去了。


  1. uboot的启动过程分析 ↩︎

  2. ITOP4412----Uboot2020移植记录 ↩︎

  3. 基于tiny4412的u-boot移植(二) ↩︎

  4. 基于iTop-4412的U-Boot 2017移植 ↩︎

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5694520.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存