
在上一篇文章中我们从源码结构入手梳理了 IgH EtherCAT Master 中master.c、slave.c、domain.c、datagram.c以及各种fsm_xxx.c文件之间的关系。如果第一次接触 IgH看到这些代码时很容易产生一个疑问EtherCAT 主站启动以后到底是怎么把一条总线上的几十个从站一步一步“拉起来”的为什么有时候执行ethercat slaves可以看到设备但应用程序就是不能正常运行为什么一个伺服驱动器明明已经被扫描到了却一直停留在 PREOP为什么有些设备能够进入 SAFEOP却无法进入 OP为什么 PDO 已经配置了通信数据仍然没有正常更新这些问题表面上看起来属于不同故障实际上背后往往都和同一个机制有关EtherCAT 的状态机。EtherCAT 并不是主站启动以后马上就把所有设备切换到 OP 状态。一个完整的 EtherCAT 系统启动过程通常需要经历设备发现、从站信息读取、状态切换、邮箱通信、PDO 配置、同步管理器配置、FMMU 配置、分布式时钟配置以及最终进入 OP 等多个阶段。IgH EtherCAT Master 并不是通过一个巨大的初始化函数“一次性完成”这些事情而是把复杂过程拆分成多个状态机由 Master FSM、Slave Scan FSM、Slave Configuration FSM、PDO FSM、SII FSM、CoE FSM 等多个状态机协同完成。官方 1.6 文档中也将这些状态机分别列出包括 Master、Slave Scan、Slave Configuration、PDO、SII、CoE 等 FSM。所以如果真正想读懂 IgH 的启动过程与其只记住 INIT、PREOP、SAFEOP、OP 四个状态不如进一步理解谁负责状态切换谁负责扫描设备谁负责读取设备信息谁负责配置 PDO谁负责发送这些请求这才是理解 IgH EtherCAT Master 源码的关键。一、EtherCAT 为什么需要 INIT、PREOP、SAFEOP、OP 四个状态很多初学者第一次接触 EtherCAT 时会把 INIT、PREOP、SAFEOP、OP 理解成简单的“四级启动状态”。这种理解并不完全错误但还不够准确。更准确地说这四个状态代表的是 EtherCAT 从站在应用层状态机AL State Machine中所处的不同阶段。IgH 的应用接口中直接定义了EC_AL_STATE_INIT 1 EC_AL_STATE_PREOP 2 EC_AL_STATE_SAFEOP 4 EC_AL_STATE_OP 8也就是说IgH 在 API 层面直接提供了对 EtherCAT AL 状态的抽象。可以先把整个过程简单理解成EtherCAT Slave INIT │ ▼ PREOP │ ▼ SAFEOP │ ▼ OP但是这张图只是帮助我们建立第一层认识。真正工程实践中状态之间并不是简单的“程序启动 → INIT → PREOP → SAFEOP → OP”。因为每次状态转换背后都可能伴随着大量配置操作。例如INIT │ ├─ 识别设备 ├─ 读取 SII ├─ 建立邮箱配置 │ ▼ PREOP │ ├─ CoE / SDO 通信 ├─ PDO Mapping ├─ PDO Assignment ├─ Sync Manager ├─ 其他从站参数 │ ▼ SAFEOP │ ├─ 检查输入输出配置 ├─ 检查过程数据 ├─ 配置 DC ├─ 等待从站满足运行条件 │ ▼ OP │ └─ 正式进入周期性过程数据交换这也是为什么一个 EtherCAT 设备“能够被扫描到”并不意味着它已经能够正常工作。1. INIT设备刚刚被主站接管INIT 是 EtherCAT 从站比较基础的状态。从 IgH 源码定义来看INIT 的描述是INIT state (no mailbox communication, no IO)也就是说在 INIT 状态下从站还没有进入正常的邮箱通信和 I/O 过程数据交换阶段。因此可以把 INIT 理解成“我已经存在于 EtherCAT 总线上但还没有进入真正的应用层通信阶段。”这一步最重要的事情之一是让主站认识这个设备。例如Vendor ID Product Code Revision Serial / Device Information SII Information其中一个重要来源就是 SII。SII 可以理解为从站内部保存设备描述信息的一块区域。IgH 中专门存在fsm_sii.c fsm_sii.h对应ec_fsm_sii官方文档将其定义为 Slave Information Interface FSM并记录了它所使用的 Datagram、重试次数、SII 读取状态以及读取偏移等信息。所以当你在源码中看到fsm_sii.c不要简单地认为这是“读取一个配置文件”。它实际上承担的是主站通过 EtherCAT 通信读取从站内部信息并将这些信息整理为主站可以使用的数据结构。2. PREOP开始真正配置设备PREOP即 Pre-Operational。如果把 INIT 理解成“认识这个设备”那么 PREOP 可以理解成“开始准备这个设备怎么工作。”这个阶段非常重要因为大量 EtherCAT 设备的配置工作都会发生在这里。尤其是采用 CoE 的设备主站可以通过邮箱机制进一步访问对象字典。例如伺服驱动器经常会存在大量对象0x6040 Controlword 0x6041 Statusword 0x6060 Modes of operation 0x6061 Modes of operation display 0x6064 Position actual value 0x606C Velocity actual value 0x607A Target position这些对象并不是 EtherCAT 本身直接规定所有设备都必须一样而是与设备所采用的应用层协议、设备规范等有关。在大量工业设备中CoE也就是 CANopen over EtherCAT是非常重要的一种邮箱协议。IgH 中对应的实现就是fsm_coe.c fsm_coe.h官方源码中可以看到CoE FSM 会处理字典访问、SDO 请求等流程并通过 mailbox 机制完成通信。因此在 PREOP 阶段我们可能看到这样的过程EtherCAT Master │ │ CoE / SDO ▼ EtherCAT Slave │ ├── 读取对象 ├── 修改对象 ├── 配置参数 └── 配置 PDO这就是为什么很多设备虽然已经被扫描出来但仍然没有办法直接进入 OP。设备存在 ≠ 设备已经完成配置。二、SAFEOP 到底“安全”在哪里SAFEOP 是很多初学者最容易误解的一个状态。很多人看到名字里的 Safe就会认为“设备已经可以安全运行了。”实际上并不是这样。SAFEOP 更接近于从站已经完成了进入运行状态前的重要配置并允许过程数据相关机制进入一个受控状态但还没有真正进入完整的 OP 运行阶段。这里最重要的是理解PREOP ↓ SAFEOP ↓ OP并不是配置完成 ↓ SAFEOP ↓ 已经开始正常控制SAFEOP 更像是一个非常重要的“检查点”。SAFEOP 为什么是 EtherCAT 调试中的高频状态因为从 PREOP 到 SAFEOP 之间会涉及大量配置是否正确。例如PDO Mapping Sync Manager FMMU Watchdog Distributed Clocks 设备参数 邮箱配置 从站自身状态只要其中某些配置不满足设备要求就可能出现PREOP → SAFEOP 失败或者SAFEOP → OP 失败所以工程人员看到SAFEOP ERROR时不能简单地认为“网络有问题。”实际上网络可能完全正常。因为主站能够找到设备 ↓ 可以读取从站信息 ↓ 可以与从站交换 EtherCAT Datagram已经说明通信链路至少在一定程度上是工作的。真正的问题可能发生在设备配置 PDO Sync Manager 状态转换条件 Watchdog DC 应用层参数这就是 EtherCAT 调试最重要的思维之一先判断问题发生在哪一层而不是看到 OP 失败就直接怀疑网线。三、OP 才是真正进入周期性控制阶段OP也就是 Operational。到了这个阶段EtherCAT 从站才真正进入正常的过程数据运行状态。如果是一套典型的运动控制系统Linux / RTOS │ ▼ EtherCAT Master │ ▼ EtherCAT Network │ ├── Servo 1 ├── Servo 2 ├── I/O ├── Encoder └── Other Devices进入 OP 后主站才真正按照控制周期持续执行Receive ↓ Process Data ↓ Control Algorithm ↓ Update PDO ↓ Send例如一个 1 ms 周期的控制系统t0 Receive ↓ Read PDO ↓ Control ↓ Write PDO ↓ Send t1 Receive ↓ Read PDO ↓ Control ↓ Write PDO ↓ Send t2 ...这时候我们上一篇文章讨论的ecrt_master_receive(); ecrt_domain_process(); control(); ecrt_domain_queue(); ecrt_master_send();才真正进入核心运行阶段。所以从整个 EtherCAT 系统来看INIT / PREOP / SAFEOP更多解决的是设备发现与配置。而OP解决的是周期性实时过程数据交换。这两个阶段一定要区分。四、从 IgH 源码看状态切换到底是谁完成的如果只看 EtherCAT 协议很容易把整个过程理解成Master ↓ Slave ↓ State Change但是在 IgH 源码里面真正的实现要复杂得多。上一篇文章我们已经提到了fsm_master.c fsm_slave.c fsm_slave_config.c fsm_sii.c fsm_pdo.c fsm_pdo_entry.c fsm_coe.c fsm_change.c这些文件并不是重复实现同一件事情。它们实际上形成了一套分层的状态机体系。官方文档中明确列出了 Master FSM、Slave Scan FSM、Slave Configuration FSM、PDO Configuration FSM、SII FSM、CoE FSM 等多个状态机。可以把它理解成Master FSM │ ┌────────────┼────────────┐ │ │ │ Slave Scan Slave Config Requests │ │ │ ├── SII │ ├── PDO │ ├── CoE │ ├── DC │ └── State Change │ ▼ Slave State这也是阅读 IgH 源码时非常值得建立的一张“脑图”。1. Master FSM整个总线的大管家IgH 的 Master FSM 位于fsm_master.c fsm_master.h官方文档对 Master State Machine 的描述非常关键。它主要承担三个方面的工作监控总线拓扑监控从站应用层状态并进行重新配置处理来自应用程序或外部来源的异步请求。也就是说Master FSM 并不是单纯负责“把设备启动起来”。它还要持续观察总线有没有变化 从站还在不在 从站状态是否正确 有没有需要处理的请求 是否需要重新配置这对于理解工业现场非常重要。因为工业设备不是启动以后就永远稳定。例如设备运行 ↓ 某个从站掉电 ↓ 链路变化 ↓ Master 检测 ↓ 重新扫描/重新配置 ↓ 设备恢复这也是 EtherCAT 主站和简单“发送几个以太网数据包”的程序之间的根本区别之一。五、Slave Scan FSM主站是怎么认识设备的当 EtherCAT 主站第一次面对一条总线时它并不知道到底有几个设备 设备是什么 Vendor ID 是多少 Product Code 是多少 Revision 是多少 设备支持哪些功能 邮箱在哪里 PDO 是什么因此首先要进行扫描。IgH 专门设计了fsm_slave.c相关 Slave FSM 和fsm_slave_config.c配置 FSM。此外官方文档还单独定义了ec_fsm_slave_scan也就是 Slave Scan State Machine。可以简单理解成Master │ ▼ Scan │ ├── Slave 0 ├── Slave 1 ├── Slave 2 └── Slave N对于每一个从站主站需要逐步建立自己的认知。最终形成类似Slave #0 Vendor xxx Product xxx Revision xxx Slave #1 Vendor xxx Product xxx Revision xxx这样的内部信息。六、SII为什么读取从站信息不能简单理解成“读配置文件”这是阅读 IgH 源码时另一个容易产生误解的地方。SII 经常被理解成“从站的配置文件。”严格来说这个说法不够准确。SII 是 Slave Information Interface。从站内部保存了一些与设备身份、功能和配置有关的信息。IgH 通过fsm_sii.c对应的状态机访问这些信息。从源码结构可以看到SII FSM 自己拥有slave datagram retries state word_offset mode value等状态信息。这说明它本质上是一个通过 EtherCAT Datagram 分阶段读取从站信息的状态机。因此源码阅读时不要把SII理解成一个普通的 XML 文件。XML/ESI 文件更多是工程配置层面的设备描述。而 SII 则是从站实际能够提供给主站读取的信息来源之一。两者在工程实践中有关联但不是完全相同的东西。七、Slave Configuration FSM真正负责“把设备配置起来”如果说Slave Scan解决的是“你是谁”那么Slave Configuration解决的就是“你准备怎么工作”IgH 中对应fsm_slave_config.c fsm_slave_config.h这个模块是理解整个启动过程的重点。从官方源码可以直接看到它包含多个不同阶段例如INIT Clear Sync Mailbox Sync SDO Configuration SAFEOP DC OP源码中甚至可以看到ec_fsm_slave_config_state_safeop() ec_fsm_slave_config_state_op() ec_fsm_slave_config_state_dc_cycle() ec_fsm_slave_config_state_dc_start()等状态处理函数。这意味着从 PREOP 到 SAFEOP再到 OP并不是简单地写一个状态寄存器就结束了。IgH 会根据配置要求执行一系列子状态机。八、PDO 配置为什么会成为启动过程中的关键步骤对于实时工业控制来说真正每个周期都要传输的数据通常并不是 SDO。而是 PDO。例如Master → Servo Controlword Target Position Target Velocity Target Torque以及Servo → Master Statusword Actual Position Actual Velocity Actual Torque这些数据最终需要被映射到过程数据区域。因此 IgH 中又存在fsm_pdo.c fsm_pdo_entry.c两个非常重要的模块。官方源码文件列表明确将其定义为PDO configuration state machine PDO mapping state machine所以一个典型的配置过程可以抽象为从站 │ ├── 识别 │ ├── 读取 SII │ ├── 进入 PREOP │ ├── 配置 PDO │ ├── 配置 Sync Manager │ ├── 配置 FMMU │ ├── 配置 DC │ ├── 请求 SAFEOP │ └── 请求 OP这里需要特别注意不同从站的实际配置流程会因为设备类型、厂商实现和协议支持情况而不同。因此上面的流程应该作为理解 IgH 架构的模型而不能理解成所有 EtherCAT 从站都严格执行完全相同的每一步。九、为什么 IgH 需要这么多 Datagram看到这里可能会出现一个新的问题“既然这些都是状态机状态机怎么真正和从站通信”答案还是我们上一篇文章讲过的Datagram。可以把整个机制理解成FSM │ │ 产生操作 ▼ Datagram │ ▼ EtherCAT Master │ ▼ Ethernet NIC │ ▼ EtherCAT Slave │ ▼ Response │ ▼ Datagram │ ▼ FSM例如SII FSM需要读取某个 SII 地址。它不会直接“读取”。而是SII FSM ↓ 构造 Datagram ↓ 发送 ↓ 等待返回 ↓ 解析 Datagram ↓ 更新 FSM 状态 ↓ 进入下一个 state这就是状态机非常重要的一个设计思想一次操作完成后不是整个流程结束而是推动 FSM 进入下一个状态。十、IgH 的 FSM 为什么要拆成这么多状态如果把整个启动过程写成一个函数理论上当然可以。比如init_slave(); read_sii(); configure_pdo(); configure_dc(); switch_safeop(); switch_op();看起来非常简单。但真实工业现场远没有这么简单。因为任何一次操作都有可能超时 失败 重试 没有响应 状态不符合预期 设备断线 设备重新上线 配置错误 邮箱错误 SDO Abort WKC 异常因此状态机模型更适合工业通信。例如STATE A │ ├── success → STATE B │ ├── timeout → retry │ └── error → ERROR甚至可以STATE A ↓ STATE B ↓ STATE C ↓ 子 FSM │ ├── success │ └── error ↓ STATE D这就是 IgH 源码看起来“很复杂”的真正原因。复杂的不是 EtherCAT 本身而是工业通信必须认真处理各种异常路径。十一、一个设备从启动到 OP完整过程可以怎么理解现在把前面的内容串起来。假设系统里面有Linux │ └── IgH EtherCAT Master │ ├── Servo A ├── Servo B ├── IO Module └── Encoder启动以后可以把整个过程抽象成下面这样① Master 初始化 │ ▼ ② 扫描 EtherCAT 总线 │ ▼ ③ 发现 Slave │ ▼ ④ 读取 SII │ ▼ ⑤ 建立 Slave 信息 │ ▼ ⑥ 状态切换到 PREOP │ ▼ ⑦ Mailbox / CoE / SDO │ ▼ ⑧ PDO 配置 │ ▼ ⑨ Sync Manager / FMMU │ ▼ ⑩ Distributed Clocks │ ▼ ⑪ 请求 SAFEOP │ ▼ ⑫ 检查配置 │ ▼ ⑬ 请求 OP │ ▼ ⑭ 周期性 PDO 通信这就是一套完整 EtherCAT 控制系统从“认识设备”走向“实时运行”的基本逻辑。而 IgH 的不同 FSM就是分别承担这里面的不同阶段。十二、为什么“能扫描到设备”不代表 EtherCAT 工作正常这是工业现场特别容易出现的误区。比如执行ethercat slaves看到0 0:0 PREOP Servo Drive 1 0:1 PREOP I/O Module很多人第一反应是“设备已经连接成功。”实际上只能说明主站已经能够识别这些从站并获得一定的信息。但真正的目标通常是OP如果停在INIT可能涉及设备初始化 链路 状态切换 扫描如果停在PREOP需要进一步关注邮箱 CoE SDO PDO 设备配置如果到了SAFEOP但进不了OP则需要重点检查PDO Sync Manager FMMU DC Watchdog 设备状态 应用层配置当然实际诊断不能机械地按照这个列表判断而应该结合AL Status Code WKC 主站日志 从站日志 PDO 配置 设备手册 ESI 现场链路进行交叉判断。十三、PREOP 卡住应该怎么排查假设Slave 0 PREOP首先不要马上重启整个系统。可以按照层次逐步判断。第一层设备是否真的被识别检查Vendor ID Product Code Revision以及ethercat slaves ethercat master ethercat pdos等信息。目标是确认主站看到的设备是不是你认为的那个设备。第二层设备支持什么协议检查CoE FoE SoE EoE等邮箱协议能力。例如如果后续配置依赖 CoE而设备本身并不支持对应功能那么问题自然不会通过“重新发送一次命令”解决。IgH 的 CoE FSM 中也会明确检查从站是否支持 CoE。官方源码中可以看到如果从站没有对应 mailbox protocolFSM 会报告不支持 CoE。第三层SDO 配置是否正确检查Index Subindex Data Size Data Type Access以及设备手册要求的参数。特别是伺服驱动器某些厂商要求进入特定状态后才能写某些对象。因此对象存在并不等于当前状态允许写入第四层PDO 是否正确例如应用程序认为0x6040 0x607A是输出数据。但设备实际 PDO Mapping 并不是这样。最终可能出现主站认为配置成功 设备却无法进入正常工作状态所以 PDO Mapping 是非常关键的一层。十四、SAFEOP 卡住为什么尤其值得关注 PDO因为到了 SAFEOP系统已经越过了最基础的设备识别和部分配置阶段。这时候如果PREOP → SAFEOP或者SAFEOP → OP出现问题就应该重点考虑过程数据配置例如PDO Mapping Sync Manager FMMU Watchdog DC尤其对于运动控制设备来说PDO 是实时控制数据的核心通道。假设一个伺服控制周期是1 ms那么每个周期可能需要完成Master Read ↓ Statusword Actual Position Actual Velocity ↓ Control Algorithm ↓ Controlword Target Position Target Velocity ↓ Master Send如果 PDO 映射错误后面所有实时控制算法都没有意义。十五、OP 状态之后问题就一定解决了吗当然不是。这是理解 EtherCAT 实时系统非常重要的一点。进入 OP 只代表从站已经进入正常运行状态。它不意味着控制周期一定稳定 抖动一定很小 CPU 一定没有干扰 EtherCAT 一定没有丢周期 伺服一定运行良好 控制算法一定满足实时性例如EtherCAT Slave OP但 Linux 调度出现2 ms 3 ms 1 ms 5 ms这样的周期抖动。那么即使 EtherCAT 总线本身工作正常整个控制系统仍然可能出现问题。因此必须建立一个非常重要的概念EtherCAT 的确定性通信能力和操作系统的任务执行确定性是两个不同层次的问题。EtherCAT 解决的是工业通信IgH 解决的是Linux 上的 EtherCAT Master 实现而实时 Linux / 实时操作系统解决的是任务什么时候能够被调度 中断什么时候得到处理 实时线程会不会被普通任务干扰 控制周期是否稳定最终的工业控制系统实际上是多个层次共同作用┌───────────────────────────┐ │ Control Algorithm │ ├───────────────────────────┤ │ Application │ ├───────────────────────────┤ │ Real-time Runtime │ ├───────────────────────────┤ │ Linux / RTOS │ ├───────────────────────────┤ │ IgH EtherCAT Master │ ├───────────────────────────┤ │ NIC / Driver │ ├───────────────────────────┤ │ EtherCAT Network │ ├───────────────────────────┤ │ Servo / IO / Sensor │ └───────────────────────────┘任何一层出现明显的不确定性都可能最终反映到控制系统。十六、从 IgH 源码继续往下读下一步应该看什么到了这里我们已经可以把 IgH 的启动过程建立成一张比较完整的源码地图。第一层应用接口ecrt.h ecrt.c解决应用程序怎么使用 EtherCAT Master第二层Mastermaster.c master.h fsm_master.c fsm_master.h解决整个 EtherCAT 总线怎么管理第三层Slaveslave.c slave.h fsm_slave.c fsm_slave.h解决单个从站怎么管理第四层Configurationfsm_slave_config.c fsm_pdo.c fsm_pdo_entry.c fsm_sii.c fsm_change.c解决从站怎么识别 怎么配置 怎么切换状态 怎么配置 PDO第五层Mailbox / CoEfsm_coe.c mailbox.c sdo_request.c解决如何进行非周期性参数访问 如何访问对象字典第六层Datagramdatagram.c datagram.h解决这些状态机最终怎么把数据发出去所以到了下一篇我们就可以真正进入 IgH 最核心的通信机制之一Datagram。十七、为什么下一篇要重点讲 Datagram因为前面所有状态机最终都要回答一个问题这些状态机产生的操作到底是怎么变成 EtherCAT 网络上的数据包的例如Master FSM │ Slave FSM │ SII FSM │ PDO FSM │ CoE FSM │ ▼ Datagram │ ▼ EtherCAT Frame │ ▼ NIC Driver │ ▼ EtherCAT Network而 EtherCAT 的一个重要特点就在这里。它不是传统意义上Master ↓ Slave 1 ↓ Slave 2 ↓ Slave 3一个设备一个设备地发送独立以太网数据包。而是可以让多个从站在一个 EtherCAT Frame 的处理过程中完成数据读写。这也是理解Working Counter Logical Address Physical Address Auto Increment Address Process Data Datagram EtherCAT Frame之间关系的关键。再进一步就会进入 EtherCAT 为什么能够用于高实时性工业控制的核心。十八、总结真正理解 IgH不能只记住四个状态如果只记住INIT PREOP SAFEOP OP那么你只是知道了 EtherCAT 的基本状态。真正理解 IgH需要把它们和源码中的 FSM 联系起来IgH EtherCAT Master Master FSM │ ┌─────────────┼─────────────┐ │ │ │ Slave Scan Slave Config Request │ │ │ ┌─────┼─────┐ │ │ │ │ │ SII PDO CoE │ │ │ │ └───────┴─────┴─────┘ │ State Change │ INIT → PREOP → SAFEOP → OP │ ▼ Datagram │ ▼ EtherCAT Network │ ▼ Slave Devices这张图基本可以概括我们今天讨论的内容。而从工程角度来看更重要的是建立下面这个判断框架设备能不能被扫描到解决的是总线发现设备能不能进入 PREOP重点看设备识别 SII 邮箱设备能不能进入 SAFEOP重点看配置 PDO Sync Manager FMMU设备能不能进入 OP重点看过程数据 状态条件 DC Watchdog 设备配置设备进入 OP 后是否真正满足实时控制要求则要继续向下看Datagram NIC Driver IRQ CPU Scheduler 周期 抖动 控制算法也就是说EtherCAT 从站进入 OP只是实时工业控制系统真正开始工作的起点而不是终点。对于 IgH 来说状态机是连接“设备配置”和“实时过程数据”的桥梁。对于 Linux 实时控制系统来说EtherCAT Master 又只是整个实时链路中的一个环节。当我们继续往下研究就会发现一个非常有意思的问题EtherCAT 为什么能够在一个周期内高效处理大量从站的数据这就要从 Datagram、EtherCAT Frame、Logical Address、Working Counter 以及过程数据交换机制讲起。下一篇我们将继续进入 IgH 源码从datagram.c开始详细分析《EtherCAT 为什么能做到实时通信从 IgH Datagram 机制理解工业以太网》届时会把“一个控制周期的数据到底经过了什么路径”完整拆开这也是理解后续 PDO、DC、周期抖动和实时 Linux 的基础。