将一个主流操作系统迁移到一款小众嵌入式设备上,往往意味着要在没有现成驱动的环境中从零构建硬件支持。KING JIM 推出的 Pomera DM250 是一款仅在日本销售的「数字打字机」,其硬件基于 Rockchip RK3128 四核 ARM Cortex-A7 处理器,配备 1GB RAM、8GB eMMC 存储、7 英寸 1024×600 TFT LCD 屏幕,以及全尺寸 SD 卡槽和 USB-C 接口。这款设备出厂运行定制 Linux 系统,但社区开发者 Joshua Stein 用超过一年的时间将其成功迁移到 OpenBSD,这一过程涉及 U-Boot 适配、设备树现代化改造、新增十几个内核驱动的复杂工程。

硬件基础与启动链路挑战

DM250 的核心处理器 RK3128 是 Rockchip 早期面向入门级平板和物联网设备的 SoC,采用 ARMv7 架构的 Cortex-A7 CPU,默认运行频率 600MHz,支持 ARM NEON SIMD 指令集和 VFPv4 浮点单元。该 SoC 集成了双路 MMC 控制器(分别对应 SD 卡和 eMMC)、USB 2.0 Host/Device 控制器、I2C 总线,以及内置的电源管理单元 RK818 PMIC。设备的无线功能由 AMPAK AP6236 Wi-Fi/Bluetooth SDIO 芯片提供,基于 Broadcom BCM43436 芯片方案。

设备出厂搭载的 U-Boot 版本为 2014.10,这是 Rockchip 为 RK3128 定制的古老构建,不支持 EFI 引导,且缺乏现代设备树(Device Tree)所需的诸多特性。要在此硬件上运行 OpenBSD,第一步必须替换引导加载程序。Joshua 通过 UART 调试接口(TTL 级别 115200-8N1)连接设备后发现,原厂 U-Boot 甚至没有正确输出内存检测信息 —— 它报告 512MB 内存而非实际的 1GB。UART 接口位于电路板背面的测试点 TP802-TP804,需要使用 pogo-pin 夹具或焊接线缆才能可靠访问。

U-Boot 升级的核心在于启用 EFI 支持。OpenBSD 的 armv7 引导流程依赖 EFI 运行时服务,因此引导加载程序必须能够加载 EFI 可执行文件(bootarm.efi)并传递设备树二进制(DTB)给操作系统。使用主线上游 U-Boot 代码库时,RK3128 的 MMC 驱动存在初始化时序问题,导致 SD 卡和 eMMC 均无法识别。解决方案是在 u-boot 代码中添加 RK3128 特定的定时器初始化代码,并调整 GPIO 多路复用配置以激活 MMC0 的电源和命令信号线 —— 这些引脚在默认状态下被复用为 JTAG 和 UART2 功能。完成这些修改后,U-Boot 成功从 SD 卡加载 EFI 引导程序并传递给 OpenBSD 内核。

设备树现代化改造

设备树(Device Tree)是 ARM 嵌入式系统中描述硬件拓扑的核心数据结构,它将 SoC 外设寄存器映射、内存布局、中断控制器配置等信息从内核代码中解耦出来。DM250 出厂时在 eMMC 中嵌入的设备树极其老旧,使用了大量 Rockchip 专有的属性名称,这些名称专门适配 Linux 3.10 内核中的 Rockchip 驱动,而非上游 Linux 内核或 OpenBSD 所期望的标准 compatible 字符串。

设备树现代化的第一步是参考上游 Linux 内核和 U-Boot 项目中的 RK3128 评估板设备树定义。Linux 内核中的 rk3128.dtsi 定义了 CPU 核心、时钟控制器(CRU)、中断控制器、GPIO 控制器等基础外设,而 rk3128-xpi-3128.dts 则提供了完整的开发板外设配置示例。OpenBSD 的 armv7 端口期望设备树中的 CPU 节点使用 reg = <0xf00>0xf03 的中断映射值,但原厂设备树错误地使用了 0x0000x003,这导致 cpu0 设备无法正确附加,内核在初始化 ci_flush_bp 回调时因空指针引用而崩溃。这一问题通过修改设备树中的 CPU 节点中断映射得到解决。

除 CPU 中断映射外,设备树还需要为 OpenBSD 新开发的驱动提供正确的节点定义。DM250 的键盘矩阵由 Toshiba TC3589X I2C 键盘控制器管理,电池充电由 RK818 PMIC(或美版 DM250US 中的 TI BQ25620 芯片)负责,LCD 背光通过 PWM 控制,Wi-Fi 模块通过 SDIO 接口连接。这些外设节点需要在设备树中准确描述其 I2C 地址、中断号、GPIO 引脚复用配置等信息,才能被相应的 OpenBSD 驱动正确识别和初始化。

驱动开发与硬件初始化序列

OpenBSD 对 RK3128 的支持几乎是从零构建的。在移植工作之前,OpenBSD 的 armv7 端口缺乏对该 SoC 的时钟管理、GPIO 控制、电源管理等方面的驱动支持。Joshua 为此开发了一系列新驱动,每个驱动对应一类硬件外设。

rkclock 驱动负责时钟配置。RK3128 的时钟和复位单元(CRU)管理所有外设的工作时钟频率。MMC 控制器需要正确设置时钟分频器才能工作在预期速度(例如 SD 卡需要 25MHz 或 50MHz),而网卡的时钟配置也会影响 PHY 链接状态。原厂 Linux 使用 Rockchip 专有的时钟框架进行复杂的 PLL 和分频计算,OpenBSD 驱动需要从 Rockchip 技术参考手册(TRM)中提取寄存器定义并重新实现这些计算逻辑。

