IgH EtherCAT主站拓扑扫描流程是怎样的?

摘要:目录拓扑扫描流程概览什么是拓扑扫描?地址递增机制技术详情Master FSM 扫描触发流程Slave Scan FSM 完整流程扫描获取的从站信息PDO 映射构建深入源码Slave Scan FSM 状态函数清单Master FSM 扫描触
目录拓扑扫描流程概览什么是拓扑扫描?地址递增机制技术详情Master FSM 扫描触发流程Slave Scan FSM 完整流程扫描获取的从站信息PDO 映射构建深入源码Slave Scan FSM 状态函数清单Master FSM 扫描触发关键代码拓扑扫描时序图 拓扑扫描流程 4.2 — EtherCAT 总线拓扑扫描、从站识别与 PDO 构建 概览 什么是拓扑扫描? 拓扑扫描是 EtherCAT 主站自动识别总线上所有从站设备的过程。主站通过广播读取获取在线从站数量,然后为每个从站分配递增站地址,最后逐个读取从站的 EEPROM 信息(厂商ID、产品码、PDO 映射等),构建完整的从站信息数据库。 扫描触发时机 自动触发: IDLE 线程中 Master FSM 周期性 BRD 广播,检测到从站数量变化时自动扫描 手动触发: ethercat rescan 命令强制重新扫描 热插拔: 从站上线/离线时,WKC 变化触发重新扫描 地址递增机制 技术详情 Master FSM 扫描触发流程 Master FSM 在 start 状态下,通过 BRD 广播读取寄存器 0x0130 获取在线从站数量。当检测到从站数量发生变化时,进入扫描阶段: flowchart TD A["Master FSM: start 状态"] --> B["BRD 读取 0x0130<br/>获取 slaves_responding"] B --> C{"从站数量变化?"} C -->|否| D["检查下一个设备<br/>(主/备)"] D --> B C -->|是| E["dc_read_old_times<br/>读取旧的 DC 时间"] E --> F["clear_addresses<br/>APWR 清除所有站地址"] F --> G["dc_measure_delays<br/>测量传播延迟"] G --> H["scan_slave<br/>触发 Slave Scan FSM"] H --> I["等待扫描完成"] I --> J["dc_read_offset<br/>读取 DC 偏移量"] J --> K["dc_write_offset<br/>写入校正后的偏移量"] K --> L["回到 start 监控"] Slave Scan FSM 完整流程 每个从站由独立的 Slave Scan FSM 进行扫描,包含以下步骤: flowchart TD A["start"] --> B["address: APWR 分配站地址"] B --> C["state: 读取 AL 状态"] C --> D["base: 读取基础寄存器<br/>(类型/端口/特征)"] D --> E["dc_cap: 读取 DC 能力"] E --> F["dc_times: 读取 DC 时间参数"] F --> G["datalink: 读取数据链路状态"] G --> H["assign_sii: 关联 SII 镜像"] H --> I["sii_identity: 读 EEPROM Category<br/>(厂商ID/产品码/版本号)"] I --> J["sii_device: 读设备描述"] J --> K{"支持邮箱?"} K -->|是| L["sii_request: 读邮箱协议"] K -->|否| M["sii_size: 读 PDO 数据"] L --> M M --> N["sii_data: 读 PDO 原始数据"] N --> O["sii_parse: 解析 PDO 映射"] O --> P{"支持邮箱?"} P -->|是| Q["mailbox_cleared: 清空邮箱"] P -->|否| R["regalias: 读注册别名"] Q --> R R --> S["preop: 请求进入 Pre-Op"] S --> T["sync: 配置 Sync Manager"] T --> U["pdos: 配置 PDO 映射"] U --> V["end: 扫描完成"] style A fill:#c6f6d5,stroke:#68d391 style V fill:#c6f6d5,stroke:#68d391 扫描获取的从站信息 阶段 读取内容 源/方法 address 站地址分配 APWR → 0x0010 base 从站类型、端口数量、特征位 BRD → 0x0000–0x0007 dc_cap DC 支持能力(64 位时间/同步信号数) 读寄存器 0x0910 dc_times 传播延迟、系统时间差 DC 测量数据报 datalink 各端口链路状态/通信状态 读寄存器 0x0110–0x0118 sii_identity Vendor ID、Product Code、Revision EEPROM Category 0x30–0x3E sii_parse RxPDO / TxPDO 映射 EEPROM Category 0x32/0x33 sync Sync Manager 配置信息 EEPROM Category 0x29 PDO 映射构建 在 sii_parse 阶段,Slave Scan FSM 解析 EEPROM 中的 PDO Category,构建从站的 PDO 映射表: 读取 EEPROM Sync Manager PDO 分配 Category (0x29):确定每个 SM 关联的 PDO 列表 读取 RxPDO Category (0x32):主站→从站方向的 PDO 映射 读取 TxPDO Category (0x33):从站→主站方向的 PDO 映射 解析每个 PDO Entry:索引号 + 子索引 + 位宽 构建 ec_pdo_list_t 数据结构供后续 Domain 注册使用 PDO 映射示例: 一个从站的 TxPDO 可能有多个 PDO,每个 PDO 包含多个 Entry(如 Status Word: 16bit、Position Actual: 32bit、Torque Actual: 16bit)。这些 Entry 最终通过 FMMU 映射到 Domain 的连续逻辑地址空间。 深入源码 Slave Scan FSM 状态函数清单 源文件: master/fsm_slave_scan.c, master/fsm_slave_scan.h 状态函数 行号 职责 state_start 211 入口:发送 APWR 分配站地址 state_address — 验证地址分配响应 state_state — 读取从站 AL 状态 state_base — 读取从站基础寄存器 state_dc_cap — 读取 DC 能力寄存器 state_dc_times — 读取 DC 时间参数 state_datalink — 读取端口链路状态 state_assign_sii — 查找/创建 SII 镜像 state_sii_identity — 读 EEPROM 厂商/产品信息 state_sii_device — 读 EEPROM 设备描述 state_sii_request — 读 EEPROM 邮箱协议 state_sii_size — 读 EEPROM PDO 数据大小 state_sii_data — 读 EEPROM PDO 原始数据 state_sii_parse — 解析 EEPROM PDO 映射 state_mailbox_cleared — 清空从站邮箱 state_regalias — 读取注册别名 state_preop — 请求进入 Pre-Op state_sync — 配置 Sync Manager state_pdos — 配置 PDO 映射 state_end — 扫描完成 state_error — 错误状态 Master FSM 扫描触发关键代码 源文件: master/fsm_master.c 在 ec_fsm_master_state_broadcast() 中: BRD 读取 0x0130 寄存器,获取响应的从站数量 (slaves_responding) 比较当前值与上次值,如果不同则 fsm->rescan_required = 1 如果需要重新扫描,先读取旧 DC 时间 → 清除地址 → 测量延迟 → 启动扫描 拓扑扫描时序图 sequenceDiagram participant IDLE as IDLE 线程 participant MFSM as Master FSM participant SSFSM as Slave Scan FSM participant SII as SII FSM participant BUS as EtherCAT 总线 loop 每个 IDLE 循环 IDLE->>MFSM: ec_fsm_master_exec() MFSM->>BUS: BRD 读取 0x0130 (从站数量) BUS-->>MFSM: slaves_responding = N end Note over MFSM: 检测到从站数量变化 MFSM->>BUS: APWR 清除所有站地址 MFSM->>BUS: BWR 测量 DC 传播延迟 loop 从站 0 到 N-1 MFSM->>SSFSM: scan_slave(slave[i]) SSFSM->>BUS: APWR 分配地址 = i+1 SSFSM->>BUS: 读取基础寄存器 SSFSM->>BUS: 读取 DC 能力/时间 SSFSM->>BUS: 读取数据链路状态 SSFSM->>SII: 读 EEPROM (identity) SII->>BUS: FPDR 读 EEPROM BUS-->>SII: Vendor ID / Product Code SII-->>SSFSM: 厂商信息 SSFSM->>SII: 读 EEPROM (PDO Category) SII->>BUS: FPDR 读 EEPROM BUS-->>SII: PDO 映射数据 SII-->>SSFSM: PDO 映射表 SSFSM->>BUS: 配置 Sync Manager SSFSM->>BUS: 配置 PDO 映射 SSFSM-->>MFSM: slave[i] 扫描完成 end MFSM->>MFSM: 所有从站扫描完成 MFSM->>MFSM: 计算 DC 偏移量并写入