type
status
date
slug
summary
tags
category
created days
new update day
icon
password
Created_time
Feb 25, 2025 08:58 AM
Last edited time
Mar 6, 2025 03:07 AM
0 获取源码
IgH EtherCAT Master现已迁移到GitLab:https://gitlab.com/etherlab.org/ethercat。文档可以在
ethercat/doc
目录下找到。可以使用以下命令克隆存储库:
此外,还有其他一些EtherCAT主站的实现:
ethercat
ribalda • Updated Feb 27, 2025
基于官方IgH,功能更为全面的EtherCAT主站。
KickCAT
leducp • Updated Feb 28, 2025
一个用C++编写的全新EtherCAT主站,目前功能尚不完善。
ethercrab
ethercrab-rs • Updated Mar 5, 2025
一个用纯Rust语言编写的全新EtherCAT主站,目前功能尚不完善。
本文主要讲解IgH的实现。
1 启动脚本
IgH通过脚本来启动,支持 systemd 与 init.d 启动方式。这些脚本位于源码的
scripts
目录下。script/ethercat.service.in
对于systemd方式,编译时会由
ethercat.service.in
文件生成 ethercat.service
。script/ethercatctl.in
ethercat.service
中指定了执行文件为 ethercatctl
,该文件由 ethercatctl.in
生成。script/init.d/ethercat.in
init.d 和 systemd 方式类似,都是生成一个可执行脚本,且脚本完成的工作一致,主要包括加载主站模块、网卡驱动、给主站内核模块传递参数、卸载模块等操作。
script/ethercat.conf
ethercat.conf
是共同的配置文件,用于配置主站使用的网卡、驱动等信息。下面我们来看 start
和 stop
脚本的具体工作。1.1 start
- 加载
ec_master.ko
模块 main_devices
:主网卡的MAC地址,多个main_devices
表示创建多个主站,MAC参数个数由master_count
决定。backup_devices
:备用网卡的MAC地址,多个backup_devices
表示创建多个备用主站,MAC参数个数由backup_count
决定。debug_level
:调试级别,控制调试信息输出级别。eoe_interfaces
:EOE接口,eoe_count
表示eoe_interfaces
的个数。eoe_autocreate
:是否自动创建EOE handler。pcap_size
:Pcap缓冲区大小。
模块参数包括:
- 读取
/etc/sysconfig/ethercat
中的环境变量DEVICE_MODULES
,该变量位于ethercat.conf
中。
- 在每个
DEVICE_MODULES
前添加前缀ec_
,例如,如果DEVICE_MODULES
为igb
,则添加前缀后为ec_igb
。
- 使用
modinfo
检查该模块是否存在。
- 对于非
generic
和rtdm
的驱动,需要先将网卡与当前驱动unbind
,unbind后的网卡才能被新驱动接管。
- 对于
generic
和rtdm
驱动,需要先将网卡与当前驱动解绑(unbind),解绑后的网卡才能被新驱动接管。
- 加载该驱动。
start
脚本加载了两个内核模块:ec_master.ko
和网卡驱动 ec_xxx.ko
。ec_master
根据内核参数(网卡MAC地址)创建主站实例,此时主站处于 Orphaned
阶段。随后加载网卡驱动 ec_xxx.ko
,执行网卡驱动的 probe
函数,根据MAC地址将网卡与主站实例匹配,此时主站获得操作的网卡设备,进入 Idle
阶段。详细过程将在后文介绍。
1.2 stop
stop
脚本用于卸载内核模块 ec_master.ko
和网卡驱动 ec_xxx.ko
。- 遍历配置文件中的环境变量
DEVICE_MODULES
。
- 在每个
DEVICE_MODULES
前添加前缀ec_
。
- 使用
lsmod
检查该模块是否已加载。
- 卸载模块。
在后文中,“主站”和“master”均表示主站或主站实例对象,“slave”和“从站”表示从站或从站对象,中英混用,不做刻意区分。
2 主站实例创建
在一个使用IgH的控制器中,可以有多个EtherCAT主站。每个主站可以绑定一个主网卡和一个备用网卡,通常备用网卡不启用,只有在启用线缆冗余功能时才使用备用网卡(本文假设只有一个主网卡)。

