【原创】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 状态机全图

stateDiagram-v2 [*] --> start: FSM 初始化/重启 state "总线监控阶段" as Monitor { start --> broadcast: BRD 读取从站数量(0x0130) broadcast --> start: 检查下一个设备 broadcast --> dc_read_old_times: 需要重新扫描 broadcast --> read_al_status: 无需扫描,逐从站检查 read_al_status --> reboot_slave: 从站请求重启 read_al_status --> read_al_status: 下一个从站 reboot_slave --> start: 重启完成 } state "扫描阶段" as Scan { dc_read_old_times --> dc_read_old_times: 下一个从站 dc_read_old_times --> clear_addresses: 全部完成 clear_addresses --> dc_measure_delays: 地址清除完成 dc_measure_delays --> clear_addresses: 下一个设备 dc_measure_delays --> scan_slave: 全部设备完成 scan_slave --> scan_slave: 等待从站扫描完成 } state "DC 同步阶段" as DCSync { scan_slave --> dc_read_offset: 扫描完成,开始DC偏移 dc_read_offset --> dc_write_offset: 偏移量改变 dc_read_offset --> dc_read_offset: 下一个从站(无变化) dc_write_offset --> dc_reset_filter: 写入成功 dc_reset_filter --> dc_read_offset: 下一个从站 } state "辅助任务" as Misc { broadcast --> write_sii: 有 SII 写入请求 write_sii --> write_sii: 继续写入下一个字 write_sii --> start: 全部写入完成 } dc_read_offset --> start: 全部从站DC完成 read_al_status --> write_sii: 有 SII 写入请求

技术详情

状态详解

状态 函数名 职责 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

主循环调用时序

sequenceDiagram participant IT as Idle Thread participant OT as Operation Thread participant FSM as Master FSM participant SlaveFSM as Slave FSM (每个从站) IT->>FSM: ec_fsm_master_exec() FSM->>FSM: start → broadcast Note over FSM: BRD 读取从站数和状态 alt 需要重新扫描 FSM->>FSM: dc_read_old_times FSM->>FSM: clear_addresses FSM->>FSM: dc_measure_delays FSM->>SlaveFSM: set_ready() (触发扫描) FSM->>FSM: scan_slave (等待) FSM->>FSM: dc_read_offset → dc_write_offset else 无需扫描 FSM->>FSM: read_al_status (逐从站) end OT->>FSM: ec_fsm_master_exec() Note over FSM: 配置变化时重写DC偏移

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()

核心决策状态。处理逻辑:

  1. 检查 WKC 变化 → 标记 rescan_required
  2. 检测链路断开 → 清除从站列表
  3. 读取 AL 状态变化 → 日志记录
  4. 遍历所有设备索引(主/备用)
  5. 如果需要扫描 → 分配从站内存、进入扫描流程
  6. 如果配置变化 → 进入 DC 写入流程
  7. 否则 → 逐从站读取 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 状态机全图

stateDiagram-v2 [*] --> idle: 初始化 idle --> ready: set_ready()<br/>Master FSM 触发 ready --> idle: set_unready() state "请求分发 (优先级顺序)" as Ready { ready --> scan: scan_required=1 ready --> acknowledge: AL 错误标志 ready --> config: 需要配置/状态切换 ready --> sdo_request: 内部 SDO 请求 ready --> soe_request: 内部 SoE 请求 ready --> dict_request: 字典请求 ready --> sdo_request: 外部 SDO 请求 ready --> reg_request: 寄存器请求 ready --> foe_request: FoE 请求 ready --> soe_request: 外部 SoE 请求 ready --> eoe_request: EoE IP 参数请求 ready --> mbg_request: MBox Gateway 请求 } scan --> idle: 扫描完成 acknowledge --> ready: 确认完成 config --> ready: 配置完成 dict_request --> ready: 字典获取完成 sdo_request --> ready: SDO 传输完成 soe_request --> ready: SoE 传输完成 reg_request --> ready: 寄存器访问完成 foe_request --> ready: FoE 传输完成 eoe_request --> ready: EoE 设置完成 mbg_request --> ready: MBG 传输完成

技术详情

状态详解

状态 函数名 职责 委托子 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 邮箱网关

请求处理时序

sequenceDiagram participant MF as Master FSM participant SF as Slave FSM participant SubFSM as 子状态机 MF->>SF: set_ready() → 进入 ready Note over SF: 轮询检查各类请求 alt 有 Scan 请求 SF->>SubFSM: fsm_slave_scan_start() SubFSM-->>SF: 扫描完成 → idle else 有 Config 请求 SF->>SubFSM: fsm_slave_config_start() SubFSM-->>SF: 配置完成 → ready else 有 SDO 请求 SF->>SubFSM: fsm_coe_transfer() SubFSM-->>SF: SDO 完成 → ready else 有 FoE 请求 SF->>SubFSM: fsm_foe_transfer() SubFSM-->>SF: FoE 完成 → ready end

寄存器请求说明

寄存器请求不使用子 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()

配置分发逻辑:

  1. 检查 error_flag → 跳过
  2. 检查 AL ACK_ERR → 进入 acknowledge
  3. 检查 current_state != requested_state 或 force_config → 进入 config
  4. 支持 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
posted @ 2026-04-14 21:36  沐多  阅读(447)  评论(0)    收藏  举报