Files
cnc_wams/wasm-port/working/07-emctaskmain周期对标蓝图.md
2026-07-09 18:12:01 -04:00

12 KiB
Raw Blame History

07-emctaskmain 周期对标蓝图

对标目标

本蓝图把 LinuxCNC emctaskmain.cc 的 task 主循环拆成 wasm-port 可逐步实现的周期阶段。后续实现不得只在 JSON status 层拼接 motion而必须让 task 周期本身读取并消费 motion snapshot。

上游周期源代码锚点

上游位置 行为 WASM 对标要求
emctask_startup() motion 初始化 emcMotionInit() 后立即 emcMotionUpdate(&emcStatus->motion),失败则启动失败 lctask_init_session() 必须初始化 motion runtime并建立第一份 task 持有的 motion snapshot
主循环 task_beat++ task heartbeat 每周期递增 lctask_run_cycles() 每个 task cycle 增加 task heartbeat/cycle
check_ini_hal_items() 周期检查 INI/HAL 项 standalone 可先记录为 shim 阶段,后续接 HAL/INI 检查
emcCommandBuffer->read() 读取新 task command成功后清 taskPlanError/taskExecuteError JSON C ABI command 应先进入 command buffer/slot再由 task cycle 消费
emcTaskPlan() 处理 task state/mode/interpreter/read-ahead/MDI 队列 当前 lctask_send_command_json() 的状态变化要迁到 plan 阶段
emcTaskExecute() 根据 execState issue command 或等待 motion/io 当前直接 forward motion command 的逻辑要迁到 execute 阶段
emcMotionUpdate(&emcStatus->motion) 每周期读取 motion 状态 每个 lctask_run_cycles() 周期必须执行结构化 lcmot_read_snapshot() 等价调用
volatile home sync motion enabled -> disabled 时 unhome volatile joints standalone 先保留字段/事件,后续接 joints/homing
estop subordinate sync io estop 时 disable traj、abort task/io/spindle、synch plan 需要 task 周期内根据 emcStatus.ioemcStatus.motion 统一处理
motion/io error sync soft-limit、motion error、io hard fault 驱动 abort cleanup 必须新增 motion error 注入测试
emcTaskUpdate(&emcStatus->task) 刷新 task status WASM status snapshot 要从 emcStatus.task 等价结构导出
top-level status aggregation 根据 task/motion/io 状态设置 emcStatus.statustask.status JSON status 中的 task top-level status 必须由聚合结果生成
emcStatusBuffer->write(emcStatus) 写出完整状态 WASM 中写入 last status snapshotSDK read 只读该 snapshot

WASM 周期骨架

目标伪代码:

int lctask_run_cycles(long task_period_ns, long servo_period_ns, int task_cycles)
{
    for each task cycle:
        task_heartbeat++;

        task_cycle_begin();
        check_ini_hal_items_shim();

        command_read_result = wasm_task_command_buffer_read();
        if (command_read_result.new_command) {
            taskPlanError = false;
            taskExecuteError = false;
        }

        if (wasm_emcTaskPlan() != 0) {
            taskPlanError = true;
        }

        if (wasm_emcTaskExecute() != 0) {
            taskExecuteError = true;
        }

        wasm_emcMotionUpdate(&emcStatus.motion);
        wasm_sync_subordinate_states();
        wasm_emcTaskUpdate(&emcStatus.task);
        wasm_update_top_level_status();
        wasm_status_buffer_write(emcStatus);

        lcmot_step_servo(servo_period_ns, servo_per_task);
}

说明:

  • 上游 motion 是独立 realtime 子系统task 读的是 motion 已产生的状态。
  • WASM standalone 需要 deterministic servo step。若先 step servo 再 motion update 才能模拟“读取最新子系统状态”,必须在 06-决策记录.md 明确差异,并用测试固定语义。
  • 无论 servo step 放在周期前还是周期后,emcTaskExecute() 的判断必须读取 task 持有的上一份/本份 motion snapshot不允许临时解析 status JSON。

EMC_STAT 字段映射优先级

第一优先级字段用于让 task 主循环能按 LinuxCNC 结构运行:

