Files
cnc_wams/wasm-port/working/08-上游task源码替换分解.md
2026-07-08 09:20:47 -04:00

263 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 08-上游 task 源码替换分解
## 目标
本文件把上游 `emctask.cc``taskintf.cc``emccanon.cc` 的替换路线拆成可实施步骤。目标不是把三个文件一次性塞进 WASM 构建,而是按 LinuxCNC 语义依赖顺序逐步替换当前 `linuxcnc_task_hal_wasm.cpp` 中的 JSON 自有状态机。
总原则:
- 先建立 `EMC_STAT`、motion snapshot、status buffer、command buffer。
- 再迁 `emctask.cc` 的 task/interpreter/status 管理。
- 再迁 `taskintf.cc` 的 task->motion command issue 和 motion update。
- 最后迁 `emccanon.cc` 的 canon->interp_list command 生成。
- 每迁一个函数族,都必须有 source reuse、shim 边界和 WASM 测试证据。
## 文件职责总览
| 文件 | 上游职责 | WASM 替换目标 |
| --- | --- | --- |
| `emctask.cc` | task mode/state、abort cleanup、interpreter plan open/read/execute/synch、`emcTaskUpdate()` | 替换当前 `TaskRuntime` 中 state/mode/interp/exec 字符串状态和 open/run/MDI 自有逻辑 |
| `taskintf.cc` | task 到 motion 的接口;`emcTraj*``emcJoint*``emcSpindle*``emcMotionInit/Update/Abort` | 替换当前直接 `forward_motion_command()``lcmot_read_status_json()` 拼接路径 |
| `emccanon.cc` | canonical API单位/偏置/速度加速度转换;生成 `EMC_TRAJ_*`、spindle/tool/io command 到 `interp_list` | 替换当前按字符串/G-code line 生成 motion plan/linear move 的自有行为 |
## 迁移依赖链
```text
emctaskmain cycle
-> emcTaskPlan()/emcTaskExecute()
-> interp_list
-> emcTaskIssueCommand()
-> taskintf.cc emcTraj*/emcMotion*/emcJoint*/emcSpindle*
-> lcmot/lchal runtime boundary
-> emccanon.cc canonical functions append commands to interp_list
```
因此迁移顺序必须是:
1. `EMC_STAT`/`interp_list`/command buffer 基础。
2. `taskintf.cc` 的 minimal motion command bridge。
3. `emctask.cc` 的 abort/state/mode/update 和 plan wrapper。
4. `emccanon.cc` 的 linear/traverse/feed/dwell/spindle/tool 子集。
5. 更完整的 interpreter file run 和 MDI 行为。
## `emctask.cc` 分解
### E1状态和 abort 基础
优先函数:
| 函数 | 上游行为 | WASM 实施 |
| --- | --- | --- |
| `emcTaskQueueTaskPlanSynchCmd()` | 向 task command queue 追加 `EMC_TASK_PLAN_SYNCH` | 需要 command queue 支持内部 command |
| `emcTaskAbort()` | `emcMotionAbort()`、清 `emcTaskCommand`、清 `interp_list`、重置 interp/exec/line、queue synch | 替换当前 `EMC_TASK_ABORT` 直接设置字符串状态 |
| `emcTaskSetMode()` | MANUAL/MDI/AUTO 切换并设置 traj mode、abort/synch | 替换当前 SET_MODE 自有逻辑 |
| `emcTaskSetState()` | OFF/ON/ESTOP_RESET/ESTOP 驱动 motion/io/spindle/task abort | 替换当前 SET_STATE 自有逻辑 |
| `determineMode()` | 由 `motion.traj.mode``mdiOrAuto` 推导 task mode | 用 snapshot 推导 status而不是保存字符串 |
| `determineState()` | 由 `io.aux.estop``motion.traj.enabled` 推导 task state | 用 snapshot 推导 status |
| `emcTaskUpdate()` | 更新 mode/state/motionLine/file/active modes | 替换当前 `status_json()` 手写 task 字段 |
| `emcAbortCleanup()` | abort 后清理/消息 | 初期保留 shim后续接 LinuxCNC 行为 |
依赖 shim
- `emcMotionAbort()``emcTrajSetMode()``emcTrajEnable()``emcTrajDisable()`
- `emcIoAbort()``emcAuxEstopOn/Off()`、coolant/spindle shim。
- `interp_list.clear()``emcTaskCommand`
- `emcStatus` 全局或等价容器。
验收:
- SET_STATE/SET_MODE 发送后不立即改变 task 语义;一次 task cycle 后通过 `emcTaskSetState/Mode` 路径改变。
- `emcTaskAbort()``interpState=IDLE``execState=DONE`、line 清零、motion abort command 已发出。
- `emcTaskUpdate()``state/mode/motionLine` 来自 `EMC_STAT.motion/io` snapshot。
### E2plan/interpreter wrapper
优先函数:
| 函数 | 上游行为 | WASM 实施 |
| --- | --- | --- |
| `emcTaskPlanInit()` | 创建/初始化 interpreter、执行 startup code | 先接现有 vendored interpreter init动态 shlib 路径作为非目标 shim |
| `emcTaskPlanSetWait/IsWait/ClearWait()` | 控制 read-ahead waitFlag | 直接迁移 |
| `emcTaskPlanSynch()` | `interp.synch()`,失败 abort | 用 task-held motion position/status 支撑 |
| `emcTaskPlanOpen()` | 打开文件并清 motion/current/read line | 替换 `lctask_open_program()` 中自有 open 状态 |
| `emcTaskPlanRead()` | `interp.read()`,必要时 reopen file | 替换 motion plan 预加载路线 |
| `emcTaskPlanExecute()` | `interp.execute()`MDI 时 `FINISH()` | 接 `emccanon.cc` 后形成 `interp_list` |
| `emcTaskPlanClose/Reset/Line/Level/Command()` | interpreter 状态读写 | 直接对接 vendored interpreter |
依赖 shim
- vendored `Interp` 可编译子集已在 interpreter WASM 中存在,但 task-hal 模块需要链接或抽取共享。
- `FINISH()` 来自 `emccanon.cc`
- `rs274ngc_startup_code`、INI lookup、file staging。
验收:
- `open -> runCycles(read/execute)` 通过 LinuxCNC `Interp::open/read/execute`,不是 JS/JSON motion plan。
- `readLine/currentLine/callLevel/command` 与 upstream interpreter 返回一致。
- MDI command 通过 `emcTaskPlanExecute(command)` 进入 `interp_list`
## `taskintf.cc` 分解
### TIF1motion runtime bridge
优先函数:
| 函数 | 上游行为 | WASM 实施 |
| --- | --- | --- |
| `emcMotionInit()` | `emcTrajInit()`、joint/axis/spindle init、position load | 调用 `lcmot_init_from_ini()` 和 HAL init建立 config defaults |
| `emcMotionAbort()` | jog abort + traj abort | 发 `EMCMOT_ABORT``lcmot` |
| `emcMotionHalt()` | halt/disable/save/exit | standalone shim不能真实硬件 |
| `emcMotionUpdate()` | `usrmotReadEmcmotStatus()` 后更新 traj/joint/axis/spindle/synch IO/heartbeat | 改为 `lcmot_read_status_snapshot()` -> `EMC_MOTION_STAT` |
| `emcTrajUpdate()` | 映射 emcmot status 到 `EMC_TRAJ_STAT` | 复刻字段映射到 snapshot |
| `emcJointUpdate()` | 映射 joint status | 第一阶段只映射 homed/pos/ferror 必需字段 |
| `emcAxisUpdate()` | 映射 axis status | 第一阶段映射 pos cmd/fb |
| `emcSpindleUpdate()` | 映射 spindle status | 初期单 spindle shim后续 orient/atspeed |
依赖 shim
- `usrmot*` 系列函数替换为 `lcmot_*` C ABI。
- `emcmot_command_t` 可复用上游 motion headers或建立命令转换层。
- INI axis/joint/spindle 初始化先使用已有 INI/WASM runtime 或默认值。
验收:
- `emcMotionUpdate(&emcStatus.motion)` 每个 task cycle 调用一次。
- status read 不调用 `emcMotionUpdate()`
- low-level `lcmot_step_servo()` 后 task status 不变,直到 task cycle 调用 `emcMotionUpdate()`
### TIF2traj command issue
优先函数:
| 函数 | 上游行为 | WASM 实施 |
| --- | --- | --- |
| `emcTrajSetMotionId()` | 设置下一个 motion id | 映射到 `lcmot` command id 或 task pending id |
| `emcTrajEnable/Disable/Abort()` | 发 ENABLE/DISABLE/ABORT | 替换当前 state ON/OFF 手写状态 |
| `emcTrajPause/Step/Resume()` | 发 PAUSE/STEP/RESUME | 替换当前 pause/step/resume direct JSON |
| `emcTrajLinearMove()` | 构造 `EMCMOT_SET_LINE` | 替换 `enqueue_linear_move_from_line()` |
| `emcTrajCircularMove()` | 构造 `EMCMOT_SET_CIRCLE` | 后续接 arc/canon |
| `emcTrajDelay()` | task controller 处理 delay | 映射到 `WAITING_FOR_DELAY` |
| `emcTrajSetOffset/G5X/G92/Rotation` 相关 | motion/task offsets | 后续接 `emccanon.cc` offsets |
验收:
- `EMC_TRAJ_LINEAR_MOVE``emcTrajLinearMove()` 路径进入 `lcmot`,而不是 task JSON 自行拼接。
- pause/resume/step 仍通过现有 WASM smoke。
- queueFull 时 `emcTaskExecute()` 进入 `WAITING_FOR_MOTION_QUEUE`
### TIF3joint/jog/spindle/io 命令
优先函数:
| 函数组 | 范围 | 首阶段处理 |
| --- | --- | --- |
| `emcJointHome/Unhome` | homing/unhome | 保留当前 homing smoke但通过 taskintf shim |
| `emcJogIncr/Cont/Abs/Stop` | manual jog | 先迁 `emcJogIncr()` |
| `emcSpindleOn/Off/Speed/Orient` | spindle | 初期 command/event shim后续 snapshot |
| `emcMotionSetAout/Dout` | M62-M68/switchkins | 优先保留 `M428/M429/M430` switchkins 验收 |
验收:
- Home/Jog/switchkins 现有 tests 通过。
- `motion.switchkins-type` 仍同步 HAL。
- spindle/tool 未实现项明确标为 runtime boundary不假装 ready。
## `emccanon.cc` 分解
### C1canon 基础状态和单位转换
优先函数/变量:
| 函数/组 | 上游行为 | WASM 实施 |
| --- | --- | --- |
| `INIT_CANON()``ON_RESET()``FINISH()` | 初始化 canon、丢弃/flush segments | 先直接迁移或抽取 |
| `get_canon()``CanonConfig_t canon` | canon 全局状态 | 使用 vendored类型避免自建 motion plan |
| `GET_EXTERNAL_LENGTH_UNITS()``GET_EXTERNAL_ANGLE_UNITS()` | 从 motion/task status 取单位 | 接 `EMC_STAT.motion.traj.linearUnits/angularUnits` |
| `CANON_UPDATE_END_POINT()` | 更新 canon endpoint | 接 task/motion snapshot |
| `SET_G5X_OFFSET()``SET_G92_OFFSET()``SET_XY_ROTATION()` | 偏置/旋转 | 先保留字段,后续生成 task commands |
验收:
- interpreter 执行时 canon endpoint 与 motion snapshot 可同步。
- 单位换算不再由 JS/JSON motion plan 决定。
### C2直线/圆弧/探测 motion command 生成
优先函数:
| 函数 | 上游行为 | WASM 实施 |
| --- | --- | --- |
| `STRAIGHT_TRAVERSE()` | 生成 `EMC_TRAJ_LINEAR_MOVE` traverse 到 `interp_list` | 第一优先级 |
| `STRAIGHT_FEED()` | 通过 segment queue 生成 feed move | 第一优先级 |
| `generate_fast_move()``generate_move()` | flush 后 append linear move | 作为 STRAIGHT 基础 |
| `ARC_FEED()` | 生成 circular move/segments | 第二阶段 |
| `STRAIGHT_PROBE()` | 生成 `EMC_TRAJ_PROBE` | 第二阶段 |
| `RIGID_TAP()` | 生成 rigid tap | 第二阶段 |
| `SET_MOTION_CONTROL_MODE()` | G61/G64 path control | 与 planner/tolerance 验证绑定 |
依赖 shim
- `interp_list`
- `EMC_TRAJ_LINEAR_MOVE``EMC_TRAJ_CIRCULAR_MOVE` 等 NML command 类型。
- `StateTag`
- velocity/acceleration helpers 的 axis limits 来源。
验收:
- G0/G1 文件执行后 `interp_list` 中出现 LinuxCNC `EMC_TRAJ_LINEAR_MOVE`,再由 `emcTaskExecute()` issue。
- 不再由 `loadProgramMotionPlan(plan_json)` 提供主路径 motion segments。
- line number、motion id、axis endpoint 与 upstream interpreter/canon 输出一致。
### C3spindle/tool/io canonical command
优先函数:
| 函数组 | 上游行为 | WASM 实施 |
| --- | --- | --- |
| `DWELL()` | append `EMC_TRAJ_DELAY` | 接 `WAITING_FOR_DELAY` |
| `START_SPINDLE_*``STOP_SPINDLE_TURNING()``SET_SPINDLE_SPEED()` | append spindle commands | 初期 command/event shim |
| `ORIENT_SPINDLE()``WAIT_SPINDLE_ORIENT_COMPLETE()` | spindle orient wait | 后续接 snapshot |
| `SELECT_TOOL()``CHANGE_TOOL()``CHANGE_TOOL_NUMBER()` | append tool commands | 先支持 T/M6 smoke再接 IO/tool DB |
| `MOTION_OUTPUT_BIT_()``MOTION_OUTPUT_VALUE_()` | M62-M68 motion outputs | 优先用于 switchkins |
| `WAIT()` | M66 input wait | 后续接 motion `synch_di/analog_input` |
验收:
- `M428/M429/M430` 不再 special-case 字符串 MDI而是通过 remap/canon/MOTION_OUTPUT_VALUE_ 到 motion AOUT。
- `DWELL` 进入 task delay state。
- tool/spindle runtime boundary 在 readiness 中保持 false直到有对应验收。
## 替换任务批次
| 批次 | 内容 | 退出条件 |
| --- | --- | --- |
| B1 | taskintf minimal bridge`emcMotionInit/Update/Abort``emcTrajPause/Step/Resume/Abort/LinearMove` | task cycle 内 motion snapshot 和 linear move issue 通过 |
| B2 | emctask state/update/abort`emcTaskAbort/SetMode/SetState/Update` | state/mode/home/run/pause smoke 仍通过,且语义由 task cycle 触发 |
| B3 | emctask plan wrapper`PlanInit/Open/Read/Execute/Synch` | 文件和 MDI 通过 LinuxCNC interpreter/canon 生成 `interp_list` |
| B4 | emccanon straight motion`INIT_CANON/FINISH/STRAIGHT_TRAVERSE/STRAIGHT_FEED` | G0/G1 不再依赖 JSON motion plan |
| B5 | task execute issue`emcTaskExecute()` motion branches + `taskintf` issue | wait/queue/error/top-level status 对标 |
| B6 | emccanon MDI/spindle/tool/io 子集 | MDI、switchkins、dwell、basic tool/spindle command 有验收 |
## 构建策略
1. 不直接修改 `/home/mes123456/cnc_wams/linuxcnc`
2. 优先 vendored source 或可重复 copy/sync 到 `wasm-port/vendor/linuxcnc`
3. 对 runtime-edge 依赖建立 shim
- `usrmot*` -> `lcmot_*`
- NML channels -> in-process command/status buffers
- POSIX process/system command -> blocked/shim
- IO/tool DB/spindle hardware -> minimal status/command shim
4. 每增加一个上游源文件到 build更新
- `tools/task-hal-source-manifest.txt`
- `tools/build_task_hal_wasm.sh`
- `docs/source-reuse-map.md`
- `working/04-任务矩阵.md`
- `working/05-验收证据.md`
## 禁止路线
- 不允许继续把 G-code line 文本在 `linuxcnc_task_hal_wasm.cpp` 中手写解析成 motion。
- 不允许让 `readStatus()` 触发 motion update 来掩盖 task cycle 缺失。
- 不允许把 `nativeTaskReady` 提前置 true。
- 不允许绕过 `interp_list` 直接把 `emccanon.cc` 输出改成 JSON。