151 lines
8.1 KiB
Markdown
151 lines
8.1 KiB
Markdown
# 02-项目程序开发详细步骤
|
||
|
||
## 阶段 0:基线固定
|
||
|
||
1. 记录当前实现与 LinuxCNC 主循环差距。
|
||
2. 固定当前通过的 smoke:
|
||
- `./tools/verify_task_hal_source_manifest.sh`
|
||
- `./tests/wasm/node/verify_motion_hal_sync.sh`
|
||
- `./tests/wasm/node/verify_task_hal_wasm.sh`
|
||
- `./tests/wasm/node/verify_task_hal_sdk.sh`
|
||
3. 记录当前已知阻塞和 readiness:
|
||
- `./tests/native/verify_task_hal_phase0.sh` 曾因上游运行目录缺少 `xyzac-trt_cmds.hal` 失败,T-016 已通过运行目录 machine overlay 修复该 probe 输入完整性。
|
||
- task-hal source manifest 仍显示 `task_hal_runtime_promoted=0`,不代表 full native task/HAL runtime 已 promoted。
|
||
|
||
## 阶段 1:建立 task 周期内 motion snapshot
|
||
|
||
1. 在 `linuxcnc_task_hal_wasm.cpp` 中新增 task runtime 内部 motion snapshot。
|
||
2. 在 `linuxcnc_motion_runtime.h` 中定义 `LcmotStatusSnapshot`,字段至少覆盖:
|
||
- cycle、program_line、motion_id、status、in_position、paused、stepping、aborted;
|
||
- queue_count、queue_capacity、queue_full、active_depth;
|
||
- axis/joint command/feedback;
|
||
- requested/current velocity;
|
||
- switchkins/analog outputs。
|
||
3. 从 `linuxcnc_motion_runtime.c` 暴露结构化读取函数,避免 task 周期内解析 JSON。
|
||
4. 在 `linuxcnc_task_hal_wasm.cpp` 中新增 `wasm_emcMotionUpdate()`,把 `LcmotStatusSnapshot` 映射到 task 持有的 `EMC_STAT.motion` 等价结构。
|
||
5. 在每个 `lctask_run_cycles()` task 周期调用 motion snapshot update。
|
||
6. 将 status JSON 改为读取 task 内已更新的 snapshot,而不是独立拼接最新 motion JSON。
|
||
7. 新增测试:
|
||
- 队列中 motion 状态变化必须在 `runCycles()` 后反映到 task status。
|
||
- 不调用 `runCycles()` 时,仅调用 status API 不应推进 task 周期语义。
|
||
- 直接调用 low-level `lcmot_step_servo()` 后,task status 不应自动更新,直到下一次 `lctask_run_cycles()`。
|
||
|
||
## 阶段 2:重排 `lctask_run_cycles()` 周期顺序
|
||
|
||
目标顺序:
|
||
|
||
1. task heartbeat / cycle 自增。
|
||
2. command read:从 staged command queue 或 C ABI command slot 取命令。
|
||
3. plan:处理模式、run、pause、resume、mdi、home、abort 等 task plan 行为。
|
||
4. execute:根据 task exec state 向 motion/io 发命令或等待 motion/io 完成。
|
||
5. motion update:读取 motion runtime snapshot 到 task 状态。
|
||
6. subordinate sync:处理 estop、motion error、io error、soft limit、abort cleanup 等。
|
||
7. task update:刷新 task-specific status。
|
||
8. status write:更新 C ABI 可读 status snapshot。
|
||
9. servo step:按 standalone WASM 边界推进 deterministic servo cycles。
|
||
|
||
注意:上游 LinuxCNC 是 native process/realtime 拓扑,WASM 内的 servo step 位置允许作为 standalone runtime 边界记录在决策里,但 task 对外语义必须说明与上游差异。
|
||
|
||
建议拆成内部函数,避免把所有逻辑堆回 `lctask_run_cycles()`:
|
||
|
||
```cpp
|
||
static void task_cycle_begin(TaskRuntime &state);
|
||
static bool task_read_command(TaskRuntime &state);
|
||
static int wasm_emcTaskPlan(TaskRuntime &state);
|
||
static int wasm_emcTaskExecute(TaskRuntime &state);
|
||
static int wasm_emcMotionUpdate(TaskRuntime &state);
|
||
static void sync_subordinate_states(TaskRuntime &state);
|
||
static void wasm_emcTaskUpdate(TaskRuntime &state);
|
||
static void update_top_level_status(TaskRuntime &state);
|
||
static void write_status_snapshot(TaskRuntime &state);
|
||
```
|
||
|
||
每个函数必须在注释或文档中标明对应的上游 `emctaskmain.cc` 行为。
|
||
|
||
## 阶段 3:引入 `EMC_STAT` 等价状态容器
|
||
|
||
1. 对齐 `EMC_STAT.task`、`EMC_STAT.motion`、`EMC_STAT.io` 中本阶段需要的字段。
|
||
2. 识别上游真实定义来源:
|
||
- enum 和函数声明主要在 `emc.hh`;
|
||
- `EMC_STAT`、`EMC_TASK_STAT`、`EMC_MOTION_STAT`、`EMC_TRAJ_STAT` 真实字段在 `emc_nml.hh`。
|
||
3. 优先复用 vendored `emc_nml.hh`/`emc.hh` 类型;如依赖过重,建立字段同名、语义同向的窄 `StandaloneEmcStatus`,并记录差异。
|
||
4. 把 `TaskRuntime` 中重复字段逐步映射到 `EMC_STAT.task`。
|
||
5. 把 `lcmot` motion status 映射到 `EMC_STAT.motion`。
|
||
6. 初始 IO 可用 shim 固定 `DONE`,但必须具备 `status`、`aux.estop`、`fault`、`reason` 字段。
|
||
7. 确保 JSON status 只是 `EMC_STAT` 或等价 status buffer 的导出视图。
|
||
|
||
## 阶段 4:迁移 wait/execute 语义
|
||
|
||
1. 对标 `emcTaskExecute()` 的关键状态:
|
||
- `DONE`
|
||
- `WAITING_FOR_MOTION_QUEUE`
|
||
- `WAITING_FOR_MOTION`
|
||
- `WAITING_FOR_IO`
|
||
- `WAITING_FOR_MOTION_AND_IO`
|
||
- `WAITING_FOR_DELAY`
|
||
- `WAITING_FOR_SYSTEM_CMD`
|
||
- `ERROR`
|
||
2. 先迁移 motion 相关状态,不急于实现 system command/process。
|
||
3. `queueFull`、`motion.status`、`io.status` 的判断必须从周期 snapshot 读取。
|
||
4. pause/step/resume 的状态变化必须覆盖现有 smoke。
|
||
|
||
## 阶段 5:逐步替换自有状态机
|
||
|
||
1. 把当前 JSON command 分派收缩为 host/C ABI 边界。
|
||
2. `lctask_send_command_json()` 不直接修改 `state/mode/interp/exec`,而是入队 command envelope。
|
||
3. 在 command read 阶段消费 envelope,生成 LinuxCNC task command 等价物。
|
||
4. 把 task plan/execute 语义迁向 vendored/upstream `emctask.cc`、`taskintf.cc`、`emccanon.cc`。
|
||
5. 为 native-only/runtime-edge 功能建立 shim:
|
||
- NML transport
|
||
- file IO
|
||
- process spawning
|
||
- IO process
|
||
- realtime HAL/thread scheduling
|
||
6. 每替换一段,补一条 matrix 任务和验收证据。
|
||
|
||
具体源码替换顺序见 `08-上游task源码替换分解.md`。实施时按以下顺序推进:
|
||
|
||
1. `taskintf.cc` minimal bridge:先替换 motion init/update/abort、traj pause/step/resume/linear move。
|
||
2. `emctask.cc` state/update/abort:替换 task state/mode/abort/update。
|
||
3. `emctask.cc` plan wrapper:接 interpreter open/read/execute/synch。
|
||
4. `emccanon.cc` straight motion:接 `INIT_CANON()`、`FINISH()`、`STRAIGHT_TRAVERSE()`、`STRAIGHT_FEED()`。
|
||
5. `emctaskmain.cc` execute 分支:用 `interp_list` 和 taskintf issue command。
|
||
6. `emccanon.cc` spindle/tool/io 子集:dwell、switchkins、tool/spindle command。
|
||
|
||
## 阶段 6:readiness 和文档收口
|
||
|
||
1. 修正文档、代码、测试中的 readiness 口径。
|
||
2. `nativeTaskReady` 只有在真实 vendored/native task 周期被采用后才能为 true。
|
||
3. `nativeHalSyncReady` 只有在 HAL 同步达到对应验收后才能为 true。
|
||
4. `fullLinuxCncProgramExecutionReady` 只有在完整 program execution 语义闭合后才能为 true。
|
||
5. 更新 `docs/source-reuse-map.md`,避免文档声称与实现不一致。
|
||
|
||
## 阶段 7:后续 WASM 核心状态机完善
|
||
|
||
本阶段用于后续新增任务,不改变 T-001 到 T-049 的闭合状态。实施前必须先在 `04-任务矩阵.md` 新增任务编号、状态、验收标准和 gate。
|
||
|
||
1. 坚持 WASM/C++ 为核心状态机实现:
|
||
- task/motion 状态机、周期调度、状态聚合、命令执行进入 C/C++。
|
||
- `StandaloneEmcStatus` 或后续 `EMC_STAT` 等价容器是 status 事实源。
|
||
- `LcmotStatusSnapshot` 是 task 周期读取 motion 的结构化输入。
|
||
2. 保持 JS/SDK 为 host 边界:
|
||
- JS/SDK 可以加载 WASM、写入文件、入队 command、读取 status。
|
||
- JS/SDK 不实现 G-code、task、motion、planner 或 canon 语义。
|
||
3. 保持 JSON 为通信格式:
|
||
- command JSON 只描述 host command envelope。
|
||
- status JSON 只导出最后一次 status write。
|
||
- 不允许新增依赖 JSON 文本推进 task cycle 的路径。
|
||
- 新增 status 字段进入 `emcStatus` 对标对象,不再提供旧字段兼容视图。
|
||
4. 每次迁移新语义时优先查找 vendored LinuxCNC source:
|
||
- 能接入 source-anchored subset 时接入 subset。
|
||
- 不能直接接入时建立窄 shim,并在 `06-决策记录.md` 写明原因。
|
||
5. 每次新增状态字段时同步更新:
|
||
- C/C++ status 结构体。
|
||
- status JSON 导出。
|
||
- WASM smoke。
|
||
- SDK smoke。
|
||
- state matrix。
|
||
- source reuse/drift docs gate。
|
||
|
||
详细边界和检查清单见 `11-WASM核心状态机边界与后续完善路线.md`;status JSON 字段映射、禁止链路和后续 SJ 批次见 `12-status-json-LinuxCNC对标方案.md`。
|