移植 u-boot-2020.07 到 iTOP-4412(三)重定位、UART

文章目录

  • 一、重定位
    • 1. boot from SD
    • 2. boot from EMMC4.4
    • 3. verification
  • 二、UART 初始化
    • 1. exynos_pinmux_config()
    • 2. debug_uart_init()
    • 3. 测试
  • 三、UART 优化

一、重定位

copy_uboot_to_ram() 流程:

  1. spl_get_machine_params() 获取从 SERIAL 启动时的参数,仅 spl 编译。(不会使用到)
  2. get_boot_mode() 获取启动模式,SD、emmc 等。
  3. 通过启动模式获取相应的 copy 函数。
  4. 将 u-boot.bin 重定位到 CONFIG_SYS_TEXT_BASE 地址处,长度为 BL2_SIZE_BLOC_COUNT。

1. boot from SD

   首先只考虑从 SD 中启动,先分析启动参数:(顺便吐槽一下不知道为什么 u-boot 要把下面的 if 放到 switch 外面,真是人类迷惑行为)

case BOOT_MODE_SD:
	offset = BL2_START_OFFSET;
	size = BL2_SIZE_BLOC_COUNT;
	copy_bl2 = get_irom_func(MMC_INDEX);
	if (copy_bl2)
		copy_bl2(offset, size, CONFIG_SYS_TEXT_BASE);
	break;

计算 u-boot.bin 的偏移,固定拷贝 512 KB 到 RAM。

#define RESERVE_BLOCK_SIZE		(512)
#define BL1_SIZE				(8 << 10)  /*8 K reserved for BL1*/
#define SPL_SIZE				(16 << 10) /*8 K reserved for SPL*/
#define COPY_BL2_SIZE			0x80000 // 512 KB
#define BL2_START_OFFSET		((RESERVE_BLOCK_SIZE + BL1_SIZE + SPL_SIZE)/512)
#define BL2_SIZE_BLOC_COUNT		(COPY_BL2_SIZE/512)

惊奇的发现,卧槽?原来三星早就固化好了 copy to ram 的程序?仔细想想,也是啊,都能先从这些设备启动 bl1,肯定在 iROM 已经有程序可以操作它们了。

/* IROM Function Pointers Table */
u32 irom_ptr_table[] = {
	[MMC_INDEX] = 0x02020030,	/* iROM Function Pointer-SDMMC boot */
	[EMMC44_INDEX] = 0x02020044,	/* iROM Function Pointer-EMMC4.4 boot*/
	[EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer
						-EMMC4.4 end boot operation */
	[SPI_INDEX] = 0x02020058,	/* iROM Function Pointer-SPI boot */
	[USB_INDEX] = 0x02020070,	/* iROM Function Pointer-USB boot*/
};

2. boot from EMMC4.4

TODO

3. verification

   又到了愉快的点灯时刻。。。

   如果 u-boot 加载成功,会执行到 common/main.c 中的 main_loop() 函数中,你懂的。。。

   果然,失败了。。开始找原因!顺便看一看 u-boot 的启动流程,和 spl 应该是不一样的。

   经过努力看 code,终于找到了问题的根本:板子电源没有插,插上就亮了。。。。愣是看了一小时代码才发现。

   不过不看不知道,一看吓一跳,原来 spl 跳转到 ram 中的 u-boot 后,会经过一系列地址无关码到 relocate_code ,该函数会将 ram 中的 u-boot 重新定位一个偏移量,这之后才是重定位结束,再跳转到 u-boot 开始执行(抱歉这一系列汇编操作太骚,没看懂)。

二、UART 初始化

   经过上面的实验,已经可以执行到 main_loop() 函数,之后基本都是和架构无关的 code 了,但是为了调试,还要将 UART 初始化。

   UART 初始化在文件 arch/arm/mach-exynos/lowlevel_init.cdo_lowlevel_init() 函数中:

#ifdef CONFIG_DEBUG_UART
#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL_SUPPORT)) || \
    !defined(CONFIG_SPL_BUILD)
		exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
		debug_uart_init();
#endif
#endif

   可以看出需要定义 CONFIG_DEBUG_UART 和 定义 CONFIG_SPL_BUILD 时才编译,如果想在 spl 阶段就开始 printf 需要定义 CONFIG_SPL_SERIAL_SUPPORT。

移植 u-boot-2020.07 到 iTOP-4412(三)重定位、UART_第1张图片
打开 > Device Drivers > Serial drivers > Enable an early debug UART for debugging,并将

  • Base address of UART 设置为 0x13820000,这是寄存器的地址
  • UART input clock 设置为 100000000

1. exynos_pinmux_config()

   该函数初始化 gpio,将涉及到的 gpio 配置为 UART。但是默认使用的是 UART3,这里改为 UART2,上面设置的寄存器地址也是 UART2。

#ifdef CONFIG_XHR4412
		exynos_pinmux_config(PERIPH_ID_UART2, PINMUX_FLAG_NONE);
#else
		exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
#endif

2. debug_uart_init()

文件为:

  • drivers/serial/serial_s5p.c

不需要更改。

3. 测试

一次成功,没有问题!
移植 u-boot-2020.07 到 iTOP-4412(三)重定位、UART_第2张图片
   不过发现一个让人很不爽的问题,在 u-boot 输入命令,有顿手卡,一卡一卡的,而且输入多个字符可能都不显示,就打开了源码看一看:

static void __maybe_unused s5p_serial_init(struct s5p_uart *uart)
{
	/* enable FIFOs, auto clear Rx FIFO */
	writel(0x3, &uart->ufcon);
	writel(0, &uart->umcon);
	/* 8N1 */
	writel(0x3, &uart->ulcon);
	/* No interrupts, no DMA, pure polling */
	writel(0x245, &uart->ucon);
}

   = = 卧槽,鬼才,不开中断进行 polling,这个一定要给他改改。

三、UART 优化

大概分析了一下,想要打开中断主要可能有这些步骤:

  1. 打开 arm IRQ 模式,设置该模式的 SP
  2. 把 vector 重定位
  3. 使能 IRQ
  4. vector 中正确的链接位置跳转到中断处理函数
  5. 处理中断

应该不算很简单,之后再做。

初始化文件:

  • drivers/serial/serial-uclass.c [serial_init]

你可能感兴趣的:(移植 u-boot-2020.07 到 iTOP-4412(三)重定位、UART)