start 过程中执行
insmod ec_master.ko
,这个时候,先调用的就是 module_init
调用的初始化函数ec_init_module()
。先根据参数main_devices
的个数master_count
,每个master需要一个设备节点来与应用程序交互,所以master_count
决定需要创建多少个matser和多少个字符设备;这里先分配注册
master_count
个字符设备的主次设备号device_number
和名称,这样每个master对应的设备在文件系统中就是/dev/EtherCAT0
、/dev/EtherCAT1
...(Linux下)。解析模块参数得到MAC地址,保存到数组
macs
中。分配
master_count
个主站对象的内存,调用ec_master_init()
初始化这些实例。2.1 Master Phases
IgH中,状态机是其核心思想,所有操作都基于状态机执行。每个EtherCAT主站实例都需要经历以下阶段转换(见图2.3),主站各阶段的操作如下:

- Orphaned phase:此时主站实例已分配并初始化,正在等待以太网设备连接,即尚未与网卡驱动关联,此时无法进行总线通信。
- Idle phase:当主站与网卡绑定后,Idle线程
ec_master_idle_thread
开始运行,主站处于IDLE状态。ec_master_idle_thread
主要完成从站拓扑扫描、配置站点地址等工作。该阶段命令行工具能够访问总线,但无法进行过程数据交换,因为总线配置尚未完成。
- Operation phase:应用程序请求主站提供总线配置并激活主站后,主站进入Operation状态。
ec_master_idle_thread
停止运行,内核线程变为ec_master_operation_thread
,之后应用程序可以周期性地交换过程数据。
在继续讲解
ec_master_init
函数之前,我们先了解数据报与状态机的关系,这对后续理解非常重要。2.2 数据报
2.2.1 EtherCAT 数据报格式
EtherCAT 是以以太网为基础的现场总线系统,EtherCAT 使用标准的 IEEE 802.3 以太网帧,在主站一侧使用标准的以太网控制器,不需要额外的硬件。并在以太网帧头使用以太网类型
0x88A4
来和其他以太网帧相区别(EtherCAT 数据还可以通过 UDP/IP 来传输,本文已忽略),标准的 IEEE 802.3 以太网帧中数据部分为 EtherCAT 的数据,标准的 IEEE 802.3 以太网帧与 EtherCAT 数据帧关系如下:
EtherCAT 数据位于以太网帧数据区,EtherCAT 数据由 EtherCAT头和若干EtherCAT数据报文组成。EtherCAT头中记录了EtherCAT数据报的长度和类型,类型为1表示与从站通信。EtherCAT数据报文内包含多个子报文,每个子报文由报文头、数据和WKC域组成。子报文结构含义如下。

