263 lines
13 KiB
Markdown
263 lines
13 KiB
Markdown
# 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。
|
||
|
||
### E2:plan/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` 分解
|
||
|
||
### TIF1:motion 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()`。
|
||
|
||
### TIF2:traj 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`。
|
||
|
||
### TIF3:joint/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` 分解
|
||
|
||
### C1:canon 基础状态和单位转换
|
||
|
||
优先函数/变量:
|
||
|
||
| 函数/组 | 上游行为 | 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 输出一致。
|
||
|
||
### C3:spindle/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。
|