【原创】IgH EtherCAT主站详解(八)--Master状态机与Slave状态机
一、Master FSM (ec_fsm_master) — 主站状态机
3.4.4.1 — 主站核心状态机,负责总线监控、从站扫描、DC 时间同步与 SII 写入
概览
什么是 Master FSM
Master FSM 是 EtherCAT 主站的核心状态机,运行在内核线程中。它负责:
- 总线监控:周期性广播读取从站数量和 AL 状态,检测拓扑变化
- 从站扫描:当检测到总线变化时,触发完整的从站扫描流程
- DC 时间同步:测量传播延迟、计算并写入时间偏移量
- SII 写入:处理用户空间发起的 EEPROM 写入请求
- 从站重启:执行单个或全部从站的重启操作
Master FSM 由 ec_master_idle_thread()(空闲线程)和 ec_master_operation_thread()(运行线程)在每次循环中调用 ec_fsm_master_exec() 驱动执行。
Master FSM 状态机全图
技术详情
状态详解
| 状态 | 函数名 | 职责 | ESC 寄存器 |
|---|---|---|---|
| start | ec_fsm_master_state_start |
检查紧急请求、重启请求;发送 BRD 获取从站数 | 0x0130 (BRD) |
| broadcast | ec_fsm_master_state_broadcast |
处理广播响应:检测拓扑变化、链路状态、从站状态变化 | 0x0130 (BRD) |
| read_al_status | ec_fsm_master_state_read_al_status |
FPRD 读取单个从站 AL 状态 | 0x0130 (FPRD) |
| reboot_slave | ec_fsm_master_state_reboot_slave |
通过 fsm_reboot 子状态机执行从站重启 | — |
| dc_read_old_times | ec_fsm_master_state_dc_read_old_times |
APRD 读取从站 DC 端口接收时间(扫描前快照) | 0x0900 (APRD) |
| clear_addresses | ec_fsm_master_state_clear_addresses |
BWR 广播清除所有从站站地址 | 0x0010 (BWR) |
| dc_measure_delays | ec_fsm_master_state_dc_measure_delays |
BWR 触发从站锁存传播延迟 | 0x0900 (BWR) |
| scan_slave | ec_fsm_master_state_scan_slave |
等待所有从站完成扫描(scan_required=0) | — |
| dc_read_offset | ec_fsm_master_state_dc_read_offset |
读取 DC 系统时间(0x0910)、偏移(0x0920)、延迟(0x0928) | 0x0910-0x092B (FPRD) |
| dc_write_offset | ec_fsm_master_state_dc_write_offset |
写入新的 DC 时间偏移和传输延迟 | 0x0920-0x092B (FPWR) |
| dc_reset_filter | ec_fsm_master_state_dc_reset_filter |
重置 DC 速度计数器滤波器(写入 0x1000) | 0x0930 (FPWR) |
| write_sii | ec_fsm_master_state_write_sii |
通过 fsm_sii 子状态机写入 EEPROM | 0x0502 |
主循环调用时序
DC 偏移计算
Master FSM 支持 32 位和 64 位两种偏移计算模式,取决于从站的 base_dc_range:
- EC_DC_32:
ec_fsm_master_dc_offset32()— 使用低 32 位计算 - EC_DC_64:
ec_fsm_master_dc_offset64()— 使用完整 64 位计算
容差阈值:EC_SYSTEM_TIME_TOLERANCE_NS = 1000 (1μs)。仅当时间差超过此值时才更新偏移。已在 SAFEOP 及以上状态的从站不会修改偏移,以避免干扰正在运行的 DC 同步。
关键寄存器访问表
| 寄存器地址 | 操作 | 用途 |
|---|---|---|
| 0x0010 | BWR | 广播清除站地址 |
| 0x0130 | BRD / FPRD | 读取 AL 状态 |
| 0x0900 | APRD / BWR | DC 端口接收时间 / 延迟测量 |
| 0x0910 | FPRD | DC 系统时间 (64-bit) |
| 0x0920 | FPRD / FPWR | DC 系统时间偏移 (64-bit) |
| 0x0928 | FPRD / FPWR | DC 传输延迟 (32-bit) |
| 0x0930 | FPWR | DC 速度计数器(滤波器重置) |
| 0x0502 | FPWR / FPRD | SII (EEPROM) 访问 |
深入源码
ec_fsm_master 结构体
| 字段 | 类型 | 说明 |
|---|---|---|
master |
ec_master_t * |
所属主站 |
datagram |
ec_datagram_t * |
使用的 datagram |
retries |
unsigned int |
datagram 超时重试计数 |
state |
void (*)(ec_fsm_master_t *) |
当前状态函数指针 |
dev_idx |
ec_device_index_t |
当前设备索引(支持多设备/冗余) |
idle |
int |
是否处于空闲阶段 |
scan_jiffies |
unsigned long |
扫描开始时间 |
link_state[] |
uint8_t[EC_MAX_NUM_DEVICES] |
上次链路状态 |
slaves_responding[] |
unsigned int[EC_MAX_NUM_DEVICES] |
每设备的响应从站数 |
rescan_required |
unsigned int |
是否需要重新扫描 |
slave_states[] |
ec_slave_state_t[EC_MAX_NUM_DEVICES] |
每设备的从站 AL 状态 |
slave |
ec_slave_t * |
当前操作的从站 |
sii_request |
ec_sii_write_request_t * |
当前 SII 写入请求 |
sii_index |
off_t |
SII 写入数据索引 |
fsm_reboot |
ec_fsm_reboot_t |
从站重启子状态机 |
fsm_sii |
ec_fsm_sii_t |
SII 读写子状态机 |
关键函数
ec_fsm_master_exec()
执行当前状态。如果 datagram 尚未发送/接收则延迟到下一周期。返回 1 表示已执行。
int ec_fsm_master_exec(ec_fsm_master_t *fsm)
{
if (fsm->datagram->state == EC_DATAGRAM_SENT
|| fsm->datagram->state == EC_DATAGRAM_QUEUED) {
return 0; // datagram 未完成
}
fsm->state(fsm); // 执行当前状态
return 1;
}
ec_fsm_master_state_start()
入口状态。依次检查紧急寄存器请求、重启请求,最终发送 BRD 读取从站数量。设置 fsm->idle = 1。
ec_fsm_master_state_broadcast()
核心决策状态。处理逻辑:
- 检查 WKC 变化 → 标记 rescan_required
- 检测链路断开 → 清除从站列表
- 读取 AL 状态变化 → 日志记录
- 遍历所有设备索引(主/备用)
- 如果需要扫描 → 分配从站内存、进入扫描流程
- 如果配置变化 → 进入 DC 写入流程
- 否则 → 逐从站读取 AL 状态
DC 偏移写入流程
enter_write_system_times() → dc_read_offset → dc_write_offset → dc_reset_filter 对每个支持 DC 的从站依次执行。
- 跳过不支持 DC 或不支持系统时间的从站
- 32 位模式:适用于
base_dc_range == EC_DC_32 - 64 位模式:适用于
base_dc_range == EC_DC_64 - 已运行从站(≥SAFEOP)不修改偏移,避免干扰
源文件索引
| 文件 | 说明 |
|---|---|
master/fsm_master.h |
Master FSM 结构体和接口声明 |
master/fsm_master.c |
Master FSM 状态实现 (~1430 行) |
master/master.c |
调用方:idle_thread / operation_thread |
master/fsm_reboot.c |
子状态机:从站重启 |
master/fsm_sii.c |
子状态机:SII/EEPROM 访问 |
二、Slave FSM (ec_fsm_slave) — 从站状态机
3.4.4.2 — 每个从站独立运行的请求分发状态机,负责扫描、配置和各类协议请求处理
概览
什么是 Slave FSM
Slave FSM 是每个 EtherCAT 从站独立运行的状态机(各从站之间无耦合、互不等待)。它负责:
- 请求分发:在
ready状态按优先级轮询各类请求 - 从站扫描:触发并等待 Slave Scan FSM 完成
- 从站配置:调用 Slave Config FSM 执行状态转换
- SDO 请求:处理 CoE SDO 上传/下载
- 字典请求:读取从站 SDO 字典
- 寄存器请求:直接读写从站 ESC 寄存器
- FoE 请求:固件升级文件传输
- SoE 请求:伺服驱动 IDN 访问
- EoE 请求:以太网隧道 IP 参数设置
- MBG 请求:邮箱网关透传
每个从站拥有独立的 ec_fsm_slave_t 实例,由 Master FSM 通过 ec_fsm_slave_exec() 在每个周期驱动。
Slave FSM 状态机全图
技术详情
状态详解
| 状态 | 函数名 | 职责 | 委托子 FSM |
|---|---|---|---|
| idle | ec_fsm_slave_state_idle |
空闲状态,不处理任何请求 | — |
| ready | ec_fsm_slave_state_ready |
按优先级轮询所有待处理请求 | — |
| scan | ec_fsm_slave_state_scan |
执行从站扫描(EEPROM/PDO) | fsm_slave_scan |
| acknowledge | ec_fsm_slave_state_acknowledge |
确认 AL 错误标志(ACK_ERR) | fsm_change |
| config | ec_fsm_slave_state_config |
执行从站配置和状态切换 | fsm_slave_config |
| dict_request | ec_fsm_slave_state_dict_request |
读取 SDO 字典 | fsm_coe |
| sdo_request | ec_fsm_slave_state_sdo_request |
处理 SDO 上传/下载请求 | fsm_coe |
| reg_request | ec_fsm_slave_state_reg_request |
直接读写从站寄存器 | 直接 FPRD/FPWR |
| foe_request | ec_fsm_slave_state_foe_request |
处理 FoE 文件传输请求 | fsm_foe |
| soe_request | ec_fsm_slave_state_soe_request |
处理 SoE IDN 请求 | fsm_soe |
| eoe_request | ec_fsm_slave_state_eoe_request |
处理 EoE IP 参数设置请求 | fsm_eoe |
| mbg_request | ec_fsm_slave_state_mbg_request |
处理邮箱网关透传请求 | fsm_mbg |
请求分发优先级
ready 状态按以下优先级顺序检查请求(前面的优先级更高):
| 优先级 | 请求类型 | 检查函数 | 说明 |
|---|---|---|---|
| 1 (最高) | Scan | ec_fsm_slave_action_scan |
slave->scan_required 为真时触发 |
| 2 | Config | ec_fsm_slave_action_config |
含 AL 确认和配置下发 |
| 3 | 内部 SDO | ec_fsm_slave_action_process_config_sdo |
配置中的 SDO 请求 |
| 4 | 内部 SoE | ec_fsm_slave_action_process_config_soe |
配置中的 SoE 请求 |
| 5 | 字典读取 | ec_fsm_slave_action_process_dict |
SDO 字典获取 |
| 6 | 外部 SDO | ec_fsm_slave_action_process_sdo |
用户空间 SDO 请求 |
| 7 | 寄存器 | ec_fsm_slave_action_process_reg |
直接寄存器读写 |
| 8 | FoE | ec_fsm_slave_action_process_foe |
固件传输 |
| 9 | 外部 SoE | ec_fsm_slave_action_process_soe |
用户空间 SoE 请求 |
| 10 | EoE | ec_fsm_slave_action_process_eoe |
IP 参数设置 |
| 11 (最低) | MBG | ec_fsm_slave_action_process_mbg |
邮箱网关 |
请求处理时序
寄存器请求说明
寄存器请求不使用子 FSM,直接通过 datagram 操作 ESC 寄存器:
EC_DIR_INPUT:FPRD 读取EC_DIR_OUTPUT:FPWR 写入EC_DIR_BOTH:FPRW 读写
深入源码
ec_fsm_slave 结构体
| 字段 | 类型 | 说明 |
|---|---|---|
slave |
ec_slave_t * |
所属从站 |
list |
struct list_head |
链表节点(标记是否已在执行列表中) |
state |
void (*)(ec_fsm_slave_t *, ec_datagram_t *) |
当前状态函数指针 |
datagram |
ec_datagram_t * |
使用的 datagram |
sdo_request |
ec_sdo_request_t * |
当前处理的 SDO 请求 |
reg_request |
ec_reg_request_t * |
当前处理的寄存器请求 |
foe_request |
ec_foe_request_t * |
当前处理的 FoE 请求 |
soe_request |
ec_soe_request_t * |
当前处理的 SoE 请求 |
eoe_request |
ec_eoe_request_t * |
当前处理的 EoE 请求 |
mbg_request |
ec_mbg_request_t * |
当前处理的 MBG 请求 |
dict_request |
ec_dict_request_t * |
当前处理的字典请求 |
int_dict_request |
ec_dict_request_t |
内部字典请求(自动获取) |
fsm_coe |
ec_fsm_coe_t |
CoE 子状态机 |
fsm_foe |
ec_fsm_foe_t |
FoE 子状态机 |
fsm_soe |
ec_fsm_soe_t |
SoE 子状态机 |
fsm_eoe |
ec_fsm_eoe_t |
EoE 子状态机 |
fsm_mbg |
ec_fsm_mbg_t |
MBG 子状态机 |
fsm_pdo |
ec_fsm_pdo_t |
PDO 子状态机 |
fsm_change |
ec_fsm_change_t |
状态转换子状态机 |
fsm_slave_config |
ec_fsm_slave_config_t |
从站配置子状态机 |
fsm_slave_scan |
ec_fsm_slave_scan_t |
从站扫描子状态机 |
关键函数
ec_fsm_slave_exec()
执行当前状态。返回 1 表示 datagram 被使用(状态机正在处理请求),返回 0 表示空闲。非 idle/ready 状态时 datagram 的 device_index 设为从站所属设备。
ec_fsm_slave_state_ready()
核心分发状态。按优先级依次调用 action_scan → action_config → action_process_config_sdo → action_process_config_soe → action_process_dict → action_process_sdo → action_process_reg → action_process_foe → action_process_soe → action_process_eoe → action_process_mbg。第一个返回非零的 action 将 FSM 切换到对应处理状态。
ec_fsm_slave_action_config()
配置分发逻辑:
- 检查
error_flag→ 跳过 - 检查 AL ACK_ERR → 进入 acknowledge
- 检查
current_state != requested_state或force_config→ 进入 config - 支持
EC_QUICK_OP:SafeOP→OP 快速切换(跳过完整配置)
源文件索引
| 文件 | 说明 |
|---|---|
master/fsm_slave.h |
Slave FSM 结构体和接口声明 |
master/fsm_slave.c |
Slave FSM 状态实现 (~1400 行) |
master/master.c |
调用方:ecrt_master_send/receive_ext |

浙公网安备 33010602011771号