规划文档 工程与评审背景 固件与软件架构

背景资料 · 工程与评审背景

固件与软件架构规划

项目内容
文档版本0.1
状态ESP-IDF、C++17、LVGL已确认;模块接口为规划稿
更新日期2026-08-28

1. 技术基线

  • 原生ESP-IDF,正式启动时锁定经过验证的具体版本。
  • C++17用于业务、状态和服务接口;芯片驱动保持C接口兼容。
  • LVGL 9负责静态页面、列表、焦点和后续触摸适配;DisplayService拥有最终刷新权,卡面允许使用专用渲染路径。
  • FreeRTOS使用ESP-IDF内置能力,不增加额外调度框架。
  • FatFS管理MicroSD,NVS管理设置和对局状态,LittleFS保存系统资源和当前卡面缓存。
  • Python负责资源转换、校验和打包。
  • 16MB Flash从首版规划双OTA分区。

不建议以Arduino或PlatformIO作为正式工程基础。依赖版本必须固定,不能自动追随最新版。

2. 仓库规划

CardHelper/
├─ core/                  可移植C++17核心
│  ├─ game_core/
│  ├─ game_sanguosha/
│  ├─ card_model/
│  ├─ resource_model/
│  └─ session_model/
├─ firmware/
│  ├─ main/
│  └─ components/
│     ├─ board/
│     ├─ display/
│     ├─ display_st7305/
│     ├─ input/
│     ├─ storage/
│     ├─ persistence/
│     ├─ rtc/
│     ├─ power/
│     ├─ usb/
│     ├─ wireless/
│     ├─ ui/
│     ├─ diagnostics/
│     └─ updater/
├─ simulator/
├─ tools/cardpack/
├─ schemas/
├─ sample-data/
├─ tests/
├─ hardware/
└─ docs/

core不得引用ESP-IDF、FreeRTOS或LVGL头文件,使游戏规则和状态恢复能够在电脑端直接测试。

3. 分层和依赖

产品应用层

游戏领域层

产品服务层

UI与显示层 / 硬件适配层

依赖只能从上层指向公开接口。GPIO只能出现在Board层,ST7305命令只能出现在对应驱动,三国杀规则只能出现在游戏适配器,UI不能直接写NVS或MicroSD。

4. 单向数据流

建议采用Command/Event模型:

五键、系统或后台结果

     Command

ApplicationController

   GameSession

   StateChanged Event
    ├─ UI刷新
    ├─ 延迟保存
    └─ 日志记录

ApplicationController唯一拥有并修改当前对局。UI、存储和无线任务不能直接修改GameSession。

典型Command包括StartGame、ResumeGame、SelectCard、AdjustHealth、AdjustShield、AdjustToken、UndoLastChange、LockGame、EndGame和EnterSleep。

典型Event包括GameStarted、CardChanged、HealthChanged、SessionSaved、BatteryLow、SdRemoved、DisplayTimeout和OperationRejected。

5. 任务模型

Rev.A保持有限任务数量:

  • UI与应用任务:LVGL、页面、应用控制器和按键意图。
  • 后台工作任务:SD读取、索引、图片和资源校验。
  • 无线任务:Wi-Fi或BLE开启时运行。
  • 系统定时服务:RTC、电量、自动锁定、延迟保存和睡眠判断。

耗时任务通过消息队列返回结果。UI不得等待大文件读取、屏幕BUSY或网络连接。

建议初始队列容量:应用事件32项、输入16项、后台工作8项;显示刷新请求合并。游戏操作、SD拔出、低电和更新结果不得静默丢弃。

6. 组件职责

Board

管理Rev.A引脚、总线、电源控制、硬件版本、唤醒原因和开机按键组合。

DisplayDevice

管理初始化、睡眠、唤醒、能力查询、区域提交、BUSY等待和错误恢复。

DisplayService

管理LVGL、卡面合成、状态层、脏区域合并和刷新策略。业务不直接调用ST7305。

Input

输出KeyDown、KeyUp、ShortPress、LongPress、VeryLongPress和Repeat事件,不自行切页或修改体力。

StorageService

只理解挂载、文件、目录、流和校验,不理解武将规则。

ResourceRepository

理解Catalog、卡牌包、卡池、武将和显示资源,不向UI暴露SD路径。

Persistence

管理设置、A/B对局快照、延迟保存、恢复和版本迁移。

GameCore