整个EtherCAT网络形成一个环状,主站与从站之间是通过EtherCAT数据报来交互,一个EtherCAT报文从网卡 TX 发出后,从站 ESC 芯片 EtherCAT 报文进行交换数据,最后该报文回到主站。网上有个经典的EtherCAT动态图(刷新后动态图重新播放).
认识 EtherCAT 数据帧结构后,我们看 IgH 内是如何表示一个 EtherCAT 数据报文的?EtherCAT数据报文在 igh 中用对象
ec_datagram_t
表示。2.2.2 ec_datagram_t
结构体
ec_datagram_t
是 IgH EtherCAT 主站中用于表示 EtherCAT 数据报的结构体。EtherCAT 数据报是主站与从站之间通信的基本单元,包含了数据、地址、类型等信息。该结构体定义了数据报的各种属性和状态,用于管理和操作 EtherCAT 通信过程中的数据报。可以看到,上述子报文中的各个字段在
ec_datagram_t
结构体中都有对应的表示。为了避免重复,这里不再详细介绍这些字段,而是重点解释其他几个关键成员的作用。device_index
- 作用:表示该数据报是通过哪个网卡设备发送或接收的。
- 背景:在 IgH 中,一个 master 实例可以绑定多个网卡设备(例如主网卡和备用网卡),用于发送和接收 EtherCAT 数据帧。
device_index
用于标识当前数据报所属的网卡设备。 - 示例:如果 master 绑定了两个网卡,
device_index
可以区分数据报是通过主网卡还是备用网卡发送的。
data_origin
- 作用:表示该数据报的内存来源类别。
- 背景:在 IgH 中,master 管理着多个空闲的
ec_datagram_t
对象,这些对象根据用途被分为不同的类别(例如内部使用、外部使用等)。data_origin
用于标识当前数据报属于哪一类别。 - 后续说明:具体的分类和用途将在后文详细讨论。
index
- 作用:表示该数据报在 EtherCAT 数据区中的子报文索引。
- 背景:一个完整的 EtherCAT 数据帧可能包含多个子报文,每个子报文都有一个唯一的索引。
index
用于标识当前数据报是第几个子报文。 - 使用场景:在 master 组装以太网数据帧时,会根据
index
将多个子报文按顺序组合成一个完整的数据帧。
data
- 作用:指向子报文的数据内存区。
- 背景:每个子报文的数据内容可能不同,因此数据区是动态分配的。
data
指针指向实际的数据内存区域。 - 相关字段:
mem_size
表示分配的内存大小,而data_size
表示实际使用的数据大小。
mem_size
- 作用:表示数据报数据区的分配内存大小。
- 说明:由于每个子报文的数据大小可能不同,
mem_size
记录了为数据区分配的总内存大小,以确保有足够的空间存储数据。
data_size
- 作用:表示数据报中实际使用的数据大小。
- 示例:如果该数据报用于读取从站的某个寄存器,
data_size
就是该寄存器的大小。 - 与
mem_size
的关系:data_size
必须小于或等于mem_size
。
jiffies_sent
、jiffies_received
、cycles_sent
、cycles_received
- 作用:记录数据报的发送和接收时间,用于统计和调试。
- 背景:
jiffies_sent
和jiffies_received
使用内核的jiffies
计时方式,记录数据报的发送和接收时间。cycles_sent
和cycles_received
使用高精度计时器(cycles),提供更精确的时间记录。- 使用场景:这些时间戳用于分析数据报的传输延迟、网络性能等。
ec_datagram_state_t
表示数据报的状态,每个数据报(ec_datagram_t)也是基于状态来处理,有6种状态:EC_DATAGRAM_INIT
:数据报已经初始化
EC_DATAGRAM_QUEUED
:数据报已插入发送队列
EC_DATAGRAM_SENT
:数据报已经发送(还存在队列中)
EC_DATAGRAM_RECEIVED
:该数据报已接收,并从发送队列删除
EC_DATAGRAM_TIMED_OUT
:该数据报发送后,接收超时,从发送队列删除
EC_DATAGRAM_ERROR
: 发送和接收过程中出错(从队列删除),校验错误、不匹配等。
2.2.3 M 位的作用
- 发送时:在主站组装 EtherCAT 数据帧时,M 位(More 位)用于指示当前子报文是否是最后一个子报文。如果 M 位为 1,表示后面还有更多的子报文;如果 M 位为 0,表示当前子报文是最后一个。
- 接收时:从站根据 M 位判断是否还有后续子报文需要处理。如果 M 位为 1,从站会继续处理下一个子报文;如果 M 位为 0,从站会停止处理并返回响应。
数据报对象初始化由函数
ec_datagram_init()
完成:2.3 状态机
2.3.1 有限状态机(FSM)概述
有限状态机(Finite State Machine, FSM)是一种表示有限个状态以及在这些状态之间转移和动作的数学模型。它在数字系统设计中具有重要作用,广泛应用于协议处理、控制器设计、菜单系统等领域。无论是单片机、FPGA,还是现代计算机系统,状态机都是核心的设计模式之一。例如,Linux 的 TCP 协议栈就是基于状态机实现的。
在 IgH EtherCAT 主站中,状态机同样是核心机制。几乎所有功能都是通过状态机来实现的,每个状态机负责管理某个对象的状态和功能实现的状态转换。这些状态转换基于 EtherCAT 数据报进行,具体流程如下:
- 状态机在某个状态(如 A0)中填充数据报(
datagram
)。
- 数据报通过 EtherCAT 数据帧发送到从站,经过从站的 ESC(EtherCAT Slave Controller)处理。
- 处理后的数据报返回到主站的网卡接收端。
- 主站将接收到的数据报交给状态机的下一个状态(如 A1)进行解析和处理。
2.3.2 IgH 中状态机的基本表示
在 IgH 中,状态机的基本结构如下:
datagram
:指向状态机操作的数据报对象。每个状态机都需要操作一个数据报对象,用于与从站进行数据交换。
state
:状态函数指针,指向当前状态的处理函数。状态函数负责执行当前状态的操作,并决定状态机的下一步转移。
IgH EtherCAT协议栈几乎所有功能通过状态机实现,每个状态机管理着某个对象的状态、功能实现的状态装换,而这些状态转换是基于EtherCAT数据报来进行的,如状态机A0状态函数填充datagram,经EtherCAT数据帧发出后,经过slave ESC处理,回到网卡接收端接收后,交给状态机A1状态的下一个状态函数解析处理。所以每个状态机内都包含有指向该状态机操作的数据报对象指针
datagram
和状态执行的状态函数void (*state)(ec_fsm_master_t *)
;总结一句话:状态机是根据数据报的状态来执行,每个状态机都需要操作一个数据报对象。
现在知道了状态机与数据报的关系,下面介绍IgH EtherCAT协议栈中有哪些状态机,及状态机使用的数据报对象是从哪里分配如何管理的。
2.3.3 master状态机
前面说到主站具有的三个阶段,当主站与网卡设备attach后进入Idle phase,处于Idle phase后,开始执行主站状态机。
主站状态机包含1个主状态机和许多子状态机,matser状态机主要目的是:
- Bus monitoring 监控EtherCAT总线拓扑结构,如果发生改变,则重新扫描。
- Slave con fguration 监视从站的应用程序层状态。如果从站未处于其应有的状态,则从站将被(重新)配置
- Request handling 请求处理(源自应用程序或外部来源),主站任务应该处理异步请求,例如:SII访问,SDO访问或类似。
主状态机
ec_fsm_master_t
结构如下:可以看到,主站状态机结构下还有很多子状态机,想象一下如果主站的所有功能通过一个状态机来完成,那么这个状态机的状态数量、各状态之间的联系会有多恐怖,复杂性级别将会提高到无法管理的水平。为此,IgH中,将EtherCAT主状态机的某些功能用子状态机完成。这有助于封装相关工作流,并且避免“状态爆炸”现象。这样当主站完成coe功能时,可以由子状态机fsm_coe去完成。具体各功能是如何通过状态机完成的,文章后面会介绍。
2.3.4 slave 状态机
slave 状态机管理着每个从站的状态,所以位于从站对象 (
ec_slave_t
) 内:slave状态机和master状态机类似,slave状态机内还包含许多子状态机。slave状态机主要目的是:
- 主站管理从站状态
- 主站与从站应用层(AL)通讯。比如具有EoE功能的从站,主站通过该从站下的子状态机fsm_eoe来管理主站与从站应用层的EOE通讯。
2.3.5 数据报对象的管理
上面简单介绍了IgH内的状态机,状态机输入输出的对象是
datagram
,fsm对象内只有数据报对象的指针,那fsm工作过程中的数据报对象从哪里分配?由于每个循环周期都需要操作数据报对象,IgH为减少
datagram
的动态分配操作,提高主站性能,在master初始化的时候预分配了主站运行需要的所有datagram对象。在master实例我们可以看到下面的数据报对象:这些数据报对象都是已经分配内存的,但由于报文不同,报文操作的数据大小不同,所以datagram数据区大小随状态机的具体操作而变化,在具体使用时才分配数据区内存。
以上数据报对象给状态机使用,别忘了还有过程数据也需要数据报对象,所以IgH中数据报类型分为以下四类:
分为三类(非常重要):
数据报对象 | 用途 |
Datagram_pairs | 过程数据报 |
fsm_datagram[] | Fsm_master及子状态机专用的数据报对象。 |
ext_datagram_ring[] | 动态分配给fsm_slave及其子fsm。 |
ref_sync_datagram sync_datagram sync64_datagram sync_mon_datagram | 应用专用数据报用于时钟同步。 |
其中
fsm_datagram
为 master 状态机及 master 下的子状态机执行过程中操作的对象。ext_datagram_ring[]
是一个环形队列,当fsm_slave
从站状态机处于ready状态,可以开始处理与slave相关请求,如配置、扫描、SDO、PDO等,这时会从ext_datagram_ring[]
中给该fsm_slave
分配一个数据报,并运行fsm_slave
状态机检查并处理请求。应用专用数据报用于时钟同步,与时钟强相关,它们比较特殊,它们的数据区大小是恒定的,所以其数据区在主站初始化时就已分配内存,应用调用时直接填数据发送,避免linux的内存分配带来时钟的偏差。
数据报数据区(data)内存通过
ec_datagram_prealloc()
来分配.数据区的大小为一个以太网帧中单个Ethercat数据报的最大数据大小
EC_MAX_DATA_SIZE
。由于以太网帧的大小有限,因此数据报的最大大小受到限制,即以太网帧长度 1500 - ethercat头2byte- ethercat子数据报报头10字节-WKC 2字节,如图:

