- 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)();
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()函数在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里面去了。
uboot的启动过程分析 ↩︎
ITOP4412----Uboot2020移植记录 ↩︎
基于tiny4412的u-boot移植(二) ↩︎
基于iTop-4412的U-Boot 2017移植 ↩︎
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)