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
ribaldaUpdated Feb 27, 2025
基于官方IgH,功能更为全面的EtherCAT主站。
KickCAT
leducpUpdated Feb 28, 2025
一个用C++编写的全新EtherCAT主站,目前功能尚不完善。
ethercrab
ethercrab-rsUpdated 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

  1. 加载 ec_master.ko 模块
    1. 模块参数包括:
      • 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缓冲区大小。
  1. 读取 /etc/sysconfig/ethercat 中的环境变量 DEVICE_MODULES,该变量位于 ethercat.conf 中。
  1. 在每个 DEVICE_MODULES 前添加前缀 ec_,例如,如果 DEVICE_MODULES 为 igb,则添加前缀后为 ec_igb
  1. 使用 modinfo 检查该模块是否存在。
  1. 对于非genericrtdm的驱动,需要先将网卡与当前驱动unbindunbind后的网卡才能被新驱动接管
  1. 对于 generic 和 rtdm 驱动,需要先将网卡与当前驱动解绑(unbind),解绑后的网卡才能被新驱动接管。
  1. 加载该驱动。
start 脚本加载了两个内核模块:ec_master.ko 和网卡驱动 ec_xxx.koec_master 根据内核参数(网卡MAC地址)创建主站实例,此时主站处于 Orphaned 阶段。随后加载网卡驱动 ec_xxx.ko,执行网卡驱动的 probe 函数,根据MAC地址将网卡与主站实例匹配,此时主站获得操作的网卡设备,进入 Idle 阶段。详细过程将在后文介绍。
notion image

1.2 stop

stop 脚本用于卸载内核模块 ec_master.ko 和网卡驱动 ec_xxx.ko
  1. 遍历配置文件中的环境变量 DEVICE_MODULES
  1. 在每个 DEVICE_MODULES 前添加前缀 ec_
  1. 使用 lsmod 检查该模块是否已加载。
  1. 卸载模块。
在后文中,“主站”和“master”均表示主站或主站实例对象,“slave”和“从站”表示从站或从站对象,中英混用,不做刻意区分。

2 主站实例创建

在一个使用IgH的控制器中,可以有多个EtherCAT主站。每个主站可以绑定一个主网卡和一个备用网卡,通常备用网卡不启用,只有在启用线缆冗余功能时才使用备用网卡(本文假设只有一个主网卡)。
notion image
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),主站各阶段的操作如下:
notion image
  • 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 数据帧关系如下:
notion image
EtherCAT 数据位于以太网帧数据区,EtherCAT 数据由 EtherCAT头若干EtherCAT数据报文组成。EtherCAT头中记录了EtherCAT数据报的长度和类型,类型为1表示与从站通信。EtherCAT数据报文内包含多个子报文,每个子报文由报文头、数据和WKC域组成。子报文结构含义如下。
notion image
整个EtherCAT网络形成一个环状,主站与从站之间是通过EtherCAT数据报来交互,一个EtherCAT报文从网卡 TX 发出后,从站 ESC 芯片 EtherCAT 报文进行交换数据,最后该报文回到主站。网上有个经典的EtherCAT动态图(刷新后动态图重新播放).
notion image
认识 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 结构体中都有对应的表示。为了避免重复,这里不再详细介绍这些字段,而是重点解释其他几个关键成员的作用。
  1. device_index
      • 作用:表示该数据报是通过哪个网卡设备发送或接收的。
      • 背景:在 IgH 中,一个 master 实例可以绑定多个网卡设备(例如主网卡和备用网卡),用于发送和接收 EtherCAT 数据帧。device_index 用于标识当前数据报所属的网卡设备。
      • 示例:如果 master 绑定了两个网卡,device_index 可以区分数据报是通过主网卡还是备用网卡发送的。
  1. data_origin
      • 作用:表示该数据报的内存来源类别。
      • 背景:在 IgH 中,master 管理着多个空闲的 ec_datagram_t 对象,这些对象根据用途被分为不同的类别(例如内部使用、外部使用等)。data_origin 用于标识当前数据报属于哪一类别。
      • 后续说明:具体的分类和用途将在后文详细讨论。
  1. index
      • 作用:表示该数据报在 EtherCAT 数据区中的子报文索引。
      • 背景:一个完整的 EtherCAT 数据帧可能包含多个子报文,每个子报文都有一个唯一的索引。index 用于标识当前数据报是第几个子报文。
      • 使用场景:在 master 组装以太网数据帧时,会根据 index 将多个子报文按顺序组合成一个完整的数据帧。
  1. data
      • 作用:指向子报文的数据内存区。
      • 背景:每个子报文的数据内容可能不同,因此数据区是动态分配的。data 指针指向实际的数据内存区域。
      • 相关字段mem_size 表示分配的内存大小,而 data_size 表示实际使用的数据大小。
  1. mem_size
      • 作用:表示数据报数据区的分配内存大小。
      • 说明:由于每个子报文的数据大小可能不同,mem_size 记录了为数据区分配的总内存大小,以确保有足够的空间存储数据。
  1. data_size
      • 作用:表示数据报中实际使用的数据大小。
      • 示例:如果该数据报用于读取从站的某个寄存器,data_size 就是该寄存器的大小。
      • 与 mem_size 的关系data_size 必须小于或等于 mem_size
  1. jiffies_sentjiffies_receivedcycles_sentcycles_received
      • 作用:记录数据报的发送和接收时间,用于统计和调试。
      • 背景
        • jiffies_sent 和 jiffies_received 使用内核的 jiffies 计时方式,记录数据报的发送和接收时间。
        • cycles_sent 和 cycles_received 使用高精度计时器(cycles),提供更精确的时间记录。
      • 使用场景:这些时间戳用于分析数据报的传输延迟、网络性能等。
