把 RISC-V 积木教学软件搬到香橙派 RV2:一次 OpenHarmony 移植复盘

我们最开始以为,OpenHarmony 版本只是把 Web 页面塞进一个 HAP 包里。真正跑到香橙派 RV2 上以后,才发现问题不在“能不能显示页面”这么简单,而在 SDK 版本、签名、系统能力、ArkWeb 输入事件、屏幕布局和课堂演示节奏这些细节上。

这篇文章记录的是一次比较真实的移植过程。项目没有重写成完整 ArkUI,也没有把软件模拟说成真实硬件控制。我们做的是把现有 RISC-V 可视化教学软件稳定放到 OpenHarmony 设备端运行,并围绕触屏、教学屏和演示场景做适配。

项目背景

我们的软件面向 RISC-V 指令教学。学生可以用积木拼出 addaddilwswbeqjal 等指令,再观察 PC、寄存器和存储器如何变化。

早期主线是 Windows / Web 版本,核心功能已经比较完整:

  • 左侧选择指令和操作数积木;
  • 中间拼接程序;
  • 右侧查看机器状态、汇编代码和教学说明;
  • 支持单步执行、自动执行、暂停和重置;
  • 用动画显示寄存器、存储器和 PC 的变化。

OpenHarmony 版本的目标不是另起一套 UI,而是把这套教学闭环搬到香橙派 RV2 上。香橙派 RV2 本身是 RISC-V 开发板,运行 OpenHarmony 后,正好可以作为后续实体积木和外设控制路线的主控设备。

为什么没有直接重写 ArkUI

当时摆在面前有两条路。

一条是用 ArkUI 重写界面,积木拖拽、吸附、缩放、撤销、案例导入、执行动画全部重新实现。这样看起来“更原生”,但周期太长,而且很容易让 Windows 版和 OpenHarmony 版分叉。

另一条是保留 Web 主线,把页面作为 rawfile 放进 OpenHarmony 工程,用 ArkTS 创建 ArkWeb 来加载本地页面。我们最后选了这条路。

当前结构大致是:

app/ 主线 Web 界面
→ npm run oh:sync 同步静态资源
→ openharmony-port/entry/src/main/resources/rawfile/app/
→ ArkTS Index.ets 创建 ArkWeb
→ ArkWeb 加载 app/index.html
→ JSBridge 预留原生接口

这个选择保住了已有的教学逻辑。解析器、模拟器、机器状态动画和大部分 UI 都继续来自 app/,OpenHarmony 工程只负责承载、适配和以后接原生能力。

第一个坑:SDK 版本和设备版本并不天然匹配

DevEco Studio 同步工程时,我们先遇到 SDK 路径不合法和找不到 ArkTS、toolchains 的问题。后来发现本机安装的 OpenHarmony SDK 是扁平目录,而 hvigor 期望按 API 版本组织目录。为避免改 DevEco 安装目录,我们在项目里做了一个本地 SDK 镜像,让工程指向 .oh-sdk/24

同步成功以后,真机安装又报过两类问题。

第一类是系统能力不匹配。DevEco 提示设备 rpcid.json 不包含一串系统能力,比如多媒体转码、后台进程管理、部分 ArkUI 能力等。我们的应用并不需要这些能力,于是通过 syscap.json 把不需要的能力从产物里移除。

第二类是 compatibleSdkVersionreleaseType 和设备不匹配。香橙派 RV2 上读取到的是 OpenHarmony 5.0.0.71,API 版本为 12,releaseType 是 Release。工程最初按较新的 SDK 元数据生成,HAP 信息和设备不一致。后来把兼容版本调整到 12,并在本地 SDK 镜像里处理 Release 元数据,才让安装流程走通。

这个阶段最大的经验是:不要只看 DevEco 里能不能 Build。真机的 apiVersionreleaseTypesyscap 都要核对。否则工程能编译,设备照样不收。

第二个坑:签名不是点一下就结束

第一次部署时,HAP 能传到设备上,但安装失败:

Install Failed
error: no signature file

原因很直接,DevEco 当时生成的是 unsigned HAP。后来配置调试签名后,才生成 entry-default-signed.hap,并成功完成:

bm install 成功
aa start 成功
com.riscv.visualteaching successfully launched

OpenHarmony 工程签名里有 .p12、证书、Profile、包名等概念。自动签名能解决大部分调试场景,但工程的包名和 Profile 模板也要对上。我们最后把签名流程写进文档,就是为了避免后面接手的人在“能构建但装不上”这里反复卡住。

