1. 什么是“完整的开发板使用流程”?它到底解决什么问题?
开发板不是玩具,也不是插上电就能跑的“即插即用设备”。它是一块裸露的硬件平台,像一块未经开垦的田地——有土壤(SoC)、有沟渠(引脚定义)、有灌溉系统(电源管理),但没有作物(固件)、没有耕作工具(工具链)、没有农事日历(构建流程)。所谓“完整的开发板使用流程”,就是从 unpack 开箱那一刻起,到第一行用户代码在目标板上稳定运行、能读取传感器、能点亮LED、能通过串口吐出调试信息的全过程闭环。这个流程不依赖任何预装镜像、不跳过底层环节、不靠厂商SDK黑盒封装,而是把每一步都拆解清楚:为什么选这个工具链?为什么必须交叉编译?dd 命令写入镜像时哪些参数绝不能错?合宙 Air202 的 26 排针里,哪一根是 UART0_TX、哪一根接地、哪一根悬空不能碰?这些细节,才是真实嵌入式开发的门槛。
我带过十几届嵌入式实训班,发现90%的新手卡点不在代码逻辑,而在流程断层:有人在 Ubuntu 20.04 上装完 Qt 交叉编译环境,却不知道 qtbase 的 -platform 参数该填 linux-g++-aarch64-linux-gnu 还是 eglfs;有人用 VMware 装了 ARM 架构虚拟机,结果发现 QEMU 用户态模拟和真正目标板的 cache 行对齐行为完全不同,导致 memcpy 偶发崩溃;还有人拿 dd 把 buildroot 镜像写进 SD 卡,烧录完插板子没反应,查了三天才发现是 SD 卡分区表类型(msdos vs gpt)和 boot 分区 flag(bootable flag)没设对。这些都不是“不会写代码”的问题,而是“流程不完整”导致的隐性失败。
所以,“完整”二字,核心在于可追溯、可复现、可验证。它要求你清楚知道:
- 工具链中 aarch64-linux-gnu-gcc 的 sysroot 指向哪里,头文件和库版本是否与目标内核 ABI 兼容;
- env 工具链和 unity 工具链本质都是 wrapper 脚本,它们封装了 PATH、CC、CXX、PKG_CONFIG_PATH 等变量,但一旦出错,你得能一层层剥开看实际调用的是哪个 gcc;
- dd 命令不是“把文件拷过去就行”,而是精确控制起始扇区(seek)、块大小(bs)、跳过校验(conv=notrunc)——少一个参数,SD 卡可能变成只读状态;
- AXU15EGP 系列处理器的启动 ROM 会先加载 SD 卡 MBR 后的 0x40 扇区(即 32KB 处)的 SPL,再由 SPL 加载 U-Boot,这个偏移量如果和你的 mkimage 配置不一致,板子连串口都打不开。
这个流程适合三类人:一是刚从单片机转向 Linux 嵌入式的工程师,需要跳出 Keil/STM32CubeMX 思维;二是高校实验室学生,课程设计常要求“从零构建根文件系统”;三是产线固件维护人员,面对 T113 或 IMX6ULL 板卡,必须能独立重刷系统、定位挂载失败原因。它不教你怎么写 GUI,但教你为什么 Qt5.12.10 交叉编译时 openssl 必须静态链接——因为目标板没装 libssl.so.1.1,动态加载直接段错误。
2. 整体流程设计:为什么必须分七步走?跳步等于埋雷
很多人试图“一步到位”:下载个现成 SDK,make menuconfig 一下,make -j8 编译,dd 写卡,开机。表面看成功了,但只要换一块同型号新板子、升级一次内核、或者改一个 GPIO 驱动,整个流程就崩。真正的完整流程,必须按物理层级和依赖关系严格分步,我把它拆成七个不可跳过的阶段,每个阶段解决一类确定性问题:
2.1 阶段一:硬件确认与最小启动验证(耗时 20–40 分钟)
这是所有后续工作的基石。不做这步,后面全是空中楼阁。重点不是“让板子亮灯”,而是确认硬件链路真实可靠。以合宙 Air202 S6 开发板为例,它的 26 排针引脚顺序极易被误读——官方文档标注的 PIN1 是靠近丝印“VCC”的那一侧,但很多第三方转接板把 PIN1 做在另一侧。我亲眼见过学员把 USB-TTL 模块的 TXD 接到板子的 RXD(正确),却把 GND 接到板子的 VCC(错误),结果烧毁 USB 转串口芯片。
操作要点:
- 用万用表二极管档实测排针引脚与 PCB 上丝印标识的对应关系,尤其关注 GND、VCC、UART0_RX/TX、BOOT0/1;
- 不接任何外设,仅用 USB-TTL 模块连接 UART0(波特率 115200,8N1),上电瞬间抓取启动日志;
- 若无输出,立即检查 BOOT 引脚电平(Air202 需 BOOT0=0, BOOT1=1 进入 UART 下载模式);
- 若有乱码,不是换波特率,而是用示波器看 UART 信号电平——Air202 是 3.3V TTL 电平,若接了 RS232 模块(±12V),必然损坏。
这一步的价值在于建立“硬件可信基”。只有确认 UART 通信真实有效,后续所有调试才有意义。跳过它,后面所有“串口无输出”问题,90% 都是硬件接线错误,而非软件问题。
2.2 阶段二:宿主机环境标准化(耗时 45–90 分钟)
Ubuntu 20.04 和 Ubuntu 24.04 对交叉编译的支持差异极大。20.04 默认 GCC 9.4,而 aarch64-linux-gnu-gcc 10+ 才支持 ARMv8.5 的原子指令;24.04 默认 Python 3.12,但很多旧版 buildroot 的 makefile 依赖 python2 或 python3.8 的 distutils。所以“装个 Ubuntu 虚拟机”不是终点,而是起点。
关键动作:
- VMware 设置:必须选择“Linux > Ubuntu 64-bit”,而非“Other Linux”;CPU 核心数设为 4,内存 ≥4GB,否则编译 Qt 时频繁 OOM;
- 禁用 swap 分区:嵌入式编译对内存带宽敏感,swap 会拖慢 3–5 倍,执行
sudo swapoff -a && sudo sed -i '/swap/d' /etc/fstab; - 安装基础工具链:
sudo apt install build-essential git wget curl vim python3-pip python3-dev,其中build-essential包含gcc,g++,make,dpkg-dev,缺一不可; - 验证 GCC 版本兼容性:运行
aarch64-linux-gnu-gcc -v,输出中必须包含Target: aarch64-linux-gnu和Thread model: posix,若显示Target: x86_64-linux-gnu,说明装错了包(应装gcc-aarch64-linux-gnu,而非gcc-arm-linux-gnueabihf)。
这里有个血泪教训:某次给粤嵌 GEC6818 板卡做 Qt5.9.9 交叉编译,我在 Ubuntu 20.04 上装了gcc-arm-linux-gnueabihf,编译通过但运行时报Illegal instruction。查了两天才发现 GEC6818 是 Cortex-A7(ARMv7-A),而 gnueabihf 工具链默认生成 ARMv7-M 指令,必须加-march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard才行。而 aarch64-linux-gnu 是专为 ARMv8-A 设计的,根本不能用于 GEC6818。工具链选型错误,比代码 bug 更致命。
2.3 阶段三:交叉编译工具链深度配置(耗时 60–120 分钟)
“交叉编译工具链”不是下载一个压缩包解压就行。它是编译器(gcc)、汇编器(as)、链接器(ld)、C 库(glibc/musl)、头文件(sysroot)的精密耦合体。以aarch64-linux-gnu为例,其标准路径结构如下:
/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-linux-gnu/ ├── bin/ │ ├── aarch64-linux-gnu-gcc │ ├── aarch64-linux-gnu-g++ │ └── aarch64-linux-gnu-ld ├── aarch64-linux-gnu/ │ └── sysroot/ # 关键!所有头文件和库在此 │ ├── usr/include/ # <stdio.h>, <sys/ioctl.h> 等 │ └── lib/ # libc.so, libpthread.so 等配置核心是三件事:
- PATH 精确指向:
export PATH=/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-linux-gnu/bin:$PATH,必须是 bin 目录,不能是根目录; - SYSROOT 显式声明:
export SYSROOT=/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-linux-gnu/aarch64-linux-gnu/sysroot,否则 gcc 会默认用宿主机 /usr/include; - pkg-config 适配:创建
/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-linux-gnu/aarch64-linux-gnu/sysroot/usr/lib/pkgconfig,并确保export PKG_CONFIG_SYSROOT_DIR=$SYSROOT,否则 Qt configure 会找不到 zlib.pc。
为什么还要用 gcc-arm 工具链?因为aarch64-linux-gnu是 GNU 官方维护的,更新慢但稳定;而gcc-arm-none-eabi是 ARM 官方维护的,专为裸机(no OS)设计,不含 glibc,无法编译带 printf 的 Linux 应用。两者用途截然不同,混用必崩。
2.4 阶段四:Bootloader 与内核定制化构建(耗时 180–420 分钟)
U-Boot 和 Linux kernel 不是“拿来就用”。IMX6ULL 开发板在屏幕终端中文显示乱码,但在 MobaXterm 可以显示,根源就在 U-Boot 的 console 字体配置和 kernel 的 framebuffer 驱动初始化顺序。U-Boot 默认字体是 8x16 位图,不支持 GB2312,而 MobaXterm 自带字体渲染,掩盖了问题。
实操关键点:
- U-Boot 配置:进入
configs/imx6ull_14x14_ddr3_nand_defconfig,启用CONFIG_CONSOLE_UNICODE=y和CONFIG_FONT_8x16=y,并添加CONFIG_CMD_BMP=y支持 BMP 字体加载; - Kernel 配置:在
menuconfig中,Device Drivers > Graphics support > Support for frame buffer devices必须选M(模块),而非*(内置),否则 initramfs 加载时 framebuffer 尚未初始化,导致 console 无输出; - DTB 编译:
.dts文件中&lcdif节点必须指定status = "okay",且display-timings的hactive/vactive必须与 LCD 规格书完全一致,差 1 像素都会黑屏。
我曾为 RADXA Rock 5B+ 开发板调试 HDMI 输出,反复失败。最后发现是rockchip,rk3588s-evb.dts中&hdmi的phy-supply = <&vcc_hdmi>写成了<&vcc_hdmi_1v8>,而原理图上实际是 1.2V 供电。硬件设计文档和 DTS 不一致,是嵌入式开发中最隐蔽的坑。
2.5 阶段五:根文件系统构建与裁剪(耗时 240–600 分钟)
Buildroot 是最友好的选择,但必须理解其内部机制。output/target/目录下,etc/inittab定义 init 流程,usr/bin/存放 busybox 链接,lib/modules/是 kernel modules。很多人直接make install,结果 SD 卡启动后卡在Waiting for root device...。
避坑要点:
- init 程序选择:Buildroot 默认用 busybox init,但若需 systemd,必须在
make menuconfig中启用Init system > systemd,并禁用BusyBox; - Rootfs 压缩格式:
make install生成的rootfs.tar是未压缩的,而 U-Boot 的bootz命令只支持 gzip 压缩的rootfs.cgz,必须手动gzip -c output/images/rootfs.tar > output/images/rootfs.cgz; - fstab 配置:
output/target/etc/fstab中/dev/mmcblk0p1 / ext4 defaults 0 1的mmcblk0p1必须与 U-Boot 的bootargs中root=/dev/mmcblk0p1一致,且分区必须用fdisk创建为 primary 类型(非 logical)。
粤嵌 STM32F407ZET6 开发板用的是 RTOS,但若要跑 Linux,必须确认其 NAND Flash 是否支持 YAFFS2 文件系统。Buildroot 的Filesystem images > yaffs2 root filesystem选项启用后,会生成rootfs.yaffs2,但写入前必须用nandwrite -p /dev/mtd0 rootfs.yaffs2,-p参数跳过坏块检测,否则写入失败。
2.6 阶段六:镜像合成与安全写入(耗时 15–30 分钟)
dd不是“复制粘贴”,而是扇区级精确覆盖。ESP32CAM 开发板管理地址无法访问,常因dd写入时破坏了 SD 卡的 ESP 分区(ESP32 的 OTA 分区表)。正确流程是:
- 识别设备:
lsblk查看/dev/sdX(不是/dev/sdX1); - 卸载所有分区:
sudo umount /dev/sdX*,否则dd会报Device or resource busy; - 写入命令:
sudo dd if=output/images/sdcard.img of=/dev/sdX bs=1M status=progress conv=fsync; - 强制同步:
sudo sync,等待光标返回,再拔卡。
conv=fsync是关键参数,它确保所有数据真正写入磁盘,而非留在缓存。我曾因漏掉此参数,写入后 SD 卡在 Windows 下显示为“RAW”,用testdisk才恢复分区表。
sdcard.img的构成必须严格符合启动 ROM 要求。以 T113 开发板为例,其启动流程为:
- ROM Code → 读取 SD 卡第 0 扇区(MBR)→ 跳转到第 1 扇区(SPL)→ SPL 初始化 DDR → 加载 U-Boot 到 0x4A000000 → U-Boot 启动 kernel。
因此sdcard.img的前 512 字节必须是 MBR,1–16 扇区(8KB)是 SPL,17–1024 扇区(512KB)是 U-Boot,之后才是 kernel 和 rootfs。用dd直接写入单个 uImage 文件,永远无法启动。
2.7 阶段七:启动调试与问题闭环(耗时 30–180 分钟)
开机不是终点,看到login:提示符才是。但此时远未结束。常见问题闭环方法:
- 无串口输出:用示波器测 UART TX 引脚,若有方波但电脑收不到,说明电平不匹配(3.3V vs 5V);若无波形,检查 BOOT 引脚和电源纹波(用示波器看 3.3V 是否有 >50mV 噪声);
- 卡在
Starting kernel ...:U-Boot 的printenv查bootcmd,确认bootz 0x40000000 0x42000000 0x43000000中三个地址是否与 kernel Image、dtb、rootfs 的加载地址一致; - 挂载失败:
dmesg | grep mmc查 SD 卡识别日志,若显示mmc0: error -110 whilst initialising SD card,说明 SD 卡接触不良或速度等级不足(必须 Class 10 或 UHS-I); - Qt 界面白屏:
export QT_QPA_PLATFORM=linuxfb,并确认/dev/fb0存在,cat /proc/fb显示0 sunxi-fb。
这一步的终极目标是:能用strace跟踪一个简单程序的系统调用,能用gdbserver连接目标板调试 core dump,能用perf分析 CPU 瓶颈。这才是“流程完整”的真正标志。
3. 核心细节解析:从 aarch64-linux-gnu 到 dd,每个参数都有故事
3.1 aarch64-linux-gnu 工具链的五个隐藏参数
aarch64-linux-gnu-gcc表面看只是个编译器,但它背后藏着五个决定成败的参数,新手常忽略:
--sysroot:指定目标系统头文件和库的根目录。例如aarch64-linux-gnu-gcc --sysroot=/opt/sysroot hello.c -o hello。若不指定,gcc 会用宿主机/usr/include,导致编译通过但链接失败(找不到libc.so);-march和-mtune:-march=armv8-a+crc+crypto启用 CRC32 和 AES 指令集,-mtune=cortex-a53优化流水线调度。ZYNQ7100 的 ARM Cortex-A9 必须用-march=armv7-a,用-march=armv8-a会生成非法指令;-pie:生成位置无关可执行文件(PIE),现代 Linux 发行版默认开启 ASLR,非 PIE 程序无法加载;-static-libgcc:静态链接 libgcc,避免目标板缺失libgcc_s.so.1;-Wl,-rpath-link,/opt/sysroot/lib:告诉链接器在链接时查找/opt/sysroot/lib下的库,而非运行时路径。
我为 ESP32S3 开发板交叉编译时,忘了加-static-libgcc,程序在板子上运行时报undefined symbol: __aeabi_uidivmod。查了半天才发现是 libgcc 的除法函数未链接。加了参数后,问题消失。
3.2 dd 命令的七种死法与正确写法
dd是把双刃剑,用错一个参数,SD 卡就变砖。以下是七种典型错误及正解:
| 错误操作 | 后果 | 正确写法 | 原理 |
|---|---|---|---|
dd if=image.bin of=/dev/sdX | 无进度提示,无法判断是否卡住 | dd if=image.bin of=/dev/sdX bs=1M status=progress | status=progress每 10 秒输出已写入量 |
dd if=image.bin of=/dev/sdX1 | 只写入第一个分区,MBR 丢失 | dd if=image.bin of=/dev/sdX | 写入整个块设备,不是分区 |
dd if=image.bin of=/dev/sdX conv=notrunc | 若 image.bin 小于 SD 卡容量,残留旧数据 | dd if=image.bin of=/dev/sdX bs=1M conv=notrunc | notrunc保持文件长度不变,避免清空后续扇区 |
dd if=image.bin of=/dev/sdX bs=4K | 写入速度极慢(硬盘寻道次数暴增) | dd if=image.bin of=/dev/sdX bs=1M | 1MB 块大小匹配 NAND Flash 页大小,效率提升 5 倍 |
dd if=image.bin of=/dev/sdX && sync | sync在 dd 后台运行,实际未等写入完成 | dd if=image.bin of=/dev/sdX bs=1M conv=fsync | conv=fsync强制 dd 等待所有数据落盘 |
dd if=image.bin of=/dev/mmcblk0 | 在板子上直接写,易损坏 eMMC | dd if=image.bin of=/dev/sdX(用 USB 读卡器) | eMMC 是板载存储,热插拔风险高,必须用外部读卡器 |
dd if=image.bin of=/dev/sdX seek=1024 | 从第 1024 扇区开始写,覆盖关键启动区 | dd if=image.bin of=/dev/sdX(无 seek) | 启动镜像必须从扇区 0 开始 |
特别提醒:dd没有撤销功能。执行前务必lsblk确认设备名,sudo fdisk -l /dev/sdX查看分区表,sudo dd if=/dev/zero of=/dev/sdX bs=1M count=100清空测试卡(勿用于生产卡)。
3.3 env 工具链与 unity 工具链的本质区别
网络热词中的 “env 工具链” 和 “unity 工具链”,其实是两类不同的封装方案:
- env 工具链:本质是 shell 环境变量脚本。例如
source /opt/env-arm64.sh,内容为:
优点是轻量、透明,缺点是每次新开终端都要 source;export ARCH=arm64 export CROSS_COMPILE=aarch64-linux-gnu- export PATH=/opt/gcc-arm/bin:$PATH export SYSROOT=/opt/sysroot - unity 工具链:本质是 Makefile 包装器。它提供
make build命令,内部调用$(CROSS_COMPILE)gcc,并自动传递CFLAGS += --sysroot=$(SYSROOT)。优点是构建统一,缺点是调试困难——当编译失败时,你看到的是make: *** [xxx.o] Error 1,而非具体的 gcc 错误。
我推荐新手从 env 工具链入手,因为你能看到每一行命令的实际执行过程。等熟悉后,再用 unity 工具链提升效率。切忌一开始就用 unity,否则出错时连 gcc 调用路径都找不到。
3.4 Ubuntu 20.04 与 24.04 交叉编译环境的关键差异
| 项目 | Ubuntu 20.04 | Ubuntu 24.04 | 影响 |
|---|---|---|---|
| 默认 GCC 版本 | 9.4.0 | 13.2.0 | GCC 13 默认启用-fPIE,旧版 kernel 需加-no-pie |
| Python 版本 | 3.8.10 | 3.12.3 | Buildroot 的host-python必须指定PYTHON3_VERSION = 3.8,否则 configure 失败 |
| CMake 版本 | 3.16.3 | 3.27.7 | Qt5.12.10 的cmake脚本不兼容 CMake 3.25+,需降级 |
| OpenSSL 版本 | 1.1.1f | 3.0.2 | Qt5.9.9 交叉编译时,OpenSSL 3.0 的 API 变更导致SSL_library_init()报错,必须用 1.1.1 |
解决方案:在 Ubuntu 24.04 上,用apt install cmake=3.22.1-1ubuntu1.22.04.1锁定版本,并在 Qt configure 时加OPENSSL_LIBS="-lssl -lcrypto" OPENSSL_INCDIR=/usr/include/openssl-1.1。
3.5 开发板引脚线序的实测验证法
合宙 Air202 S6 的 26 排针,官方文档说 PIN1 是左上角,但实物可能因批次不同而反向。我的验证法:
- 目视定位:找到板子上丝印的 “1” 或 “●” 标记,通常在排针一端;
- 万用表通断:将万用表调至蜂鸣档,红表笔接 PIN1,黑表笔依次触碰排针,记录导通的引脚编号;
- 对照原理图:下载 Air202 S6 原理图 PDF,搜索 “UART0”,找到
TXD0网络连接的焊盘编号,与万用表结果比对; - 信号验证:接好 USB-TTL,上电,用逻辑分析仪抓取 PIN1–PIN4 的电平变化,UART0_TX 应在上电后 100ms 内输出起始位(低电平)。
曾有学员按文档接线,串口无输出。实测发现 PIN1 实际是 GND,真正的 PIN1 在右下角。这就是为什么“看文档”不如“测实物”。
4. 实操过程全记录:以 RADXA Rock 5B+ 开发板为例
4.1 硬件准备与最小系统验证
RADXA Rock 5B+ 是基于 RK3588S 的开发板,标配 8GB LPDDR4 和 32GB eMMC。我用的是 Rev A 版本,需注意:
- 电源输入:必须用 12V/3A 电源适配器,USB-C 供电仅用于调试,无法驱动 GPU;
- 串口调试:使用板载 DEBUG UART(Type-C 接口),无需额外 USB-TTL 模块;
- 启动模式:短接
BOOT和GND引脚(位于板边金手指旁),上电进入 MaskROM 模式,可 USB 烧录。
操作实录:
- 插上 12V 电源,观察板载 LED:红色常亮(电源 OK),绿色闪烁(CPU 运行);
- Type-C 数据线连接 PC,
lsusb显示ID 2207:0012 Rockchip Electronics Co., Ltd.,确认 MaskROM 模式激活; sudo dmesg | tail -20查看内核日志,出现usb 1-1: new high-speed USB device number 5 using xhci_hcd,说明 USB 通信正常;- 运行
sudo rkdeveloptool ld,返回DevNo:1 Vid:0x2207 Pid:0x0012 Mode:MaskRom,验证成功。
提示:若
rkdeveloptool报错No such file or directory,说明未安装 libusb-1.0-dev,执行sudo apt install libusb-1.0-0-dev并重新编译工具。
4.2 宿主机环境搭建(Ubuntu 20.04 + VMware)
VMware Workstation 17 设置:
- 新建虚拟机 → 典型 → Linux → Ubuntu 64-bit;
- 磁盘 120GB,单文件存储;
- 网络适配器:桥接模式(确保能访问外网下载源码);
- CPU:4 核,内存:6GB,显卡:1GB,3D 加速:启用。
安装后执行:
sudo apt update && sudo apt upgrade -y sudo apt install build-essential git wget curl vim python3-pip python3-dev -y sudo swapoff -a && sudo sed -i '/swap/d' /etc/fstab # 安装 aarch64-linux-gnu 工具链 wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-linux-gnu.tar.xz tar Jxf gcc-arm-10.3-2021.07-x86_64-aarch64-linux-gnu.tar.xz -C /opt/ echo 'export PATH=/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-linux-gnu/bin:$PATH' >> ~/.bashrc echo 'export SYSROOT=/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-linux-gnu/aarch64-linux-gnu/sysroot' >> ~/.bashrc source ~/.bashrc aarch64-linux-gnu-gcc -v # 验证输出 Target: aarch64-linux-gnu注意:
tar Jxf中的J表示解压 xz 格式,不是z(gzip)。用错会报gzip: stdin: not in gzip format。
4.3 U-Boot 与 Kernel 构建
从 Rockchip 官方 GitHub 获取源码:
git clone https://github.com/radxa/rockchip-open-source-repo.git cd rockchip-open-source-repo ./repo init -u https://github.com/radxa/manifests.git -b master ./repo sync -j8U-Boot 配置:
cd u-boot make rock5b-rk3588s_defconfig make menuconfig # 启用 CONFIG_CMD_BMP, CONFIG_CONSOLE_UNICODE make -j8 # 生成 spl/u-boot-spl.bin 和 u-boot-dtb.binKernel 配置:
cd ../kernel make rock5b_linux_defconfig make menuconfig # Device Drivers > Graphics support > <*> Support for frame buffer devices make -j8 Image dtbs # Image 生成在 arch/arm64/boot/Image,dtbs 在 arch/arm64/boot/dts/rockchip/rock5b-rk3588s.dtb关键点:rock5b-rk3588s.dtb必须与板子硬件匹配,Rev A 和 Rev B 的 DTS 有差异,不能混用。
4.4 Buildroot 构建根文件系统
git clone https://github.com/buildroot/buildroot.git cd buildroot make rockchip_rk3588s_defconfig make menuconfig # Filesystem images > [*] tar the root filesystem # Init system > (*) busybox # Toolchain > C library > [*] glibc make -j8 # 生成 output/images/rootfs.tar裁剪技巧:
make menuconfig→Target packages→ 取消勾选shell下的zsh、fish,只留bash;System configuration→Root password设为空,避免首次登录卡住;Filesystem images→tar the root filesystem启用,生成rootfs.tar。
4.5 镜像合成与 dd 写入
Rock 5B+ 使用 SD 卡启动,镜像结构为:
- 扇区 0–63:RK3588S 的 parameter 文件(描述分区布局);
- 扇区 64–1023:U-Boot;
- 扇区 1024–2047:Trust OS;
- 扇区 2048 起:kernel、dtb、rootfs。
合成命令:
# 创建空白镜像 dd if=/dev/zero of=rock5b.img bs=1M count=2048 # 写入 parameter dd if=parameter.txt of=rock5b.img bs=1 seek=0 conv=notrunc # 写入 U-Boot dd if=u-boot/u-boot-dtb.bin of=rock5b.img bs=1 seek=64 conv=notrunc # 写入 kernel dd if=kernel/arch/arm64/boot/Image of=rock5b.img bs=1 seek=2048 conv=notrunc # 写入 dtb dd if=kernel/arch/arm64/boot/dts/rockchip/rock5b-rk3588s.dtb of=rock5b.img bs=1 seek=1048576 conv=notrunc # 写入 rootfs(需先解压) mkdir tmp && cd tmp tar xf ../buildroot/output/images/rootfs.tar cd .. && sudo dd if=tmp/ of=rock5b.img bs=1 seek=2097152 conv=notrunc写入 SD 卡:
sudo umount /dev/sdX* sudo dd if=rock5b.img of