rkpmic 与 rkcharger 驱动处理电源管理。RK818 PMIC 集成了多路 DC-DC 降压转换器和 LDO 稳压器,为 CPU、内存、LCD 等部件供电。在设备启动过程中,PMIC 必须按照特定顺序开启各路电源,否则会导致系统不稳定。更关键的是,DM250 的电池充电策略需要正确配置:原厂 U-Boot 会以较高电流(最高 2A)为电池充电,但 OpenBSD 初始版本未能启用快充模式,导致充电速度不足以覆盖设备空闲功耗,电池最终会过度放电而无法启动。rkcharger 驱动通过配置 RK818 的充电电流和电压阈值解决了这一问题,并将电池状态通过 hw.sensors 接口暴露给用户空间。

tcmfd 驱动实现了 TC3589X 键盘控制器的支持。该控制器通过 I2C 总线与 SoC 通信,扫描键盘矩阵并将按键事件转换为标准键盘码。开发过程中遇到的主要挑战是中断机制 —— 键盘控制器支持中断驱动的按键事件报告,但 OpenBSD 的中断子系统在某些配置下无法正确识别卡检测(card-detect)中断。通过在设备树中正确指定 interrupt-parentinterrupts 属性,并确保 GPIO 控制器已正确初始化,中断问题得到解决。

rkdrm、rkvop、rklvds 驱动负责图形输出。RK3128 内置显示控制器(VOP)和 LVDS 发射器,可驱动 1024×600 分辨率的 LCD 面板。OpenBSD 现有的 rkvop 驱动需要针对 RK3128(实际上是 RK3126)进行适配,以支持该芯片特有的寄存器布局。LCD 背光通过 PWM 控制,pwmbl 驱动负责调节亮度。由于 OpenBSD 可以利用 U-Boot 设置的 simplefb 进行控制台输出,图形驱动的开发进度并不影响系统基本功能的使用。

bwfm 驱动处理 Wi-Fi 功能。DM250 使用的 Broadcom BCM43430 SDIO Wi-Fi 模块需要加载固件文件(brcmfmac43430-sdio.bin)和 NVRAM 配置参数。固件加载成功后,bwfm0 设备出现在 sdmmc1 总线上,网络接口 wlan0 可用于无线连接。

工程实践中的关键经验

整个移植过程持续超过一年,开发者总结了若干对后续嵌入式系统迁移项目有指导意义的经验。

首先是 UART 调试的重要性。在缺乏显示输出的早期阶段,UART 是唯一的调试窗口。开发者通过在引导加载程序和内核代码中添加大量的调试输出语句,逐步追踪系统在各个阶段的执行状态。当 MMU 启用后串口输出失效时,需要在页表映射中显式添加 UART 寄存器的虚拟地址映射,确保启用内存管理单元后仍能继续输出调试信息。

其次是 电源和电池管理的优先级。嵌入式设备的功耗策略往往与桌面操作系统有显著差异。DM250 在连接 USB-C 电源时如果电池未充分充电,系统可能会因功率不足而随机重启。理解 PMIC 的充电控制逻辑、确保电池在各种工作状态下的供电稳定性,是系统可靠运行的基础。

第三是 设备树的版本兼容性问题。ARM 生态系统中,不同版本的 Linux 内核和引导程序对设备树格式的期望可能存在差异。移植时应当参考上游主线代码中的设备树定义,而非依赖厂商提供的旧版本。使用标准化的 compatible 字符串和中断映射规范,有助于驱动代码的跨平台兼容性。

第四是 分阶段验证策略。开发者同时维护两台 DM250 设备,一台运行原厂 Linux 用于参考硬件行为,另一台运行实验性的 OpenBSD 构建。通过在 Linux 端添加调试输出编译内核并观察输出,可以验证对硬件寄存器的理解是否正确,然后再将类似逻辑移植到 OpenBSD 驱动中。

当前状态与后续方向

截至 2026 年初,OpenBSD 在 DM250 上已经实现了较为完善的功能支持:图形控制台输出正常、键盘和电池充电可用、Wi-Fi 网络连接正常、SD 卡插槽可热插拔、CPU 频率可根据负载动态调整、红绿双色 LED 指示灯可编程控制。系统可以通过 SD 卡或 eMMC 启动,基本达到可用状态。

仍有待完善的功能包括:Linux DRM 图形加速的完整支持(目前依赖 simplefb)、外设 DMA 引擎以提升 eMMC 读写性能、以及部分电源状态的挂起和恢复(suspend/resume)功能。这些工作需要对 RK3128 的硬件手册进行更深入的解读,并在驱动代码中实现相应的状态保存和恢复逻辑。

开发者已将所有修改的 U-Boot 代码、设备树定义和 OpenBSD 内核补丁发布在 GitHub 上,供有相同设备的用户参考和测试。这一移植案例不仅为 DM250 用户提供了替代操作系统的选择,也为 ARM 嵌入式设备的 OpenBSD 迁移提供了可复用的驱动框架和工程实践参考。


参考资料

  • Joshua Stein, "Pomera DM250 Tinkering", jcs.org, 2025-2026
  • Rockchip RK3128 Technical Reference Manual
  • OpenBSD armv7 端口文档