Zephyr 在 Radxa ROCK 5B+(RK3588)上的移植与启动实战指南
【免费下载链接】zephyrPrimary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.项目地址: https://gitcode.com/GitHub_Trending/ze/zephyr
本指南以 Zephyr 仓库中 boards/radxa/rock_5b_plus/doc/index.rst 为核心,结合板级源码、设备树与 SOC 级实现,系统讲解如何为基于 Rockchip RK3588 的单板计算机 Radxa ROCK 5B+ 构建、配置和引导 Zephyr 固件。读完本文,你将掌握 Zephyr 板级支持包的完整结构、UART2 串口控制台配置、8 核 SMP 构建方法,以及通过 Radxa U-Boot 的 legacy 镜像加载路径把 Zephyr 跑起来的完整流程。
板卡概览:RK3588 与 ROCK 5B+
ROCK 5B+ 是一块以 Rockchip RK3588 为核心的单板计算机(SBC)。RK3588 是一款大小核异构 SoC,集成4 个 Cortex-A76 大核与 4 个 Cortex-A55 小核。该板卡最高可选配32 GB LPDDR5 内存,并提供了 eMMC、microSD、PCIe、USB、以太网以及 40-pin 扩展排针等丰富外设接口。
在 Zephyr 仓库中,该板卡的官方标识为rock_5b_plus,其定义位于 boards/radxa/rock_5b_plus/board.yml:
vendor: radxa,SoC 为rk3588;- 提供名为
smp的板级变体(variant),对应多核启动版本; - 基础板与 SMP 变体均为
arm64架构,RAM 声明为 131072 KB(128 MB,与设备树中预留的 DRAM 区一致)。
从 SOC 层看,SOC_RK3588由 soc/rockchip/rk35/rk3588/Kconfig.soc 定义并归属于SOC_SERIES_RK35系列,板级 Kconfig boards/radxa/rock_5b_plus/Kconfig.rock_5b_plus 通过select SOC_RK3588完成绑定。
注意:文档明确说明,板载以太网接口目前尚未被 Zephyr 支持。虽然 RK3588 设备树中已描述了两个 dwmac GMAC 节点(见 dts/arm64/rockchip/rk3588.dtsi),但它们默认处于
disabled状态,板级 dts 也未启用,因此当前阶段不要依赖网口进行开发调试。
板级配置结构解析
rock_5b_plus板卡目录下的文件组成了一个标准的 Zephyr 板级支持包(BSP):
| 文件 | 作用 |
|---|---|
| board.yml | 板卡元数据(名称、厂商、SoC、变体) |
| Kconfig.rock_5b_plus | 板级 Kconfig 符号,绑定 SoC |
| rock_5b_plus.dts | 板级设备树(基础版) |
| rock_5b_plus_smp.dts | SMP 变体设备树 |
| rock_5b_plus.yaml | 基础版 hwmv2 描述 |
| rock_5b_plus_smp.yaml | SMP 变体 hwmv2 描述 |
| rock_5b_plus_defconfig | 基础版默认配置 |
| rock_5b_plus_smp_defconfig | SMP 变体默认配置 |
设备树:console、DRAM 与 UART2
基础设备树 rock_5b_plus.dts 首先包含arm64/rockchip/rk3588.dtsi与common/mem.h,然后声明:
model = "Radxa ROCK 5B+"; compatible = "radxa,rock-5b-plus", "rockchip,rk3588"; chosen { zephyr,console = &uart2; zephyr,shell-uart = &uart2; zephyr,sram = &dram; }; dram: memory@10000000 { compatible = "mmio-sram"; device_type = "memory"; reg = <0x10000000 DT_SIZE_M(128)>; }; &uart2 { status = "okay"; current-speed = <1500000>; };关键点:
chosen节点把zephyr,console与zephyr,shell-uart都指向uart2,同时把zephyr,sram指向dram——这就是0x10000000 加载地址的来源:Zephyr 镜像被设计为加载并运行在0x10000000,设备树在对应地址声明了 128 MB 内存区域;- UART2 被显式启用并配置为 1.5 Mbit/s,这就是文档所述“串口控制台 1.5 Mbit/s”的设备树依据。
在 SoC 设备树 dts/arm64/rockchip/rk3588.dtsi 中,uart2节点描述为:
uart2: serial@feb50000 { compatible = "rockchip,rk3588-uart", "ns16550"; reg = <0xfeb50000 0x100>; interrupts = <GIC_SPI 333 IRQ_TYPE_EDGE IRQ_DEFAULT_PRIORITY>; clock-frequency = <12000000>; reg-shift = <2>; status = "disabled"; };它兼容ns16550驱动,基地址0xfeb50000,通过 GICv3 中断控制器接收 SPI 333 中断(GIC 位于 dts/arm64/rockchip/rk3588.dtsi,地址0xfe600000)。板级 dts 将其status改为okay并覆盖波特率,串口控制台随即生效。
基础版默认配置
rock_5b_plus_defconfig 中开启了以下关键项:
CONFIG_ARM_ARCH_TIMER=y # ARM 架构通用定时器 CONFIG_SERIAL=y # 串口驱动 CONFIG_CONSOLE=y # 控制台子系统 CONFIG_UART_CONSOLE=y # UART 控制台后端 CONFIG_ARMV8_A_NS=y # ARMv8-A 非安全世界 CONFIG_CACHE_MANAGEMENT=y # Cache 管理 CONFIG_TICKLESS_KERNEL=y # 无节拍(tickless)内核其中CONFIG_ARMV8_A_NS=y表明 Zephyr 运行在 ARMv8-A 的非安全(Non-Secure)世界,配合CONFIG_CACHE_MANAGEMENT做缓存管理;CONFIG_TICKLESS_KERNEL=y则让内核在空闲时关闭周期性时钟中断以降低功耗。定时器与 PSCI 依赖见下文 SMP 章节。
串口控制台:UART2 与 1.5 Mbit/s
Zephyr 在 ROCK 5B+ 上使用 UART2 作为串口控制台,波特率为 1.5 Mbit/s(1500000)。这一设置由三处共同决定:
- 板级设备树中
chosen的zephyr,console = &uart2与zephyr,shell-uart = &uart2; - 板级设备树中
&uart2 { current-speed = <1500000>; }; - defconfig 中的
CONFIG_UART_CONSOLE=y。
需要注意的是,1.5 Mbit/s 属于非标准波特率,实际连接时请确保你的 USB 转串口适配器及终端软件(如 minicom、picocom、screen)支持该速率,并据此配置波特率,否则无法正常看到 Zephyr 的启动日志与 shell 输出。
从源码结构可以推断,该串口驱动走 ns16550 兼容路径,reg-shift = <2>表明寄存器按 4 字节步进访问,这些细节在驱动实现中(drivers/serial下的 ns16550 驱动)会被使用,板级无需额外处理。
构建 Zephyr 固件
标准(单镜像)构建
按照文档给出的标准构建方式,以hello_world为例(适用于 Unix 主机):
west build -p always -b rock_5b_plus samples/hello_world构建产物为build/zephyr/zephyr.bin(以及对应的zephyr.elf、zephyr.hex等)。-p always会先执行 pristine 清理,确保构建环境干净。
SMP 变体构建:启用全部 8 核
RK3588 拥有 4 个 Cortex-A55 与 4 个 Cortex-A76 核心,SMP 变体支持全部 8 个核心。构建时板卡名写作rock_5b_plus//smp:
west build -p always -b rock_5b_plus//smp samples/synchronizationboard.yml中socs[].variants[].name: smp定义了该变体,hwmv2 描述文件 rock_5b_plus_smp.yaml 显式声明supported: [smp]。samples/synchronization是多线程同步示例,适合在 SMP 环境下观察多核调度行为。
SMP 变体的配置差异
对比 rock_5b_plus_smp_defconfig 与基础版,SMP 变体额外启用了:
CONFIG_SMP=y # 开启对称多处理 CONFIG_MP_MAX_NUM_CPUS=8 # 最大 CPU 数为 8 CONFIG_PM_CPU_OPS=y # CPU 电源管理操作(PSCI)其设备树 rock_5b_plus_smp.dts 通过#include "rock_5b_plus.dts"直接复用基础设备树,不重复定义硬件节点。
从 SoC 设备树 dts/arm64/rockchip/rk3588.dtsi 可以看到全部 8 个 CPU 节点均已描述:cpu@0~cpu@300为 Cortex-A55,cpu@400~cpu@700为 Cortex-A76,且每个节点都使用enable-method = "psci"。PSCI 节点(dts/arm64/rockchip/rk3588.dtsi)声明为arm,psci-0.2、method = "smc",这正是CONFIG_PM_CPU_OPS=y所对接的 CPU 启动/电源管理通道——Zephyr 通过 PSCI SMC 调用唤醒并管理各核心,这是 8 核 SMP 得以运行的基础。
此外,soc/rockchip/rk35/rk3588/Kconfig.defconfig.rk3588 定义了 SoC 级默认参数:NUM_IRQS = 508(对应 RK3588 丰富的 GIC 中断资源),系统时钟频率取自设备树/cpus/cpu@0的clock-frequency(即 24 MHz 的 Cortex-A55 基准频率,见 dts/arm64/rockchip/rk3588.dtsi)。
通过 U-Boot 引导 Zephyr
ROCK 5B+ 的常规启动流程由 Radxa U-Boot(AArch64 Linux 启动路径)接管,因此需要用legacy U-Boot 镜像(Legacy Image)打包 Zephyr 固件,再由 U-Boot 加载并跳转。
第一步:生成 legacy 镜像
将构建产物zephyr.bin封装为加载地址与入口地址均为0x10000000的 legacy 镜像(这与设备树中dram: memory@10000000声明的运行区域严格对应):
mkimage -C none -A arm64 -O linux -a 0x10000000 -e 0x10000000 \ -d build/zephyr/zephyr.bin build/zephyr/zephyr.img参数含义:
| 参数 | 含义 |
|---|---|
-C none | 不压缩负载 |
-A arm64 | 目标架构为 AArch64 |
-O linux | 操作系统类型标记为 linux(legacy 镜像约定) |
-a 0x10000000 | 负载应加载到的地址 |
-e 0x10000000 | 入口点地址 |
-d | 输入数据文件(zephyr.bin),输出为 zephyr.img |
第二步:准备 FAT 分区与设备树
Radxa U-Boot 的 AArch64 Linux 启动路径要求提供 devicetree。请从 Radxa Linux 发行版中获取rk3588-rock-5b-plus.dtb,然后将rk3588-rock-5b-plus.dtb与zephyr.img一并拷贝到 U-Boot 可访问的 FAT 分区(例如 SD 卡或 eMMC 的 FAT 分区)上。
第三步:查看加载地址环境变量
U-Boot 会为临时加载内核与设备树预留地址,通过环境变量提供。先查询当前取值:
printenv kernel_addr_r fdt_addr_r记录输出的kernel_addr_r与fdt_addr_r(不同 U-Boot 版本或配置下具体地址可能不同,务必以实际打印为准)。
第四步:加载镜像与设备树并 bootm
按对应地址加载两个文件,并把设备树地址传给bootm(-表示跳过 ramdisk)。MMC 设备号与分区号需根据实际启动介质调整,下面的mmc 1:1表示 MMC 设备 1 的第 1 个分区:
fatload mmc 1:1 ${kernel_addr_r} zephyr.img fatload mmc 1:1 ${fdt_addr_r} rk3588-rock-5b-plus.dtb bootm ${kernel_addr_r} - ${fdt_addr_r}启动交接原理:地址为何如此安排
这段流程的背后逻辑值得展开说明:
bootm读取 legacy 镜像头后,会按头部的-a字段把负载从kernel_addr_r搬运到0x10000000,再跳转到入口0x10000000执行 Zephyr;- Zephyr 运行时数据区位于
0x10000000起的 128 MB 区域内(见 rock_5b_plus.dts); - 因此临时镜像、设备树与 Zephyr 运行时区域必须保持分离,避免 U-Boot 搬移镜像或 Zephyr 初始化内存时互相覆盖,导致启动失败。
正是基于这一考虑,文档强调“Keeping the temporary image, devicetree, and Zephyr runtime regions separate avoids overwriting any of them during the handoff”——在自定义启动流程(如调整kernel_addr_r、改用 TFTP 或 NVMe 加载)时,务必核对三者地址区间是否重叠。
参考资料与延伸阅读
- 板卡文档正文:boards/radxa/rock_5b_plus/doc/index.rst
- 板级 BSP:boards/radxa/rock_5b_plus/
- RK3588 SoC 设备树:dts/arm64/rockchip/rk3588.dtsi
- SoC Kconfig:soc/rockchip/rk35/rk3588/Kconfig.defconfig.rk3588
- 官方参考文档:Radxa ROCK 5B+ documentation(详见原文
References一节)
关于 RK3588 更详细的硬件手册、引脚复用与 U-Boot 环境说明,可查阅 Radxa 官方 ROCK 5B+ 文档(原文链接位于 boards/radxa/rock_5b_plus/doc/index.rst 的 References 部分)。
【免费下载链接】zephyrPrimary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.项目地址: https://gitcode.com/GitHub_Trending/ze/zephyr
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考