notion image
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 数据报进行,具体流程如下:
  1. 状态机在某个状态(如 A0)中填充数据报(datagram)。
  1. 数据报通过 EtherCAT 数据帧发送到从站,经过从站的 ESC(EtherCAT Slave Controller)处理。
  1. 处理后的数据报返回到主站的网卡接收端。
  1. 主站将接收到的数据报交给状态机的下一个状态(如 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字节,如图:
notion image
如果过程数据镜像的大小超过该限制,就必须发送多个帧,并且必须对映像进行分区以使用多个数据报。 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 主站驱动模块的初始化函数,主要完成以下任务:
  1. 初始化全局信号量。
  1. 分配字符设备号。
  1. 创建设备类。
  1. 解析主站和备用网卡的 MAC 地址。
  1. 初始化主站的静态变量。
  1. 分配并初始化主站实例。
  1. 处理错误情况并释放资源。

2.4.2 ec_master_init_static(void)

ec_master_init_static() 是 EtherCAT 主站的静态变量初始化函数,主要完成以下任务:
  1. 根据是否支持高精度计时器(EC_HAVE_CYCLES),计算超时时间。
  1. 设置 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 主站的构造函数,主要完成以下任务:
  1. master初始化:使用sema_init()和ec_master_clear_device_stats()函数来初始化master及其相关的信号量和统计信息。
  1. MAC地址分配:通过检查EC_MAX_NUM_DEVICES是否大于1,将main_mac和backup_mac分别赋值给master->macs[EC_DEVICE_MAIN]和master->macs[EC_DEVICE_BACKUP]。
  1. 初始化设备:通过调用ec_device_init()函数来初始化master的所有设备,如果其中任何一个失败,代码会执行goto out_clear_devices跳转到清理部分。
  1. 状态机和数据报文初始化:使用ec_datagram_init()和ec_fsm_master_init()函数来初始化FSM和数据报文。
  1. 外部数据报文环的初始化:创建一个EC_EXT_RING_SIZE大小的数组,并使用ec_datagram_prealloc()函数为每个元素分配内存空间。
  1. 同步和引用同步数据报文的初始化:通过调用ec_datagram_init()和ec_datagram_prealloc()函数来初始化这些数据报文,并预分配它们所需的大小。
  1. 字符设备初始化:使用ec_cdev_init()函数创建一个新的字符设备用于与用户空间通信。
  1. RTDM设备的初始化(如果定义了EC_RTDM):尝试通过调用ec_rtdm_dev_init()函数来初始化RTDM设备,如果失败会跳转到out_unregister_class_device标签。
  1. 清理部分(在任何一个步骤中初始化失败时执行):如果初始化过程中的某一步失败,代码将使用一系列的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 网卡

  1. 网卡probe
    1. 给主站提供网络设备:ecdev_offer ,根据MAC地址找到master下的ec_device_t对象
      1. 上面我们只设置了ec_device_t->tx_skb[]sk_buff的以太网类型和目的地址,现在继续填充源MAC地址为网卡的MAC地址、sk_buff所属的net_device:
    1. 调用网络设备接口打开网络设备
      1. 当master下的所有的网络设备都open后,master从ORPHANED转到IDLE阶段
        其中主要设置master发送和接收回调函数,应用通过发送和接收数据时,将通过这两接口直接发送和接收。创建master idle线程ec_master_idle_thread

        4 IDLE阶段内核线程

        综上,状态机操作对象是datagram,datagram发送出去后回到主站交给状态机的下一个状态处理,所以主站需要循环地执行状态机、发送EtherCAT数据帧、接收EtherCAT数据帧、执行状态机、发送EtherCAT数据帧、……来驱动状态机运行,这个循环由内核线程来完成。
        notion image
        当主站与网卡绑定后,应用还没有请求主站,主站处于IDLE状态,这时循环由内核线程ec_master_idle_thread来完成,主要完成从站拓扑扫描、配置站点地址等工作。
        整个过程简单概述如下。

        4.1 数据报发送

        下面介绍IgH中状态机处理后数据报的发送流程(ecrt_master_send())。
        notion image
        master使用一个链表datagram_queue来管理要发送的子报文对象datagram,需要发送的子报文对象会先插入该链表中,统一发送时,分配一个sock_buff,从datagram_queue上取出报文对象,设置indexindex是发送后接收回来与原报文对应的标识之一),将一个个报文对象按EtherCAT数据帧结构填充到sock_buff中,最后通过网卡设备驱动函数hard_start_xmit,将sock_buff从网卡发送出去。
        notion image

        4.2 数据报接收

        notion image
        接收数据时,通过网卡设备驱动ec_poll函数取出Packet得到以太网数据,然后解析其中的EtherCAT数据帧,解析流程如下:
        1. 得到子报文index,遍历发送链表datagram_queue找到index对应的datagram
        1. 将子报文数据拷贝到datagram数据区。
        1. 将以太网帧内子报文中的WKC值复制到datagram中的WKC。
        1. datagram从链表datagram_queue删除。
        1. 根据子报文头M位判断还有没有子报文,有则跳转1继续处理下一个子报文,否则完成接收。
        接收完成后,进入下一个循环,内核线程运行状态机或周期应用进行下一个周期,处理接收的Ethercat报文。
        先简单介绍到这,敬请关注后续文章。。。。
        作者:wsg1100
        本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
         
        EtherCAT 主站 IgH 学习之 —— xenomai_posix 例程代码学习如何在Debian 11上手动编译安装AMD XGBE 10GB网卡驱动
        Loading...