Files
cnc_wams/wasm-port/working/02-项目程序开发详细步骤.md
2026-07-09 18:12:01 -04:00

8.1 KiB
Raw Blame History

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()

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.taskEMC_STAT.motionEMC_STAT.io 中本阶段需要的字段。
  2. 识别上游真实定义来源:
    • enum 和函数声明主要在 emc.hh
    • EMC_STATEMC_TASK_STATEMC_MOTION_STATEMC_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,但必须具备 statusaux.estopfaultreason 字段。
  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. queueFullmotion.statusio.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.cctaskintf.ccemccanon.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 motionINIT_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。

阶段 6readiness 和文档收口

  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核心状态机边界与后续完善路线.mdstatus JSON 字段映射、禁止链路和后续 SJ 批次见 12-status-json-LinuxCNC对标方案.md