LinuxCNC 字段 上游定义 当前/目标 WASM 来源 用途
EMC_STAT.task.state EMC_TASK_STAT.state 当前 TaskRuntime.state -> emcStatus.task.state ESTOP/OFF/ON gate
EMC_STAT.task.mode EMC_TASK_STAT.mode 当前 TaskRuntime.mode -> emcStatus.task.mode MANUAL/MDI/AUTO gate
EMC_STAT.task.execState EMC_TASK_STAT.execState 当前 exec_state -> enum execute 状态机
EMC_STAT.task.interpState EMC_TASK_STAT.interpState 当前 interp_state -> enum read-ahead/pause/run
EMC_STAT.task.currentLine EMC_TASK_STAT.currentLine motion plan/interp list line motion id、UI line
EMC_STAT.task.readLine EMC_TASK_STAT.readLine interpreter read line read-ahead 对标
EMC_STAT.task.motionLine EMC_TASK_STAT.motionLine motion snapshot programLine/id 当前 motion line
EMC_STAT.task.task_paused EMC_TASK_STAT.task_paused pause/step state pause/resume/step
EMC_STAT.motion.status base RCS_STAT_MSG.status lcmot snapshot status wait/error/status aggregation
EMC_STAT.motion.traj.enabled EMC_TRAJ_STAT.enabled state ON/off + motion runtime estop/disable edge
EMC_STAT.motion.traj.inpos EMC_TRAJ_STAT.inpos lcmot.in_position wait-for-motion
EMC_STAT.motion.traj.queue EMC_TRAJ_STAT.queue lcmot.queue_count queue/status aggregation
EMC_STAT.motion.traj.activeQueue EMC_TRAJ_STAT.activeQueue active motion depth queue/status aggregation
EMC_STAT.motion.traj.queueFull EMC_TRAJ_STAT.queueFull queue capacity check WAITING_FOR_MOTION_QUEUE
EMC_STAT.motion.traj.id EMC_TRAJ_STAT.id lcmot.motion_id stepping/current line
EMC_STAT.motion.traj.paused EMC_TRAJ_STAT.paused lcmot.paused pause/step
EMC_STAT.motion.traj.single_stepping EMC_TRAJ_STAT.single_stepping lcmot.stepping step
EMC_STAT.motion.traj.actualPosition EMC_TRAJ_STAT.actualPosition lcmot.axis_fb mapped pose interpreter sync/start line
EMC_STAT.motion.traj.position EMC_TRAJ_STAT.position lcmot.axis_cmd mapped pose UI/canon endpoint
EMC_STAT.motion.on_soft_limit EMC_MOTION_STAT.on_soft_limit future injection/runtime flag soft-limit path
EMC_STAT.io.status EMC_IO_STAT.status initial shim DONE/future IO runtime wait/error aggregation
EMC_STAT.io.aux.estop EMC_IO_STAT.aux.estop task state/IO shim estop subordinate sync

第二优先级字段在 program execution 更深入时补齐:

  • activeGCodesactiveMCodesactiveSettings
  • g5x_offsetg92_offsetrotation_xytoolOffset
  • synch_disynch_doanalog_inputanalog_output
  • spindle orient state/fault
  • toolchanger fault/reason

command read 对标

当前 lctask_send_command_json() 直接修改 task state 或 forward motion。目标结构

  1. lctask_send_command_json() 只把 JSON 解析成 task command envelope写入 WASM command buffer。
  2. lctask_run_cycles() 内的 command read 阶段消费一条 command。
  3. command read 成功后清 taskPlanErrortaskExecuteError
  4. command 的语义处理转入 wasm_emcTaskPlan()wasm_emcTaskIssueCommand()

验收:

  • 调用 sendCommand() 后不调用 runCycles()task state 不发生 LinuxCNC 语义变化。
  • 调用一次 runCycles()command 被计划/执行,状态变化出现。

plan 对标

第一阶段 plan 只迁移现有已支持命令:

  • EMC_TASK_SET_STATE
  • EMC_TASK_SET_MODE
  • EMC_TASK_PLAN_RUN
  • EMC_TASK_PLAN_PAUSE
  • EMC_TASK_PLAN_RESUME
  • EMC_TASK_PLAN_STEP
  • EMC_TASK_ABORT
  • EMC_TASK_PLAN_EXECUTE
  • EMC_JOINT_HOME
  • EMC_JOG_INCR

