13 KiB
13 KiB
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 的自有行为 |
迁移依赖链
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
因此迁移顺序必须是:
EMC_STAT/interp_list/command buffer 基础。taskintf.cc的 minimal motion command bridge。emctask.cc的 abort/state/mode/update 和 plan wrapper。emccanon.cc的 linear/traverse/feed/dwell/spindle/tool 子集。- 更完整的 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/iosnapshot。
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)通过 LinuxCNCInterp::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中出现 LinuxCNCEMC_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 有验收 |
构建策略
- 不直接修改
/home/mes123456/cnc_wams/linuxcnc。 - 优先 vendored source 或可重复 copy/sync 到
wasm-port/vendor/linuxcnc。 - 对 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
- 每增加一个上游源文件到 build,更新:
tools/task-hal-source-manifest.txttools/build_task_hal_wasm.shdocs/source-reuse-map.mdworking/04-任务矩阵.mdworking/05-验收证据.md
禁止路线
- 不允许继续把 G-code line 文本在
linuxcnc_task_hal_wasm.cpp中手写解析成 motion。 - 不允许让
readStatus()触发 motion update 来掩盖 task cycle 缺失。 - 不允许把
nativeTaskReady提前置 true。 - 不允许绕过
interp_list直接把emccanon.cc输出改成 JSON。