【原创】IgH EtherCAT主站详解(九)--从站扫描、配置、AL状态切换状态机
一、Slave Config FSM (ec_fsm_slave_config) — 从站配置状态机
3.4.4.3 — 最大的 FSM (~1940 行),完成从站从 INIT 到 OP 的完整配置流程
概览
什么是 Slave Config FSM
Slave Config FSM 是 IgH EtherCAT Master 中最复杂的状态机,负责将从站从 INIT 状态完整配置到 OP 状态。它按照 AL 状态机的转换要求分阶段执行:
- INIT 阶段:清除 FMMU/SM/DC 分配,配置邮箱 Sync Manager
- Init → Pre-Op:请求 AL 状态转换到 Pre-Op
- Pre-Op 阶段:配置 SDO、SoE、PDO、看门狗
- Pre-Op → Safe-Op:配置 FMMU、过程数据 SM、DC,请求 Safe-Op
- Safe-Op 阶段:配置 SoE (Safe-Op 阶段)
- Safe-Op → Op:请求 OP 状态
每个从站独立执行配置(并行,无耦合),不等待其他从站完成。
Slave Config FSM 状态机全图
技术详情
状态详解
| 状态 | 函数名 | 职责 | ESC 寄存器 |
|---|---|---|---|
| start | ec_fsm_slave_config_state_start |
清除站地址,开始配置流程 | 0x0010 (BWR) |
| quick_start | ec_fsm_slave_config_state_quick_start |
快速 SafeOP→OP 路径(跳过完整配置) | — |
| init | ec_fsm_slave_config_state_init |
读取 AL 状态,检查当前状态 | 0x0130 (FPRD) |
| clear_fmmus | ec_fsm_slave_config_state_clear_fmmus |
清除所有 FMMU 通道 | 0x0600 (FPWR) |
| clear_sync | ec_fsm_slave_config_state_clear_sync |
清除所有 Sync Manager | 0x0800 (FPWR) |
| dc_clear_assign | ec_fsm_slave_config_state_dc_clear_assign |
清除 DC 循环单元分配 | 0x0981 (FPWR) |
| mbox_sync | ec_fsm_slave_config_state_mbox_sync |
配置邮箱 Sync Manager (SM0/SM1) | 0x0800 (FPWR) |
| boot_preop | ec_fsm_slave_config_state_boot_preop |
请求 AL 转换到 Pre-Op | 0x0120 (via fsm_change) |
| sdo_conf | ec_fsm_slave_config_state_sdo_conf |
逐个写入配置 SDO | — (via fsm_coe) |
| soe_conf_preop | ec_fsm_slave_config_state_soe_conf_preop |
逐个写入 Pre-Op 阶段 SoE 配置 | — (via fsm_soe) |
| eoe_conf_preop | ec_fsm_slave_config_state_eoe_conf_preop |
EoE IP 参数配置 | — (via fsm_eoe) |
| pdo_conf | ec_fsm_slave_config_state_pdo_conf |
PDO 分配和映射配置 | — (via fsm_pdo) |
| watchdog_divider | ec_fsm_slave_config_state_watchdog_divider |
写入看门狗分频值 | 0x0400 (FPWR) |
| watchdog | ec_fsm_slave_config_state_watchdog |
写入看门狗超时时间 | 0x0420 (FPWR) |
| pdo_sync | ec_fsm_slave_config_state_pdo_sync |
配置过程数据 Sync Manager (SM2+) | 0x0800 (FPWR) |
| fmmu | ec_fsm_slave_config_state_fmmu |
配置 FMMU 通道(逻辑地址映射) | 0x0600 (FPWR) |
| dc_cycle | ec_fsm_slave_config_state_dc_cycle |
写入 DC SYNC0/SYNC1 周期时间 | 0x09A0 (FPWR) |
| dc_sync_check | ec_fsm_slave_config_state_dc_sync_check |
等待 DC 时钟同步(差值 < 10μs) | 0x092C (FPRD) |
| dc_start | ec_fsm_slave_config_state_dc_start |
写入 DC 起始时间 | 0x0990 (FPWR) |
| dc_assign | ec_fsm_slave_config_state_dc_assign |
激活 DC 循环单元分配 | 0x0981 (FPWR) |
| safeop | ec_fsm_slave_config_state_safeop |
请求 AL 转换到 Safe-Op | 0x0120 (via fsm_change) |
| soe_conf_safeop | ec_fsm_slave_config_state_soe_conf_safeop |
逐个写入 Safe-Op 阶段 SoE 配置 | — (via fsm_soe) |
| op | ec_fsm_slave_config_state_op |
请求 AL 转换到 Op | 0x0120 (via fsm_change) |
| end | ec_fsm_slave_config_state_end |
配置成功完成 | — |
| error | ec_fsm_slave_config_state_error |
配置失败 | — |
配置阶段总览时序
关键 DC 参数
| 常量 | 值 | 说明 |
|---|---|---|
EC_DC_MAX_SYNC_DIFF_NS |
10000 (10μs) | 进入 Safe-Op 前允许的最大时钟差 |
EC_DC_SYNC_WAIT_MS |
5000 (5s) | 等待 DC 时钟同步的最大时间 |
EC_DC_START_OFFSET |
100000000 (100ms) | DC 起始时间偏移量 |
快速 OP 路径
当 EC_QUICK_OP 编译选项启用时,支持从 Safe-Op 快速跳转到 OP(跳过完整配置流程)。条件:上次错误码为 0x001B(Sync Manager 看门狗超时),表示通信中断恢复。
深入源码
ec_fsm_slave_config 结构体
| 字段 | 类型 | 说明 |
|---|---|---|
slave |
ec_slave_t * |
正在配置的从站 |
datagram |
ec_datagram_t * |
使用的 datagram |
state |
void (*)(ec_fsm_slave_config_t *, ec_datagram_t *) |
当前状态函数指针 |
fsm_change |
ec_fsm_change_t * |
AL 状态转换子状态机 |
fsm_coe |
ec_fsm_coe_t * |
CoE 子状态机(SDO 配置) |
fsm_soe |
ec_fsm_soe_t * |
SoE 子状态机 |
fsm_pdo |
ec_fsm_pdo_t * |
PDO 子状态机 |
fsm_eoe |
ec_fsm_eoe_t * |
EoE 子状态机 |
retries |
unsigned int |
Datagram 重试计数 |
sdos_configured |
unsigned int |
已配置的 SDO 数量 |
soes_configured |
unsigned int |
已配置的 SoE 数量 |
dc_start_time |
u64 |
DC 起始时间 |
jiffies_start |
unsigned long |
DC 同步等待起始时间 |
关键函数
ec_fsm_slave_config_start()
标准配置入口。从 INIT 状态开始完整配置流程:清除 FMMU/SM/DC → 配置邮箱 → 切换 Pre-Op → 配置参数 → 切换 Safe-Op → 切换 OP。
ec_fsm_slave_config_quick_start()
快速配置入口。跳过大部分配置步骤,直接从当前状态切换到 OP。用于通信中断后的快速恢复。
dc_sync_check 状态
DC 同步检查循环:
- FPRD 读取 0x092C (System Time Difference)
- 检查差值是否 <
EC_DC_MAX_SYNC_DIFF_NS(10μs) - 超时
EC_DC_SYNC_WAIT_MS(5s) 后放弃等待,直接进入下一阶段 - 差值满足要求后,计算 DC 起始时间 = 当前时间 +
EC_DC_START_OFFSET(100ms)
条件编译状态
| 宏 | 额外状态 | 说明 |
|---|---|---|
EC_SII_ASSIGN |
assign_pdi, assign_ethercat | SII 访问权限切换(EtherCAT ↔ PDI) |
EC_EOE |
eoe_conf_preop | Pre-Op 阶段配置 EoE IP 参数 |
EC_QUICK_OP |
quick_start | 快速 SafeOP→OP 路径 |
源文件索引
| 文件 | 说明 |
|---|---|
master/fsm_slave_config.h |
Slave Config FSM 结构体和接口声明 |
master/fsm_slave_config.c |
Slave Config FSM 状态实现 (~1940 行,最大的 FSM) |
master/fsm_slave.c |
调用方:config 状态 |
master/fsm_slave_scan.c |
调用方:preop 状态(扫描时切换到 Pre-Op) |
二、Slave Scan FSM (ec_fsm_slave_scan) — 从站扫描状态机
3.4.4.4 — 扫描从站基本信息、读取 EEPROM、构建 PDO 映射
概览
什么是 Slave Scan FSM
Slave Scan FSM 负责扫描单个从站的完整信息。当 Master FSM 检测到总线变化时,为每个新发现的从站触发扫描。扫描过程包括:
- 写入站地址(APWR 自动递增地址 → 配置站地址)
- 读取 AL 状态、基础数据(类型、FMMU 数、SM 数、DC 能力)
- 读取 DC 端口接收时间和数据链路状态
- 读取 SII/EEPROM 全部内容(大小探测 → 逐字读取 → 解析分类)
- 将从站切换到 Pre-Op 并读取邮箱配置
- 清空邮箱并读取 PDO 映射
Slave Scan FSM 状态机全图
技术详情
状态详解
| 状态 | 函数名 | 职责 | ESC 寄存器 |
|---|---|---|---|
| start | ec_fsm_slave_scan_state_start |
APWR 写入配置站地址 | 0x0010 (APWR) |
| address | ec_fsm_slave_scan_state_address |
验证地址写入成功 | — |
| state | ec_fsm_slave_scan_state_state |
读取当前 AL 状态 | 0x0130 (FPRD) |
| base | ec_fsm_slave_scan_state_base |
读取 ESC 基础数据:类型/版本/FMMU数/SM数/端口/DC | 0x0000 (FPRD, 12B) |
| dc_cap | ec_fsm_slave_scan_state_dc_cap |
检查 DC 系统时间寄存器是否存在 | 0x0910 (FPRD) |
| dc_times | ec_fsm_slave_scan_state_dc_times |
读取 DC 端口接收时间 | 0x0900 (FPRD, 16B) |
| datalink | ec_fsm_slave_scan_state_datalink |
读取数据链路状态 | 0x0110 (FPRD) |
| attach_sii | ec_fsm_slave_scan_enter_attach_sii |
检查 SII 缓存,创建或复用 SII image | — |
| sii_size | ec_fsm_slave_scan_state_sii_size |
遍历 EEPROM 分类头计算总大小 | 0x0502 (via fsm_sii) |
| sii_data | ec_fsm_slave_scan_state_sii_data |
逐字读取 EEPROM 数据 | 0x0502 (via fsm_sii) |
| sii_parse | ec_fsm_slave_scan_state_sii_parse |
解析 EEPROM 分类:字符串/General/SM/PDO | — |
| preop | ec_fsm_slave_scan_state_preop |
将从站切换到 Pre-Op(委托 fsm_slave_config) | — |
| sync | ec_fsm_slave_scan_state_sync |
读取已配置的 Sync Manager 参数 | 0x0800 (FPRD) |
| mailbox_cleared | ec_fsm_slave_scan_state_mailbox_cleared |
清空邮箱中的旧数据 | — |
| pdos | ec_fsm_slave_scan_state_pdos |
通过 CoE 读取 PDO 分配和映射(委托 fsm_pdo) | — |
| retry | ec_fsm_slave_scan_state_retry |
扫描失败,准备重试 | — |
| retry_wait | ec_fsm_slave_scan_state_retry_wait |
等待 100ms 后重试 | — |
| end | ec_fsm_slave_scan_state_end |
扫描成功完成 | — |
| error | ec_fsm_slave_scan_state_error |
扫描失败 | — |
拓扑扫描时序图
EEPROM 分类解析
| 分类类型 | 值 | 内容 |
|---|---|---|
| Strings | 0x000A | 文本字符串(设备名称、PDO 名称等) |
| General | 0x001E | 设备类别、CoE 详情、FOE 详情、EOE 详情 |
| FMMU 描述 | 0x0028 | FMMU 使用类型 |
| Sync Manager 描述 | 0x0029 | SM 配置信息 |
| TxPDO | 0x0032 | 输入 PDO 映射 |
| RxPDO | 0x0033 | 输出 PDO 映射 |
| 终止标记 | 0xFFFF | 分类列表结束 |
重试机制
扫描失败时自动重试:scan_retries 初始值为 EC_FSM_RETRIES,每次失败递减。重试间隔 SCAN_RETRY_TIME = 100ms。
深入源码
ec_fsm_slave_scan 结构体
| 字段 | 类型 | 说明 |
|---|---|---|
slave |
ec_slave_t * |
正在扫描的从站 |
datagram |
ec_datagram_t * |
使用的 datagram |
state |
void (*)(ec_fsm_slave_scan_t *, ec_datagram_t *) |
当前状态函数指针 |
retries |
unsigned int |
Datagram 重试计数 |
scan_retries |
unsigned int |
扫描重试计数 |
scan_jiffies_start |
unsigned long |
重试等待起始时间 |
sii_offset |
off_t |
当前 SII 读取偏移 |
fsm_sii |
ec_fsm_sii_t |
SII 子状态机 |
fsm_slave_config |
ec_fsm_slave_config_t * |
从站配置子状态机指针 |
fsm_pdo |
ec_fsm_pdo_t * |
PDO 子状态机指针 |
base 状态解析的字段
FPRD 读取 0x0000 处 12 字节,解析出:
| 偏移 | 字段 | 说明 |
|---|---|---|
| +0 | base_type |
ESC 类型 |
| +1 | base_revision |
ESC 修订版本 |
| +2~3 | base_build |
构建号 |
| +4 | base_fmmu_count |
FMMU 通道数 (≤8) |
| +5 | base_sync_count |
Sync Manager 通道数 (≤8) |
| +7 | 端口描述 | 4 端口类型 (每个 2 bit) |
| +8 | 特性标志 | bit0=FMMU位操作, bit2=DC支持, bit3=DC范围(0=32/1=64) |
条件编译特性
| 宏 | 影响 |
|---|---|
EC_SII_ASSIGN |
扫描前先分配 SII 访问权限给 EtherCAT |
EC_SII_CACHE |
缓存 SII 数据,从站重连时复用(按 alias/serial/vendor/product 匹配) |
EC_SII_OVERRIDE |
支持从固件文件加载 SII 数据覆盖 EEPROM |
EC_REGALIAS |
扫描完成后从寄存器 0x0012 读取 alias |
源文件索引
| 文件 | 说明 |
|---|---|
master/fsm_slave_scan.h |
Slave Scan FSM 结构体和接口声明 |
master/fsm_slave_scan.c |
Slave Scan FSM 状态实现 (~1700 行) |
master/fsm_slave.c |
调用方:scan 状态 |
三、State Change FSM (ec_fsm_change) — AL 状态转换状态机
3.4.4.5 — 处理从站 AL 状态转换请求与确认机制
概览
什么是 State Change FSM
State Change FSM 负责处理 EtherCAT 从站 AL (Application Layer) 状态转换。它通过向从站 ESC 的 AL 状态寄存器写入目标状态来请求状态转换,然后轮询检查转换结果。
支持两种工作模式:
- 完整转换模式 (FULL):写入目标状态 → 等待完成 → 处理错误
- 仅确认模式 (ACK_ONLY):仅确认 AL 错误标志,不请求新的状态转换
State Change FSM 状态机全图
技术详情
状态详解
| 状态 | 函数名 | 职责 | ESC 寄存器 |
|---|---|---|---|
| start | ec_fsm_change_state_start |
FPWR 写入目标 AL 状态到 0x0120 | 0x0120 (FPWR) |
| check | ec_fsm_change_state_check |
验证写入 datagram 状态,超时重试 | — |
| status | ec_fsm_change_state_status |
FPRD 读取当前 AL 状态,判断转换结果 | 0x0130 (FPRD) |
| code | ec_fsm_change_state_code |
读取 AL Status Code 获取详细错误信息 | 0x0134 (FPRD) |
| ack | ec_fsm_change_state_ack |
FPWR 写入当前状态以清除 ACK_ERR 标志 | 0x0120 (FPWR) |
| check_ack | ec_fsm_change_state_check_ack |
验证 ACK_ERR 清除是否成功 | 0x0130 (FPRD) |
| end | ec_fsm_change_state_end |
转换成功终止 | — |
| error | ec_fsm_change_state_error |
转换失败终止 | — |
状态转换请求-确认时序
常见 AL Status Code
| 错误码 | 含义 | 常见原因 |
|---|---|---|
| 0x0000 | 无错误 | 正常 |
| 0x0001 | 无错误 (转换完成) | 成功 |
| 0x0011 | 无效的状态转换 | 不允许的转换路径 |
| 0x0012 | 未知状态 | 不支持的状态码 |
| 0x0013 | Bootstrap 不支持 | 从站无 Bootstrap 模式 |
| 0x0014 | 无有效输出数据 | 过程数据输出未配置 |
| 0x0015 | 无效的输出配置 | PDO 映射不匹配 |
| 0x001A | 无效的输入配置 | 输入 PDO 映射错误 |
| 0x001B | 无效的 Sync Manager 配置 | SM 地址/长度错误 |
| 0x001C | 无有效的输入数据 | 输入过程数据无效 |
| 0x0020 | 从站需要重新扫描 | 配置变更 |
| 0x0022 | 无效的 DC 同步配置 | DC SYNC0/1 周期错误 |
| 0x0030 | 无效的 DC 锁存配置 | LATCH 配置错误 |
| 0x0042 | Sync Manager 看门狗 | 过程数据超时 |
| 0x0043 | 无 Sync Manager 看门狗 | 看门狗未激活 |
关键寄存器
| 寄存器地址 | 操作 | 用途 |
|---|---|---|
| 0x0120 | FPWR | AL Control — 写入目标状态或确认当前状态 |
| 0x0130 | FPRD | AL Status — 读取当前 AL 状态(含 ACK_ERR 位 bit4) |
| 0x0134 | FPRD | AL Status Code — 读取详细错误码 |
深入源码
ec_fsm_change 结构体
| 字段 | 类型 | 说明 |
|---|---|---|
slave |
ec_slave_t * |
目标从站 |
datagram |
ec_datagram_t * |
使用的 datagram |
retries |
unsigned int |
超时重试计数 |
state |
void (*)(ec_fsm_change_t *, ec_datagram_t *) |
当前状态函数指针 |
mode |
ec_fsm_change_mode_t |
工作模式: FULL / ACK_ONLY |
requested_state |
ec_slave_state_t |
请求的目标 AL 状态 |
old_state |
ec_slave_state_t |
转换前的原始状态 |
jiffies_start |
unsigned long |
转换计时起始时间 |
take_time |
uint8_t |
是否记录发送时间戳 |
spontaneous_change |
uint8_t |
检测到从站自发状态变化 |
关键实现细节
FSM 实现要点
超时机制:
EC_AL_STATE_CHANGE_TIMEOUT= 5 秒,使用jiffies_start计算重试机制: Datagram 发送失败自动重试
EC_FSM_RETRIES次ACK_ERR 位: AL Status 寄存器 bit4,从站转换失败时置位
自发变化检测:
spontaneous_change检测从站主动上报的状态变化(如掉线后恢复)两种模式: FULL 完整转换流程,ACK_ONLY 仅确认错误标志
源文件索引
| 文件 | 说明 |
|---|---|
master/fsm_change.h |
State Change FSM 结构体和接口声明 |
master/fsm_change.c |
State Change FSM 状态实现 (~600 行) |
master/fsm_slave.c |
调用方:acknowledge 状态和 config 状态 |
master/fsm_slave_config.c |
调用方:各配置阶段的状态转换 |

浙公网安备 33010602011771号