如果过程数据镜像的大小超过该限制,就必须发送多个帧,并且必须对映像进行分区以使用多个数据报。 Domain自动进行管理。
2.4 master状态机及数据报初始化
2.4.1 模块入口函数 ec_init_module(void)
我们看一下
ec_master.ko
模块的入口函数 ec_init_module(void)
。ec_init_module(void)
ec_init_module()
是 EtherCAT 主站驱动模块的初始化函数,主要完成以下任务:- 初始化全局信号量。
- 分配字符设备号。
- 创建设备类。
- 解析主站和备用网卡的 MAC 地址。
- 初始化主站的静态变量。
- 分配并初始化主站实例。
- 处理错误情况并释放资源。
2.4.2 ec_master_init_static(void)
ec_master_init_static()
是 EtherCAT 主站的静态变量初始化函数,主要完成以下任务:- 根据是否支持高精度计时器(
EC_HAVE_CYCLES
),计算超时时间。
- 设置 I/O 操作超时时间和外部注入超时时间。
- 说明:
jiffies
是 Linux 内核中的一种时间单位,表示系统启动以来的时钟滴答数。timeout_jiffies
是 I/O 操作的超时时间,单位为jiffies
。ext_injection_timeout_jiffies
是外部注入(如 SDO 操作)的超时时间,单位为jiffies
。HZ
是内核的时钟频率(每秒的时钟滴答数)。- 公式:
超时时间(jiffies) = 超时时间(us) * HZ / 1000000
。 max()
函数确保超时时间至少为 1 个jiffy
,避免超时时间为 0。
ec_master_init_static()
函数的主要作用是初始化 EtherCAT 主站的静态变量,特别是与超时时间相关的变量。根据系统是否支持高精度计时器,函数会使用不同的方式计算超时时间:- 如果支持高精度计时器,使用 CPU 周期数(
cycles
)作为超时时间的单位。
- 如果不支持高精度计时器,使用
jiffies
作为超时时间的单位。
2.4.3 ec_master_init()
ec_master_init()
是 EtherCAT 主站的构造函数,主要完成以下任务:- master初始化:使用sema_init()和ec_master_clear_device_stats()函数来初始化master及其相关的信号量和统计信息。
- MAC地址分配:通过检查EC_MAX_NUM_DEVICES是否大于1,将main_mac和backup_mac分别赋值给master->macs[EC_DEVICE_MAIN]和master->macs[EC_DEVICE_BACKUP]。
- 初始化设备:通过调用ec_device_init()函数来初始化master的所有设备,如果其中任何一个失败,代码会执行goto out_clear_devices跳转到清理部分。
- 状态机和数据报文初始化:使用ec_datagram_init()和ec_fsm_master_init()函数来初始化FSM和数据报文。
- 外部数据报文环的初始化:创建一个EC_EXT_RING_SIZE大小的数组,并使用ec_datagram_prealloc()函数为每个元素分配内存空间。
- 同步和引用同步数据报文的初始化:通过调用ec_datagram_init()和ec_datagram_prealloc()函数来初始化这些数据报文,并预分配它们所需的大小。
- 字符设备初始化:使用ec_cdev_init()函数创建一个新的字符设备用于与用户空间通信。
- RTDM设备的初始化(如果定义了EC_RTDM):尝试通过调用ec_rtdm_dev_init()函数来初始化RTDM设备,如果失败会跳转到out_unregister_class_device标签。
- 清理部分(在任何一个步骤中初始化失败时执行):如果初始化过程中的某一步失败,代码将使用一系列的ec_datagram_clear()、ec_fsm_master_clear()和ec_device_clear()调用来清除所有已经分配的资源。
ec_master_init()
对状态机及数据报对象有初步认识后,我们回到
ec_master.ko
模块入口函数 ec_init_module()
主站实例初始化 ec_master_init()
,主要完成主站状态机初始化及数据报:其中
ec_fsm_master_init
初始化master fsm和子状态机,并指定了master fsm使用的数据报对象fsm_datagram
。2.4.4 初始化外部数据报队列
外部数据报队列用于从站状态机,每个状态机执行期间使用的数据报从该区域分配,下面是初始化ext_datagram_ring中每个结构:
非应用数据报队列链表,如EOE数据报会插入该队列后发送。
同样初始化几个时钟相关数据报对象,它们功能固定,所以数据区大小固定,就不贴代码了,比如sync_mon_datagram,它的作用是用于同步监控,获取从站系统时间差,所以是一个BRD数据报,在此直接将数据报操作偏移地址初始化,使用时能快速填充发送。
地址 | 位 | 名称 | 描述 | 复位值 |
0x092c~0x092F | 0~30 | 系统时间差 | 本地系统时间副本与参考时钟系统时间值之差 | 0 |
ㅤ | 31 | 符号 | 0:本地系统时间≥参考时钟时间1:本地系统时间<参考时钟时间 | 0 |
另外比较重要的是将使用的网卡MAC地址放到macs[]中,在网卡驱动probe过程中根据MAC来匹配主站使用哪个网卡。
2.5 初始化EtherCAT device
master协议栈主要完成EtherCAT数据报的解析和组装,然后需要再添加EtherNet报头和FCS组成一个完整的以太网帧,最后通过网卡设备发送出去。为与以太网设备驱动层解耦,igh使用ec_device_t来封装底层以太网设备,一般来说每个master只有一个ec_device_t,这个编译时配置决定,若启用线缆冗余功能,可指定多个网卡设备:
成员
*master
表示改对象属于哪个master,*dev
指向使用的以太网设备net_device,poll
该网络设备poll函数,tx_skb[]
以太网帧发送缓冲区队列,需要发送的以太网帧会先放到该队里,tx_ring_index
管理tx_skb[]
,以及一些网络统计变量,下面初始化ec_device_t对象:主要关注分配以太网帧发送队列内存tx_skb[],并填充Ethernet报头中的以太网类型字段为0x88A4,目标MAC地址0xFFFFFFFF FFFF,对于源MAC地址、sk_buff所属网络设备、ec_device_t对象使用的网络设备net_device,将在网卡驱动初始化与master建立联系过程中设置。
2.6 设置IDLE 线程的发送间隔:
根据网卡速率计算:
100Mbps网卡发送一字节数据需要的时间EC_BYTE_TRANSMISSION_TIME_NS:
1/(100 MBit/s / 8 bit/byte) = 80 ns/byte
.2.7 初始化字符设备
由于主站位于内核空间,用户空间应用与主站交互通过字符设备来交互;
创建普通字符设备,给普通linux应用和Ethercat tool使用。若使用xenomai或RTAI,则再创建实时字符设备,提供给实时应用使用。
到这里明白了IgH中的状态机与数据报之间的关系,主站对象也创建好了,但是主站还没有网卡设备与之关联,主站也还没有工作,下面简单看一下ecdev_offer流程。
关于网卡驱动代码详细解析推荐这两篇文章:
3 网卡
- 网卡probe
- 给主站提供网络设备:
ecdev_offer
,根据MAC地址找到master下的ec_device_t
对象
上面我们只设置了
ec_device_t->tx_skb[]
中sk_buff
的以太网类型和目的地址,现在继续填充源MAC地址为网卡的MAC地址、sk_buff所属的net_device:- 调用网络设备接口打开网络设备
- 当master下的所有的网络设备都
open
后,master从ORPHANED转到IDLE阶段
其中主要设置master发送和接收回调函数,应用通过发送和接收数据时,将通过这两接口直接发送和接收。创建master idle线程
ec_master_idle_thread
。4 IDLE阶段内核线程
综上,状态机操作对象是datagram,datagram发送出去后回到主站交给状态机的下一个状态处理,所以主站需要循环地执行状态机、发送EtherCAT数据帧、接收EtherCAT数据帧、执行状态机、发送EtherCAT数据帧、……来驱动状态机运行,这个循环由内核线程来完成。

