第4章:U-Boot移植与配置

U-Boot,说白了就是嵌入式系统的“第一道门”。它负责把硬件初始化好,然后引导内核启动。在全志T507平台上,U-Boot的移植工作直接决定了你的仪表盘能不能跑起来。

我记得刚接触T507时,第一件事就是研究它的U-Boot源码结构。嗯,这里面的门道不少,今天我就带你走一遍。

4.1 U-Boot源码结构

全志T507的U-Boot基于官方主线版本,但做了不少定制。源码目录结构大致如下:

u-boot/
├── arch/              # 架构相关代码
│   └── arm/          # ARM架构
│       ├── cpu/      # CPU初始化
│       └── dts/      # 设备树文件
├── board/            # 板级支持包
│   └── sunxi/        # 全志系列
├── configs/          # 板级配置
│   └── t507_defconfig
├── drivers/          # 驱动代码
│   ├── net/          # 网络驱动
│   ├── mmc/          # 存储驱动
│   └── video/        # 显示驱动
├── dts/              # 设备树源文件
└── include/          # 头文件

我个人习惯先看board/sunxi/目录。这里存放了全志系列所有板子的初始化代码。T507的板级文件就在这里面,文件名通常叫board_t507.c

核心要点:U-Boot的启动流程是:SPL → U-Boot proper → Kernel。SPL负责最基础的初始化,比如时钟、DDR。U-Boot proper则加载设备树和内核。

4.2 板级配置

板级配置是移植的第一步。全志T507的默认配置在configs/t507_defconfig里。我建议你直接基于这个文件修改。

打开看看,内容大致是这样的:

CONFIG_ARM=y
CONFIG_ARCH_SUNXI=y
CONFIG_MACH_SUN50I_H6=y
CONFIG_DRAM_CLK=672
CONFIG_DRAM_TYPE=3
CONFIG_MMC0_CD_PIN="PH13"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2

这里有几个关键参数:

  • CONFIG_DRAM_CLK:DDR时钟频率。T507默认是672MHz,但如果你用的是不同型号的DDR颗粒,可能需要调整。
  • CONFIG_DRAM_TYPE:DDR类型。3代表DDR3,4代表DDR4。T507支持DDR3和DDR4,但要注意电压匹配。
  • CONFIG_MMC0_CD_PIN:SD卡检测引脚。这个引脚错了,插卡都识别不了。

我的经验:有一次客户说他们的板子启动不了,我排查了半天,发现是DRAM_CLK设高了。DDR跑在700MHz以上就不稳定。所以,别一味追求高频,稳定第一。

4.3 设备树修改

设备树(Device Tree)是U-Boot和内核沟通的桥梁。T507的设备树文件在arch/arm/dts/目录下,文件名是sun50i-h6-t507.dts

设备树里定义了硬件资源,比如:

&mmc0 {
    pinctrl-names = "default";
    pinctrl-0 = <&mmc0_pins>;
    vmmc-supply = <&reg_vcc3v3>;
    cd-gpios = <&pio PH 13 GPIO_ACTIVE_LOW>;
    status = "okay";
};

这段代码配置了SD卡控制器。注意cd-gpios,它指定了卡检测引脚。如果硬件设计上这个引脚接的是PH13,那就对了。

我遇到过一个问题:设备树里status写成了"disabled",结果SD卡死活不工作。嗯,这种低级错误,排查起来最费时间。

警告:修改设备树时,一定要和硬件原理图对照。引脚号、电平、电源域,一个都不能错。我曾经因为一个上拉电阻没加,导致设备树里配了内部上拉也没用。

4.4 网络驱动

车载仪表盘通常需要网络功能,比如OTA升级。T507内置了千兆以太网控制器,驱动在drivers/net/里。

网络驱动的配置项:

CONFIG_SUN8I_EMAC=y
CONFIG_SUN8I_EMAC_USE_PHY=y
CONFIG_PHY_REALTEK=y

这里SUN8I_EMAC是T507的以太网控制器驱动。PHY芯片用的是Realtek的,所以也要打开对应的PHY驱动。

设备树里网络部分是这样配的:

&emac {
    pinctrl-names = "default";
    pinctrl-0 = <&emac_pins>;
    phy-mode = "rgmii";
    phy-handle = <&ext_rgmii_phy>;
    status = "okay";
};

注意phy-mode,它决定了MAC和PHY之间的接口模式。RGMII是千兆模式,如果你的硬件只支持百兆,要改成"rmii"

避坑指南:我曾经在调试网络时,发现U-Boot能ping通,但内核里网络不通。后来发现是U-Boot和内核的设备树里PHY地址不一致。所以,两个地方的设备树一定要同步。

4.5 存储驱动

存储驱动主要管eMMC和SD卡。T507的MMC控制器驱动在drivers/mmc/里。

配置项:

CONFIG_MMC_SUNXI=y
CONFIG_MMC_SUNXI_SLOT=0
CONFIG_MMC_SUNXI_SLOT_EXTRA=2

MMC_SUNXI_SLOT是主控制器,通常接eMMC。MMC_SUNXI_SLOT_EXTRA是扩展控制器,接SD卡。

设备树里eMMC的配置:

&mmc2 {
    pinctrl-names = "default";
    pinctrl-0 = <&mmc2_pins>;
    vmmc-supply = <&reg_vcc3v3>;
    vqmmc-supply = <&reg_vcc1v8>;
    non-removable;
    bus-width = <8>;
    status = "okay";
};

注意bus-width,eMMC支持8位数据总线,SD卡只支持4位。配错了,性能会大打折扣。

我记得有一次,客户说eMMC读写速度慢。我一看,bus-width配成了4。改成8后,速度翻了一倍。

4.6 编译与烧录

配置好之后,就是编译了。全志T507的U-Boot编译命令:

make t507_defconfig
make -j4

编译完成后,会生成u-boot-sunxi-with-spl.bin。这个文件包含了SPL和U-Boot proper。

烧录到SD卡:

sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8

注意seek=8,这是全志平台的固定偏移。写错了位置,板子就起不来了。

警告:烧录前一定要确认/dev/sdX是你的SD卡,不是硬盘。我见过有人把U-Boot写到了系统盘上,结果电脑都启动不了。

4.7 调试技巧

U-Boot移植过程中,调试是少不了的。我常用的方法:

  • 串口日志:U-Boot默认会输出日志到串口。如果板子没反应,先检查串口接线和波特率(通常是115200)。
  • GPIO点灯:在关键位置加GPIO点灯代码,可以快速定位问题。
  • 内存测试:用mtest命令测试DDR稳定性。

举个例子,在board_init_f()里加个GPIO点灯:

gpio_direction_output(SUNXI_GPL(2), 1);  // 点亮LED

如果LED亮了,说明代码执行到了这里。没亮,那就是前面出问题了。

我的习惯:我会在SPL、U-Boot proper、内核启动这三个阶段各放一个LED指示。这样一眼就能看出系统卡在了哪一步。

4.8 总结

U-Boot移植,说白了就是三板斧:配好板级配置、改好设备树、调通驱动。全志T507的U-Boot已经比较成熟,大部分工作都是微调。

但要注意,车载仪表盘对稳定性要求极高。U-Boot阶段如果出了问题,系统根本起不来。所以,每一步都要仔细验证。

嗯,这一章就到这里。下一章我们讲内核移植,那才是真正的大头。