要求:

  • plan 只决定 task/interp/exec 状态和待执行命令,不直接 step motion。
  • AUTO run 必须通过 state/mode/home/program/motion-plan gates。
  • MDI/JOG/HOME 只生成后续 execute 要 issue 的 command。

execute 对标

第一阶段 execute 对标 emcTaskExecute() 的 motion 相关分支:

  • DONE:从 interp/MDI/jog/home pending command 取命令,检查 motion.traj.queueFullissue command 或进入 wait。
  • WAITING_FOR_MOTION_QUEUE:直到 motion.traj.queueFull == false 才继续。
  • WAITING_FOR_MOTIONmotion.status == ERROR 进入 ERRORmotion.status == DONE 进入 DONE
  • WAITING_FOR_MOTION_AND_IOmotion/io 都 DONE 才完成,任一 ERROR 则 ERROR。
  • ERROR:执行 abort cleanup清 pending command/interp list重置 interp/exec state。

暂缓:

  • WAITING_FOR_SYSTEM_CMD:外部进程 runtime boundary。
  • spindle orient 深度行为:先保留字段和测试入口,后续接 spindle snapshot。
  • toolchanger fault 深度行为:先由 IO shim 固定 DONE。

motion update 对标

必须新增结构化边界,建议名称:

typedef struct LcmotStatusSnapshot { ... } LcmotStatusSnapshot;
int lcmot_read_status_snapshot(LcmotStatusSnapshot *out);

要求:

  • lcmot_read_status_snapshot() 不推进 servo不消费队列只复制当前 motion runtime 状态。
  • wasm_emcMotionUpdate(&emcStatus.motion) 只把 LcmotStatusSnapshot 映射到 EMC_MOTION_STAT 等价结构。
  • lctask_read_status_json() 只导出最后一次 wasm_status_buffer_write() 的结果。

验收:

  • 先写入 motion command不跑 task cyclestatus 不应被 task semantic 更新。
  • 跑 task cycle 后task-held motion.traj.queue/queueFull/id/inpos/position 更新。
  • 直接调用 low-level lcmot_step_servo() 后,除非再跑 task cycle否则 task status snapshot 仍保持上一周期。

subordinate sync 对标

第一阶段需要覆盖:

  1. motion.traj.enabled 从 true 到 false 时,清 homed 或记录 volatile-home TODO。
  2. io.aux.estop == true 且 motion enabled 时,执行 traj disable、task abort、io abort、spindle abort shim、plan synch。
  3. motion.status == ERROR && motion.on_soft_limit 时,进入 soft-limit reporting path。
  4. motion.status == ERROR 或 hard IO error 时,执行 abort cleanup。
  5. 根据 task/motion/io 三方状态聚合 top-level RCS_STATUS::ERROR/DONE/EXEC

status write 对标

WASM 需要引入 task status buffer 等价物:

  • TaskRuntime.last_status_snapshot
  • StandaloneEmcStatus emcStatus
  • lctask_read_status_json() 从该 snapshot 序列化

要求:

  • status read 不改变 task/motion/io 状态。
  • status read 不直接调用 lcmot_read_status_json() 改变观察口径。
  • debug/event log 可以单独存在,但不能替代 status buffer。

status JSON 只是 status buffer 的 host/browser 序列化格式。后续新增 LinuxCNC 对标字段时,字段应先进入 StandaloneEmcStatus 或后续 EMC_STAT 等价容器,再导出到 emcStatus JSON 对象;旧 taskmotionStatus 等顶层状态字段不再作为兼容视图输出。具体字段映射和 SJ 批次见 12-status-json-LinuxCNC对标方案.md

替换上游源码路线

阶段 引入源 目标
R1 emc_nml.hh 必需 enum/status 子集或 vendored include 用 LinuxCNC 状态类型替换字符串状态
R2 emctaskmain.cc 周期骨架等价函数 建立 task main loop 结构
R3 taskintf.cc motion issuing 可编译子集 用上游 task interface 发 motion command
R4 emctask.cc state/mode/task update 可编译子集 减少自有 task state logic
R5 emccanon.cc canonical motion command 子集 interpreter/canon 到 motion 命令更接近上游

每一阶段必须满足:

  • source reuse map 更新。
  • build 脚本增量编译。
  • Node WASM smoke 不回退。
  • 新增至少一个对标断言。