当主站与网卡绑定后,应用还没有请求主站,主站处于IDLE状态,这时循环由内核线程
ec_master_idle_thread
来完成,主要完成从站拓扑扫描、配置站点地址等工作。整个过程简单概述如下。
4.1 数据报发送
下面介绍IgH中状态机处理后数据报的发送流程(
ecrt_master_send()
)。
master使用一个链表
datagram_queue
来管理要发送的子报文对象datagram,需要发送的子报文对象会先插入该链表中,统一发送时,分配一个sock_buff
,从datagram_queue
上取出报文对象,设置index
(index
是发送后接收回来与原报文对应的标识之一),将一个个报文对象按EtherCAT数据帧结构填充到sock_buff
中,最后通过网卡设备驱动函数hard_start_xmit
,将sock_buff
从网卡发送出去。
4.2 数据报接收

接收数据时,通过网卡设备驱动
ec_poll
函数取出Packet得到以太网数据,然后解析其中的EtherCAT数据帧,解析流程如下:- 得到子报文
index
,遍历发送链表datagram_queue
,找到index
对应的datagram。
- 将子报文数据拷贝到
datagram
数据区。
- 将以太网帧内子报文中的WKC值复制到
datagram
中的WKC。
- 将
datagram
从链表datagram_queue
删除。
- 根据子报文头M位判断还有没有子报文,有则跳转1继续处理下一个子报文,否则完成接收。
接收完成后,进入下一个循环,内核线程运行状态机或周期应用进行下一个周期,处理接收的Ethercat报文。
先简单介绍到这,敬请关注后续文章。。。。
作者:wsg1100
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
- 作者:tangcuyu
- 链接:https://expoli.tech/articles/2025/03/06/EtherCAT-Master-IgH-Analysis-(Part-One)---Master-Initialization%2C-State-Machine-and-EtherCAT-Messages---Mu-Duo
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章