管理游戏会话、体力、护盾、Token、撤销、开始和结束。

SanguoshaAdapter

管理三国杀模式、身份、基础体力解释和主公/地主修正。

Diagnostics

提供屏幕、按键、SD、RTC、电池、USB、无线、版本和错误记录诊断。

7. 显示抽象

业务通过产品Display接口使用宽高、颜色能力、局刷能力、刷新边界和刷新成本。ST7305与未来六色屏分别实现接口。

显示链路:

LVGL页面和卡面组件

   画面合成层

   刷新调度器

   具体屏幕驱动

LVGL禁止动画、惯性滚动、高帧率效果和依赖灰色的禁用态。刷新调度器负责合并脏区域、局刷/全刷选择、BUSY等待、超时和重试。阶段0必须规划1-bit、外部字体、局部Flush和未来六色刷新模型的最小验证;若不适配,LVGL仅保留控制页面。

8. 游戏插件边界

建议SD卡只承载内容插件:卡牌图片、属性、卡池、布局和声明式数据。任意机器代码不得从SD加载。

游戏适配器编译进固件并注册到静态Registry。第一阶段由内置SanguoshaAdapter解释SD上的三国杀内容包。未来开放SDK时,适配器仍应经过编译、测试和签名后随固件发布。

9. 对局模型

GameSession至少包含:

  • schemaVersion、sessionId、revision和状态。
  • gameId、packId、cardId、poolId、modeId和roleId。
  • baseHp、maxHp、currentHp和currentShield。
  • Token的ID、名称、数值和范围。
  • startedAt、lastUpdatedAt和elapsedSeconds。
  • locked和最近一次UndoRecord。

生命周期为None、Preparing、Active、Ending和Ended。锁定是Active中的标志,不是独立生命周期。

Rev.A数值上限建议为体力0~99、体力上限1~99、护盾0~99、Token 0~99。资源可以声明更小范围。

10. 异步请求

资源请求携带RequestId和发起时的页面/状态版本。用户快速切换武将时,较早结果即使最后返回也必须丢弃,不能覆盖新选择。

大图片不复制进事件队列,只传受控缓冲区句柄。当前、前一张和后一张可形成有限缓存,不一次加载整个卡牌包。

11. 时间和持久化

ClockService同时提供RTC时间和单调时间。RTC用于日期,单调时间用于按键长按、撤销窗口和持续时长;RTC无效不能影响本次对局。

对局不能直接序列化C++内存结构。使用版本化JSON或CBOR载荷,外层包含Magic、Schema、序号、长度和CRC,并写入A/B快照槽。

12. 错误模型

统一错误包含domain、code、severity、retryable、userMessageId和technicalContext。错误域包括System、Display、Storage、Resource、Game、Persistence、RTC、Power、USB、Wireless和Update。

底层返回稳定错误码,UI根据userMessageId显示中文提示;驱动不得直接返回面向用户的文案。

13. 内存边界

内部SRAM优先存放任务栈、中断数据、DMA缓冲、核心状态和高频对象。PSRAM存放帧缓冲、图片、LVGL大缓冲、索引和JSON解析内存。MicroSD存放卡牌资源。

大缓冲尽量在启动时分配;运行中限制动态分配;DMA缓冲必须位于兼容内存。MVP按500张验收、1,000张压力测试;更大规模需要重新评估JSON解析、字体和缓存。

14. 构建配置

  • rev_a_debug:完整日志、断言、诊断和性能统计。
  • rev_a_release:保留错误日志,关闭高频调试输出。
  • factory_test:自动进行硬件测试,不进入正常游戏。
  • simulator:电脑端300×400屏幕、键盘五键、本地目录模拟SD和文件模拟NVS。

15. Flash分区方向

16MB Flash预留NVS、OTA元数据、Firmware A、Firmware B、LittleFS、Coredump和少量余量。A/B固件各按约4MB级空间规划,具体地址在第一次真实构建后依据固件体积冻结。

16. 开发规则

  • 不使用大量全局单例,依赖在启动入口统一组装。
  • 每个可变状态或硬件资源只有一个任务所有者。
  • 所有硬件操作有超时。
  • 所有外部数据有尺寸、版本和路径校验。
  • 无SD、无网和RTC无效属于正常可处理状态。
  • 每个公开接口同时定义成功、失败和取消行为。
  • 每个设计决策通过decisions.md记录状态。