保姆级教程:手把手教你为Exynos 4412开发板移植U-Boot(附完整源码修改清单)
Exynos 4412开发板U-Boot移植实战:从零构建完整启动环境
当一块非官方评估板的开发板(如FS4412)拿到手时,最令人头疼的问题往往是启动环境的适配。不同于官方评估板开箱即用的体验,这类开发板需要开发者深入U-Boot源码,进行一系列针对性的修改。本文将带你完整走过Exynos 4412开发板的U-Boot移植全过程,从源码获取到最终烧写,每个步骤都配有详细的代码修改清单和原理说明。
1. 准备工作与环境搭建
在开始移植前,我们需要建立一个清晰的开发环境。不同于简单的应用开发,U-Boot移植对工具链和开发环境有特定要求:
- 工具链选择:推荐使用Linaro GCC 4.7或更高版本,这是经过验证对ARMv7架构支持最好的工具链之一
- 开发主机:建议使用Ubuntu 18.04/20.04 LTS,避免因glibc版本问题导致的兼容性错误
- 源码获取:U-Boot官方仓库中,针对Exynos 4412的支持从2013.10版本开始成熟
# 获取U-Boot源码 git clone git://git.denx.de/u-boot.git cd u-boot git checkout v2023.04 -b exynos4412提示:建议在源码目录外单独建立工作目录存放移植补丁和构建脚本,保持源码树的干净
开发板硬件确认清单:
- 串口调试接口引脚定义(通常为J1连接器)
- 核心板内存配置(DDR3容量与时序)
- 存储设备类型(eMMC/NAND Flash)
- 网络PHY型号(如DM9000AEP)
2. 基础移植:板级支持包创建
U-Boot对非官方开发板的支持,始于创建一个新的板级支持包(BSP)。以FS4412为例,我们需要基于最接近的官方板(通常是Origen)进行适配。
2.1 创建板级目录结构
在board/samsung/目录下创建fs4412子目录,复制origen板的相关文件:
mkdir -p board/samsung/fs4412 cp board/samsung/origen/* board/samsung/fs4412/需要重命名的关键文件:
origen.c→fs4412.corigen.h→fs4412.hMakefile中的目标名变更
2.2 修改boards.cfg配置
在顶层目录的boards.cfg文件中添加新板配置:
fs4412 arm armv7 fs4412 samsung exynos对应的各字段含义为:
- 板名称
- 架构
- CPU类型
- 板级目录
- 厂商目录
- SoC系列
2.3 基础编译测试
执行初始配置和编译:
make fs4412_config make -j4此时生成的u-boot.bin还不能正常运行,但可以验证基础编译环境是否正常。常见问题排查:
- 工具链路径错误:检查CROSS_COMPILE变量设置
- 依赖缺失:安装libssl-dev和bison/flex
- 版本冲突:确保工具链与U-Boot版本匹配
3. 关键外设驱动移植
基础框架搭建完成后,需要逐个移植关键外设驱动。这是确保开发板基本功能可用的关键步骤。
3.1 串口调试输出配置
串口是开发阶段最重要的调试手段,修改board/samsung/fs4412/lowlevel_init.S:
/* 在lowlevel_init中添加串口初始化 */ ldr r0, =0x13800000 @ Exynos4412 UART2基址 mov r1, #0x0 str r1, [r0, #0x08] @ UFCON mov r1, #0x3 str r1, [r0, #0x0C] @ UMCON mov r1, #0x5 str r1, [r0] @ UBRDIV对应的时钟配置需要添加到fs4412.c中:
/* 在board_init函数中添加 */ writel((readl(0x1003C000) | (0x1<<24)), 0x1003C000); // UART时钟门控 writel(0x666666, 0x10010210); // CLK_SRC_PERIL0 writel(0x7777, 0x10010214); // CLK_DIV_PERIL03.2 DM9000网卡驱动适配
FS4412通常采用DM9000AEP网卡,需要修改以下文件:
include/configs/fs4412.h中添加:
#define CONFIG_DRIVER_DM9000 #define CONFIG_DM9000_BASE 0x05000000 #define DM9000_IO CONFIG_DM9000_BASE #define DM9000_DATA (CONFIG_DM9000_BASE + 4) #define CONFIG_DM9000_USE_16BITboard/samsung/fs4412/fs4412.c中添加GPIO配置:
/* 网卡GPIO初始化 */ writel(0x00220020, 0x11000000 + 0x120); // GPK0CON writel(0x00002222, 0x11000000 + 0x140); // GPK0PUD3.3 eMMC/SD卡驱动移植
Exynos 4412的存储控制器支持eMMC4.4协议,需要特别注意时钟配置:
/* 在fs4412.c中添加eMMC初始化 */ #define EXYNOS4_CLOCK_BASE 0x10030000 #define CLK_SRC_FSYS_OFFSET 0x10C40 #define CLK_DIV_FSYS3_OFFSET 0x10C48 void emmc_init(void) { /* 时钟源选择MPLL */ writel((readl(EXYNOS4_CLOCK_BASE + CLK_SRC_FSYS_OFFSET) & ~0xF0000) | 0x60000, EXYNOS4_CLOCK_BASE + CLK_SRC_FSYS_OFFSET); /* 分频设置 */ writel((readl(EXYNOS4_CLOCK_BASE + CLK_DIV_FSYS3_OFFSET) & ~0xFF0F) | 0x1001, EXYNOS4_CLOCK_BASE + CLK_DIV_FSYS3_OFFSET); }对应的GPIO配置:
/* eMMC引脚配置 */ writel(0x33333333, 0x11000040); // GPK0CON writel(0x0000FFFF, 0x11000048); // GPK0PUD4. 启动流程深度定制
商业开发板通常需要添加厂商特定的启动校验和加密流程,这部分需要特别注意与硬件设计的配合。
4.1 BL1引导加载器集成
Exynos 4412采用两级启动机制,需要在U-Boot前添加三星提供的BL1:
# 生成最终镜像的shell脚本 #!/bin/bash make -j4 split -b 14336 u-boot.bin bl2 ./sdfuse_q/chksum ./sdfuse_q/add_padding cat E4412_N.bl1.bin bl2.bin u-boot.bin > final.bin注意:BL1二进制文件需要从开发板供应商处获取,不同PCB版本可能不兼容
4.2 启动设备检测机制
为支持多种启动方式(SD卡/eMMC),需要添加启动设备检测逻辑:
int board_late_init(void) { char *boot_device = getenv("bootdevice"); if (!boot_device) { if (/* 检测SD卡 */) { setenv("bootdevice", "mmc"); } else if (/* 检测eMMC */) { setenv("bootdevice", "emmc"); } } return 0; }对应的设备树需要添加:
/ { chosen { bootargs = "console=ttySAC2,115200 root=/dev/mmcblk0p2 rootwait"; }; };5. 调试技巧与问题排查
U-Boot移植过程中,有效的调试手段可以大幅提高效率。以下是经过验证的实用技巧:
5.1 LED调试法
在关键代码路径添加LED控制,帮助定位启动卡死位置:
/* 在start.S中添加 */ ldr r0, =0x11000100 @ GPX1CON ldr r1, [r0] bic r1, r1, #0xF0000000 orr r1, r1, #0x10000000 str r1, [r0] @ 配置GPX1_7为输出 ldr r0, =0x11000104 @ GPX1DAT mov r1, #0x80 str r1, [r0] @ 点亮LED5.2 内存检测方法
DDR初始化是常见问题点,添加内存测试命令:
int do_memtest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { ulong start = CONFIG_SYS_SDRAM_BASE + 0x100000; ulong end = start + 0x100000; memory_test(start, end, 0xAAAAAAAA, 0x55555555); return 0; } U_BOOT_CMD( memtest, 1, 1, do_memtest, "simple memory test", "" );5.3 常见问题解决方案
串口无输出:
- 检查UART时钟配置
- 验证串口引脚复用设置
- 确认终端软件波特率(通常115200)
网卡无法工作:
- 用示波器检测DM9000的片选信号
- 检查PHY复位电路时序
- 验证MAC地址配置
eMMC识别失败:
- 确认时钟频率不超过200MHz
- 检查CMD/DATA线上拉电阻
- 验证电源稳定时间
6. 高级功能定制
基础功能稳定后,可以考虑添加提升开发效率的高级功能。
6.1 快速启动优化
通过裁剪不必要的功能和命令减少启动时间:
/* 在include/configs/fs4412.h中禁用 */ #undef CONFIG_CMD_NET #undef CONFIG_CMD_NFS #undef CONFIG_CMD_PING /* 减小环境变量区 */ #define CONFIG_ENV_SIZE 0x20006.2 安全启动实现
添加简单的镜像校验机制:
int verify_image(ulong addr, ulong size) { ulong checksum = 0; ulong *p = (ulong *)addr; for (int i = 0; i < size/4; i++) { checksum += *p++; } return (checksum == *(p + 1)); }6.3 量产工具集成
创建自动化烧写脚本:
#!/bin/bash # fs4412_program.sh sudo dd if=/dev/zero of=$1 bs=512 seek=1 count=2047 sudo dd if=u-boot.bin of=$1 bs=512 seek=1 conv=notrunc sync7. 完整源码修改清单
以下是所有需要修改的文件及其关键变更点:
| 文件路径 | 修改内容 | 备注 |
|---|---|---|
| board/samsung/fs4412/Makefile | 目标名变更 | origen→fs4412 |
| include/configs/fs4412.h | 添加板级配置宏 | 网络、存储等 |
| arch/arm/cpu/armv7/start.S | 添加LED调试代码 | 早期调试用 |
| board/samsung/fs4412/lowlevel_init.S | 串口初始化 | 确保调试输出 |
| common/main.c | 修改启动延时 | 设为0快速启动 |
| drivers/mmc/s5p_mshc.c | 添加eMMC支持 | 4.4/4.5协议 |
关键补丁示例:
--- a/board/samsung/fs4412/fs4412.c +++ b/board/samsung/fs4412/fs4412.c @@ -15,6 +15,7 @@ #include <asm/arch/cpu.h> #include <asm/arch/mmc.h> #include <asm/arch/power.h> +#include <asm/arch/sromc.h> DECLARE_GLOBAL_DATA_PTR; @@ -22,6 +23,10 @@ { struct exynos4_power *pwr = (struct exynos4_power *)EXYNOS4_POWER_BASE; + + /* 初始化网卡 */ + dm9000aep_pre_init(); + s5p_config_sromc(); gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;移植完成后,建议使用git维护所有修改:
git init git add . git commit -m "Initial port for FS4412 board"这样既方便后续升级,也能清晰追踪每个修改的目的。当需要同步新版U-Boot时,可以通过git rebase减少合并冲突。
