嵌入式Linux新板子bring-up实战 以Rockchip平台为例
导读:新板子回来后怎么让它跑起来?本文以Rockchip RK3588为例,用流程图展示从USB烧录到驱动验证的完整bring-up过程。
一、bring-up完整流程
flowchart TB
A(["上电"]) --> B{"USB能识别<br/>设备?"}
B -->|"否"| B1["检查BOOT引脚<br/>检查供电"]
B -->|"是"| C["烧录SPL"]
C --> D{"SPL打印<br/>DDR init done?"}
D -->|"否"| D1["调DDR时序<br/>检查DDR型号"]
D -->|"是"| E["烧录完整U-Boot"]
E --> F["串口有<br/>U-Boot日志?"]
F -->|"否"| F1["查波特率<br/>查pinmux"]
F -->|"是"| G["内核能<br/>正常启动?"]
G -->|"否"| G1["查设备树<br/>查bootargs"]
G -->|"是"| H["DDR稳定性<br/>memtester测试"]
H --> I(["进入Linux<br/>开始调驱动"])
style A fill:#E3F2FD,stroke:#1976D2
style B fill:#FFF8E1,stroke:#F57C00
style D fill:#FFEBEE,stroke:#D32F2F
style D1 fill:#FFEBEE,stroke:#D32F2F
style F1 fill:#FFF8E1,stroke:#F57C00
style G1 fill:#FFF8E1,stroke:#F57C00
style I fill:#E8F5E9,stroke:#388E3C
二、第一步:USB烧录
RK3588进入烧录模式
| 模式 | 进入方式 | 用途 |
|---|---|---|
| Maskrom模式 | 断开电源 → 按住Maskrom键 → 上电 | 芯片ROM等待USB命令(eMMC为空时自动进) |
| Loader模式 | 断开电源 → 按住Recovery键 → 上电保持3秒 | SPL已运行,等待烧录 |
| 软件进入 | 系统下执行 reboot loader |
已进入系统时的备选方式 |
flowchart LR
A["断开电源"] --> B["按Recovery键"]
B --> C["上电保持3秒"]
C --> D["Loader模式<br/>等待烧录"]
软件进入Loader模式(系统能正常启动时):
# 在调试串口执行
reboot loader
烧录注意事项
- 使用数据传输线,不是充电线
- 确保电脑上的USB驱动已安装(DriverAssistant)
- 虚拟机环境下先断开虚拟机连接
烧录命令
# 查看USB是否识别
rkdeveloptool list
# 烧录SPL(DDR初始化程序)
rkdeveloptool db rk3588_spl_loader_v1.15.113.bin
# 烧录U-Boot
rkdeveloptool ul rk3588_spl_loader_v1.15.113.bin
rkdeveloptool wl 0x4000 uboot.img
# 烧录boot和rootfs
rkdeveloptool wl 0x6000 boot.img
rkdeveloptool wl 0x8000 rootfs.img
烧录失败排查
| 现象 | 原因 | 解决 |
|---|---|---|
| USB识别不到 | 未进入Loader模式 | 按住Recovery键再按复位键 |
| USB识别不到 | 使用了充电线而非数据线 | 换用支持数据传输的数据线 |
| USB识别不到 | 电脑开了虚拟机 | 挂起或断开虚拟机连接 |
| USB识别不到 | OTG口供电不足 | 先按住升级键,再插上OTG线和电源线 |
| 烧录中途报错 | DDR初始化失败 | 检查DDR型号、重配时序 |
| 烧录成功但不起动 | SPL的DDR配置与实际颗粒不匹配 | 换用正确颗粒对应的SPL bin |
| 烧录成功但找不到设备 | 分区文件与实际固件不匹配 | 使用SDK编译生成的完整固件 |
| 升级工具显示设备类型不匹配 | 板子未进入升级模式 | 按住升级键+复位键,或执行reboot loader |
| 长时间按升级键无法识别 | 个别电脑反应较慢 | 最长可能需要30秒 |
三、第二步:SPL阶段(DDR bring-up)
SPL是U-Boot的第一阶段,运行在芯片内部SRAM,负责初始化DDR。
flowchart TB
A["上电"] --> B["ROM代码"]
B --> C["加载SPL到SRAM"]
C --> D["SPL初始化DDR"]
D --> E{"DDR init<br/>成功?"}
E -->|"否"| F["卡死<br/>无任何输出"]
E -->|"是"| G["打印DDR init done"]
G --> H["加载完整U-Boot到DDR"]
H --> I["跳转执行U-Boot"]
style F fill:#FFEBEE,stroke:#D32F2F
style G fill:#E8F5E9,stroke:#388E3C
SPL启动日志
成功时串口输出:
U-Boot SPL 2022.07 (Jan 15 2026 - 10:00:00)
DDR Version 1.08 20221121
LPDDR4X, 2112MHz
BW=32 Col=10 Bk=8 CS0 Row=16 CS=1 Die BW=16 Size=4096MB
DDR init done
Trying to boot from MMC2
如果没有任何输出,说明DDR初始化卡死了——这是bring-up中最常见的问题。
固件烧写后无法启动? 如果烧写后板子完全无法启动,连Loader模式都进不去,需要用Maskrom模式重新烧写:
- 断开电源
- 按住Maskrom键
- 上电,USB被识别为Maskrom设备
- 重新烧写完整固件
DDR怎么调
第一步:确认板子上DDR的实际型号(从原理图和BOM确认)
第二步:找到SDK中对应的DDR bin文件
来自 linuxros.cn · linuxROS
rk3588_ddr_lp4_2112MHz_v1.08.bin # DDR频率和版本
rk3588_ddr_lp5_2736MHz_v1.08.bin # LPDDR5版本
第三步:对比参考板和新板的DDR差异
| 情况 | 处理方式 |
|---|---|
| 同款DDR同款布线 | 直接用参考板的bin |
| 同款DDR不同容量 | 需要修改DDR容量配置 |
| 不同DDR型号 | 必须根据新颗粒重新生成bin |
第四步:U-Boot下验证DDR
# 写入测试数据
mw.l 0x80000000 0xdeadbeef 1
# 读回验证
md.l 0x80000000 1
# 输出应为: 80000000: deadbeef
DDR问题表现
| 现象 | 可能原因 |
|---|---|
| SPL完全无输出 | DDR初始化卡死 |
| 烧录中途失败 | 烧录工具用DDR做缓存,DDR出错导致校验失败 |
| U-Boot启动后随机崩溃 | DDR时序不稳定,位翻转 |
| 内核启动到一半卡死 | 某段DDR地址不稳定 |
四、第三步:U-Boot启动
DDR验证通过后,完整U-Boot启动:
正常启动日志
U-Boot 2022.07 (Jan 15 2026 - 10:00:00)
Model: Rockchip RK3588 Evaluation Board
DRAM: 4 GiB
MMC: mmc@fe310000: 0, mmc@fe320000: 1
In: serial@feb50000
Out: serial@feb50000
Err: serial@feb50000
Net: eth0: ethernet@fe010000
Hit any key to stop autoboot: 0
=>
串口无输出?
| 检查项 | 方法 |
|---|---|
| 波特率 | 确认终端设为1500000(RK3588默认1.5M) |
| TX/RX接线 | 检查串口TX接PC的RX |
| 引脚复用 | 查设备树uart节点的pinmux |
| 时钟 | 示波器测UART TX引脚有没信号 |
U-Boot常用命令
# 查看环境变量
printenv
# 查看eMMC信息
mmc info
# 查看SPI Flash
sf probe
# 测试网络
ping 192.168.1.1
# 通过网络加载内核
tftpboot 0x80080000 Image
五、第四步:内核启动
U-Boot加载内核后,内核开始启动:
正常启动日志
[ 0.000000] Booting Linux on physical CPU 0x0000000000
[ 0.000000] Kernel command line: console=ttyS2,1500000n8 earlycon=uart8250,mmio32,0xfeb50000 root=/dev/mmcblk0p2
[ 0.100000] Memory: 4000MB total
[ 0.500000] VFS: Mounted root (ext4 filesystem) on device 179:2
内核卡死排查
| 卡住位置 | 优先查什么 |
|---|---|
| 无任何输出 | earlycon地址是否正确、uart节点status |
| 停在"Starting kernel" | 内核与设备树是否匹配 |
| 停在驱动加载 | dmesg、initcall_debug参数 |
| 停在"VFS: Cannot open root" | bootargs中root=路径是否正确 |
earlycon配置
设备树中配置串口输出:
chosen {
stdout-path = "serial2:1500000n8";
};
bootargs中追加:
earlycon=uart8250,mmio32,0xfeb50000
六、第五步:驱动验证
系统跑起来后,逐项验证硬件:
DDR稳定性测试
memtester 2048M 10
GPIO测试
# 查看GPIO
cat /sys/kernel/debug/gpio
# 控制LED
echo 24 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio24/direction
echo 1 > /sys/class/gpio/gpio24/value
I2C测试
# 扫描I2C设备
i2cdetect -y 1
# 读传感器ID
i2cget -y 1 0x48 0x00
七、总结
flowchart LR
A["USB烧录"] --> B["SPL跑通"]
B --> C["U-Boot跑通"]
C --> D["内核跑通"]
D --> E["DDR稳定"]
E --> F["驱动验证"]
style A fill:#E3F2FD,stroke:#1976D2
style B fill:#FFEBEE,stroke:#D32F2F
style C fill:#FFF8E1,stroke:#F57C00
style D fill:#FFF8E1,stroke:#F57C00
style E fill:#E8F5E9,stroke:#388E3C
style F fill:#E8F5E9,stroke:#388E3C
bring-up核心要点:
- 一次只动一个变量——先用参考板验证软件没问题
- DDR是最难的环节——SPL能打印"DDR init done"才算过第一关
- 串口是唯一的眼睛——尽早让串口有输出
- DDR稳定性必须测——memtester大范围长时间跑
你bring-up卡在哪一步?评论区说说!