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 偏移量并写入