第三个坑:ArkWeb 能打开页面,不代表交互都稳定

页面第一次能打开时,我们松了一口气。很快又遇到崩溃。

最典型的问题是拖拽。Windows 浏览器里很自然的 HTML5 drag/drop,在 RV2 的 ArkWeb 上并不稳定。鼠标一拖就可能触发 cpp crash。换成触屏后,大积木能拖,但小积木吸附和页面滚动又会互相影响。

我们尝试过恢复完整拖拽动画,在新的 1080p 屏幕上重新测试,结果仍然闪退。最后的处理比较克制:

  • OpenHarmony 运行时禁用原生 draggabledataTransfer 路径;
  • 保留自定义触摸/鼠标拖拽;
  • 让小积木支持先拖到画布空白区,再二次拖到槽位;
  • 保留点击选择、点击槽位填入的兜底操作;
  • Windows 版继续保留完整拖拽体验,不因为 OpenHarmony 降级。

这个决定有点遗憾,因为积木软件当然应该能拖。但做设备端软件时,稳定性比动画完整更重要。课堂演示中,点击填槽至少能保证教学流程不断。

第四个坑:UI 不是简单放大到 1920×1080

最早用 7 寸 1024×600 屏时,左侧积木栏太窄,右侧机器状态挤在一起,底部日志还会挡住内容。后来换到 1920×1080 屏幕,问题并没有自动消失,只是换了形态:顶部工具栏太长,日志和反馈常驻占空间,右侧辅助栏滚不到底,底部还出现过一条白色区域。

我们后来做了几轮调整:

  • 顶部只保留高频控制,执行相关按钮改回简洁图标;
  • 指令积木栏和编辑区真正左右相邻,不再让素材栏盖住画布;
  • 编辑区标题栏独立占位,网格从标题栏下沿开始;
  • 执行日志和教学反馈改成底部抽屉;
  • 右侧辅助栏支持宽度和高度调整;
  • 辅助栏内部单独滚动,避免存储器区域被底部挡住;
  • 画布增加缩放按钮,便于程序变长后观察整体结构。

其中有一次修底部白条时还出现了主体白屏。最后发现原因是高度链断了:外层用了 100vh,但中间的 main 没有作为 flex 容器继续把剩余高度传下去。修复后,工作区才真正占满剩余空间。

这类问题很难靠想象解决。必须在目标屏幕上看,拖一下,滚一下,跑一遍自动执行,才能知道哪里不舒服。

第五个坑:OpenHarmony 展示和执行动画会抢位置

项目里有一个 OpenHarmony 展示功能,用来说明软件积木、香橙派主控、软总线和后续实体积木之间的关系。后来我们又加了数据动画,用卡片显示寄存器、存储器和 PC 的变化。

一开始两套动画会互相抢右侧辅助栏。打开 OpenHarmony 展示以后,自动执行的数据动画会把展示卡片顶掉,或者展示模式干脆禁用自动执行。

这不符合课堂使用。老师可能一边讲 OpenHarmony 展示,一边执行 RISC-V 指令。于是我们把两者解耦:

  • OpenHarmony 展示只是辅助信息,不接管执行按钮;
  • 单步、自动、暂停、重置仍然控制 CPU 教学模拟;
  • 打开展示时,OpenHarmony 动画保留在辅助栏;
  • 数据执行动画出现时,和 OpenHarmony 展示上下共存;
  • 关闭 OpenHarmony 展示后,对应卡片自动收起。

后来又补了动画暂停。现在数据卡片出现时可以停住看清楚,速度档也从旧的 0.5x 改成新的 1x / 1.5x / 2x。新的 1x 实际上是课堂观察用慢速。

术语也会影响理解

有些修改看起来很小,但对教学很重要。

例如右侧机器状态里,早期写的是“内存”。后来我们改成“存储器”,因为课堂上讲 RISC-V 指令执行时,寄存器和存储器应该分清。数据动画卡片也不再只显示:

0 -> 5

而是显示成:

寄存器 x1: 0 -> 5
PC: 0 -> 1

当一条指令同时改变寄存器和 PC 时,两张卡片左右并排出现。这样学生暂停后能直接看懂:数据写到哪里,PC 又走到了哪里。

机器状态初始化区也做过细调。寄存器/存储器、目标编号、数值、写入、清除这五个控件要放在一行,并且宽度要和上一排进制按钮对齐。这个问题最后定位到 OpenHarmony 专用 CSS 后加载,覆盖了主样式里的五列 grid。主线已经改了,但真机还不变,就要查 openharmony-port.css

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