简介:这套基于IGH开源实现的EtherCAT主站源码包,面向Linux环境下的工业实时以太网开发场景,适合需要掌握主站原理、通信配置与二次开发的嵌入式及自动化工程师。压缩包共758个文件,核心为400个C源文件与224个头文件,同时包含35个C++文件、24个Makefile.am及configure脚本等构建组件,整体仅9.12MB,便于快速下载与源码分析。包内除可编译安装的完整工程外,通常还带有协议说明、API文档、示例应用及编译指南,可帮助从零搭建EtherCAT主站环境。目前已有1375人学习下载,对于想要深入理解EtherCAT帧结构、同步机制,以及Linux下实时网络编程和RT_PREEMPT优化的人群,是一份紧凑且实用的开源参考资料。
1. IGH 1.5.2 在 Linux 上做主站,卡点不在解压和编译,而在谁在驱动周期
"ethercat-1.5.2.rar" 解压出来是 IgH(EtherLab)开源的 EtherCAT 主站 1.5.2。这段源码在 Linux 运动控制领域几乎是默认选项,伺服、步进、分布式 IO、机器人控制器都靠它把 EtherCAT 总线跑起来。但它不是解压即用的工程包:主站以内核模块形态运行,编译要对齐内核源码,实时性要靠 PREEMPT_RT 这类配置,网卡还要从内核协议栈手里让渡给 ec_* 驱动。比这些更隐蔽的是 IGH 的设计:从站进了 OP 不代表数据在流动,周期性过程数据由应用层在每个周期调用 send/receive 主动驱动,主站自己没有独立时钟在刷帧。这个认知没建立,"IGH 进入 OP 读不到数据"就能卡一个下午。下面按依赖核对、编译加载、总线运行、排错验证这条路线把落地路径写完。
2. 编译 IGH 1.5.2 前先定三件事:内核匹配、RAR 解压与实时配置
2.1 内核版本先对齐:IGH 1.5.2 对不同内核的适配差异
IGH 1.5.2 是 2018 年前后发布的版本,官方发布时面向当时 4.x 主线内核。拿它编到现在的 LTS 内核上,报错基本来自内核 API 变迁而不是主站逻辑本身:旧定时器接口 init_timer、setup_timer 在 6.1 被删除,网卡驱动的 NAPI 回调签名前后改过多次,IGH 的老代码会在编译阶段直接报 implicit declaration。所以第一步不是 ./configure,而是确认这份 1.5.2 要站在哪个内核上。
我一般选 5.15 或 6.6 这类 LTS,再决定实时内核怎么来。5.15 的 PREEMPT_RT 要自己打补丁树,步骤多一步,但社区踩坑资料最全,IGH 1.5.2 需要做的适配最少。6.6 的 RT 支持来自 rt 补丁树或发行版开启 PREEMPT_RT 的内核包;主线把 PREEMPT_RT 全量合入是 6.12 之后的事,所以在 6.6 上直接开 CONFIG_PREEMPT_RT=y 是找不到这个选项的。如果项目绑定 6.6 + PREEMPT_RT,就要做好 IGH 设备驱动层小改动的准备,别指望 1.5.2 原包直接编译通过。
提示:先跑 uname -r 记下目标内核版本,再准备匹配的源码和头文件。IGH 编译需要 /lib/modules/$(uname -r)/build 指向有效内核构建目录,只用发行版默认的 headers 包通常不够,Debian 系建议装 linux-headers-$(uname -r) 并确认软链没断。
2.2 解压 ethercat-1.5.2.rar:unar 怎么避免中文文件名乱码
rar 是 Windows 侧常见打包格式,Linux 解压常见工具是 unrar 和 unar。unrar 在多数发行版里要单独加 non-free 仓库,unrar-free 对 rar5 格式支持又不全;unar 在 Debian/Ubuntu 直接 apt 能装,处理文件名编码更稳,所以我默认用 unar。
# Debian/Ubuntu 安装 unar;它会同时提供 lsar 列表工具 sudo apt install unar cd ~/work # -o 指定解压目标目录,解出来的顶层目录保持原样 unar -o /opt/etherlab ethercat-1.5.2.rar # 先列出包内文件名,确认为什么解出来是乱码 lsar -e GB18030 ethercat-1.5.2.rarunar -o 指定输出根目录,避免解出来的文件散落到当前目录;不写 -o 时默认解到当前目录,对源码包来说够用,但我习惯先建一个干净的构建目录。lsar 是检查编码用的:rar 在 Windows 下常用 GBK/GB18030 存文件名,Linux 终端 locale 是 UTF-8 时直接 unrar x 会把外层中文目录名解成乱码。lsar -e GB18030 按 GBK 解释文件名并列出,随后 unar 用同样的编码参数解压就不会花屏。IGH 源码目录本身是英文名,乱码通常只影响最外层的打包目录名,不影响后续 configure,但目录名带乱码会在脚本里埋雷,建议顺手处理。解压完成后先 ls 确认根目录下有 configure、README、master/、devices/、tools/、examples/,结构对得上再进下一步。
2.3 内核配置项核对:PREEMPT_RT、高精度定时器和网卡驱动
IGH 不需要内核为它单独打补丁,它就是普通内核模块,实时性完全来自内核配置和网卡驱动选择。编译内核或挑发行版内核时,我会按下面这张表核对:
| 配置项 | 推荐值 | 对主站的影响 |
|---|---|---|
| CONFIG_PREEMPT_RT | y(RT 补丁树或 6.12+ 主线) | 内核可抢占,周期任务抖动从几十微秒降到个位数微秒 |
| CONFIG_HIGH_RES_TIMERS | y | 高精度定时器,周期不稳先查它是不是 n |
| CONFIG_NO_HZ_FULL | n | 全无滴答模式会干扰周期线程调度,默认别开 |
| CONFIG_IRQ_FORCED_THREADING | y | 中断线程化,PREEMPT_RT 下抖动更可控 |
网卡相关的两处也要盯。一是承载 EtherCAT 的网卡驱动要编成模块,编进内核的话 ec_* 驱动加载时会因为设备已被占用而失败;二是 IGH 1.5.2 对网卡有一组自己的驱动模块,ec_igb.ko 对应 Intel I210/I350,ec_e1000e.ko 对应老千兆,ec_r8169.ko 对应 Realtek。真正干活的是这组模块,而不是内核自带的同名驱动。较新的 I225/I226 走 igc 驱动,1.5.2 里没有官方 ec_igc,常见做法是找社区适配分支,或者退回 ec_generic 用 NAPI 方式跑,延迟会差一些,但能先把总线通起来。
3. configure 到 modprobe:IGH 1.5.2 主站的完整编译安装参数
3.1 configure 参数怎么给:--enable-cycles 与 --disable-eoe 的含义
IGH 1.5.2 的 configure 开关很多,默认值适合"试着玩",不适合现实项目。下面是我在工控机上常用的配置:
cd ethercat-1.5.2 # --enable-cycles 用 CPU 周期计数器计时,抖动统计必须开 # --disable-eoe 禁用 Ethernet over EtherCAT,去掉周期路径里的转发开销 ./configure \ --prefix=/usr/local/etherlab \ --with-linux-dir=/lib/modules/$(uname -r)/build \ --enable-cycles \ --disable-eoe \ --disable-generic \ --enable-igb--prefix 决定 ethercat 工具、头文件、库的安装位置,这里用独立的 /usr/local/etherlab 便于整体卸载。--with-linux-dir 必须指到当前运行内核的 build 目录,写 /usr/src/linux 或者干脆不写,后面 make 会在找头文件时失败。--enable-cycles 让主站用 CPU 周期计数器作为计时基准,比 jiffies 细得多,做帧率、抖动统计时必须开;代价是它依赖 CPU 主频稳定,工控机上一般要顺手关掉 intel_pstate 的变频。--enable-rtdm 只有当应用层要跑 Xenomai 时才需要,没有 Xenomai 环境就不要开,开了反而多一层依赖。
--disable-eoe 直接对应热词"igh为什么要禁用eoe"。EoE(Ethernet over EtherCAT)把普通以太网帧封装进 EtherCAT 邮箱传输,让挂在总线上的以太网终端能被主站侧的网络栈访问。这个功能本身有价值,但实现上是一条额外的转发路径:从站邮箱带宽被占用,主站每收到一个 EoE 帧都要在内核里多做一次网络栈投递,周期数据路径的抖动随之上升。多数运动控制项目根本不需要在总线里跑以太网帧,所以默认禁用;只有调试从站内置网页或做协议分析时才需要把它开回来。
--disable-generic 关掉 ec_generic,--enable-igb 只编译 Intel I210/I350 对应的主站驱动。这样 modprobe 时少一个到处接管网卡的模块,系统里多张物理网卡时不容易误绑定。
3.2 编译、安装、加载 ec_master 的最小命令序列
配置通过后,编译安装和模块加载按下面顺序执行:
# -j$(nproc) 按 CPU 数并行,模块产物在 master/、devices/ 目录下 make -j$(nproc) # modules_install 装内核模块,install 装工具、头文件和库 sudo make modules_install install # 重建模块依赖;漏掉这步,modprobe 可能报 module not found sudo depmod # 先加载主站,再加载网卡驱动;顺序反了可能被原生驱动占住设备 sudo modprobe ec_master sudo modprobe ec_igb # 看到 EtherCAT 注册信息说明驱动接管成功 dmesg | grep -i ethercat # 字符设备出现后,ethercat 工具才能访问主站 ls -l /dev/EtherCAT0make 默认把所有启用的模块一起编出来:master/ 里是主站本体 ec_master.ko,devices/ 里是各网卡驱动,tools/ 生成 ethercat 命令行工具。install 把工具装到 $prefix/sbin,头文件装到 $prefix/include,应用层写基于 ecrt API 的程序时要引用它,所以前缀要记牢。加载网卡驱动时,如果该网卡已被内核原生驱动占用,dmesg 会报设备 busy,我一般先 ip link set eth0 down 再 modprobe。加载顺序上 ec_master 先、网卡驱动后,反过来的话网卡驱动找不到主站符号会加载失败。加载成功且 /dev/EtherCAT0 出现后,主站还没有开始工作,它需要一个应用去激活,这是下一章的事。
注意:/dev/EtherCAT0 默认 root 可访问。普通用户直接跑 ethercat 会 permission denied,常见做法是写一条 udev 规则把属主改成用户组,否则保持 sudo 运行也够用。
3.3 编译报错定位:timer API 移除和头文件路径两处典型
IGH 1.5.2 的编译错误集中在 master/ 和 devices/ 两个目录。第一类典型是内核 6.1 之后老定时器 API 被移除,报错形如 implicit declaration of function 'init_timer',这基本就锁定为内核版本问题,要么回退内核,要么按 timer_setup 的新写法小改一两处结构体初始化。第二类是配置阶段内核目录检测不过,表现为找不到版本头文件或 KERNELDIR not found,优先检查 /lib/modules/$(uname -r)/build 是否存在、是不是软链到了不存在的路径。
定位时用 make V=1 重编一次,看具体报错的编译命令和文件路径,比盯着最后几行错误更有效。还有一个环境坑:在虚拟机上编好模块拿到真机加载,会因内核 vermagic 不一致报 invalid module format。IGH 模块必须在目标机同版本内核下构建,这点绕不过去,也是跨版本移植时最常见的"编译没问题、加载起不来"的原因。
4. 扫描从站、进入 OP,以及 IGH 进入 OP 读不到数据的排查路径
4.1 用 ethercat 命令确认主站相位和从站状态
ethercat 工具默认装在 $prefix/sbin 下,先把 /usr/local/etherlab/sbin 加进 PATH,或者命令里写全路径。模块就绪后按顺序执行以下三条:
# 主站相位、网卡绑定、从站数量、帧统计都在这一条里 ethercat master # -v 列出每个从站的 Alias/Position、厂商号、产品号和状态 ethercat slaves -v # -c 表示所有从站;不加 -c 只切换 0 号位置的从站 sudo ethercat states -c OPethercat master 的输出包含主站当前相位(INIT/PREOP/SAFEOP/OP)、绑定的网卡、从站数量以及周期和丢帧统计。抖动排查时第一眼先看它,帧率不稳或丢帧率异常往往在从站报错之前就暴露了。slaves -v 是总线勘察工具,输出里每个从站一行,状态字段会显示所在的状态机位置。第一次扫描总线如果结果为空,问题绝大多数在网卡没有被 ec_* 驱动接管,回 dmesg 看有没有 EtherCAT 主站注册信息。states -c OP 是强制把总线上所有从站切到 OP。切换后立刻再跑一次 slaves -v,看状态是否稳定在 Operation,还是闪回 Pre-Op/SafeOp。闪回说明从站不认可主站下发的配置,接下来要查 PDO 映射和域配置,这正是 4.2 要讲的内容。
4.2 PDO 映射与方向:RxPDO 和 TxPDO 在 OP 下怎么对齐
从站能进 OP,但交换数据是错的或全 0,要先查 PDO 映射。PDO 分两个方向:RxPDO 从主站到从站,比如伺服的 0x1600 里放控制字、目标速度;TxPDO 从从站到主站,0x1A00 里放状态字、实际位置。命令查看方式如下:
# -p 0 表示按位置选 0 号从站,位置号以 slaves -v 的输出为准 ethercat pdos -p 0 # 查看 2 号位置从站的 PDO 分配和映射 ethercat pdos -p 2pdos 输出里 RxPDO 段对应主站发送给从站的过程数据,TxPDO 段对应从站反馈回来的数据。和 CoE 对象(比如 0x6040 控制字、0x6060 模式)不同,PDO 决定的是每个周期那帧过程数据里按什么顺序、什么位宽放哪些对象;应用侧的域(domain)配置必须和从站 PDO 总大小严格一致,方向或字节序错了,应用读出来的就是错位的数据。伺服驱动里通常在 0x1600/0x1601 和 0x1A00/0x1A01 预置几组映射,换一个映射组,主站侧域配置要跟着改,这是配置阶段最容易被忽略的对应关系。
4.3 IGH 进入 OP 读不到数据:按顺序排查的六个位置
"IGH 进入 OP 读不到数据"是这个标题下被问得最多的问题,我按下面顺序排查,比盲改 SDO 快得多。
- 状态是不是真的稳定在 OP。从站在看门狗超时、配置变化时会自己退回 SafeOp,先跑 ethercat slaves -v 确认状态列,不要只看应用层打印。
- 应用有没有在周期里驱动数据帧。IGH 的周期性数据交换由应用发起,主站自己不刷帧。激活主站之后,每个周期必须调用 ecrt_master_receive() 收帧、ecrt_master_send() 发帧;只 activate 不 send,从站看到总线没有周期帧,应用读到的永远是旧数据。这条占了"读不到"的一半原因。
- PDO 映射和域大小。应用里 ecrt_domain_data() 拿到的缓冲区是按配置顺序排的,和从站实际 PDO 对不上时数据错位或全 0,对照 4.2 的 pdos 输出逐字节核对。
- 从站看门狗。从站在 PDO 里配了看门狗时间,主站周期如果比看门狗还慢,从站判定主站失联,自动退回 SafeOp。核对主站周期和从站看门狗参数,必要时调周期或改 SDO 0x420/0x421。
- DC 同步。带 DC(Distributed Clocks)的从站要求主站周期里维护 application time 并同步参考时钟,没做 DC 配置的从站处于 free-run 状态,位置采样点会有固定延迟甚至不更新。
- 拓扑和 Alias。多从站时 alias 或 position 配错,配置会下发到错误的从站,现象是数据有值但明显不是当前设备的。
按这个顺序,前三条能解决绝大多数"进了 OP 但没数据"的现场问题。
4.4 IGH 和 SOEM 哪个稳定:稳定性之争的实质
"igh和soem那个稳定"也是常被问到的选型问题。整理成一张对比表:
| 对比项 | IGH 1.5.2 | SOEM |
|---|---|---|
| 运行位置 | 内核模块,应用通过 /dev/EtherCAT0 访问 | 纯用户态,直接操作网络 socket |
| 周期驱动 | 应用在周期里 send/receive | 应用在周期里 send/receive |
| 功能覆盖 | 状态机完整,DC、EoE、拓扑工具齐全 | 核心功能齐全,DC 支持依赖具体分支 |
| 上手成本 | 内核匹配、编译步骤多,门槛高 | 交叉编译简单,分钟级跑通 |
| 适合场景 | 产线级工控、长期维护、高实时要求 | 原型验证、产品集成、硬件资源受限 |
说 IGH 绝对稳定、SOEM 是玩具,都是标签。两者都需要应用层把周期循环做好,中断绑定、CPU 隔离、看门狗配置才是稳定性的主要来源。IGH 的资料和踩坑记录多,遇到问题搜得到答案,这是它在大项目里更常见的原因;SOEM 胜在轻和快,拿到新板子半天就能跑起来。选型按内核态/用户态、功能完整度、团队维护能力来定,比看论坛吵哪个稳定更靠谱。
5. 把中断钉到专用核,用 cyclictest 验收 IGH 1.5.2 主站的抖动
5.1 把网卡中断绑定到独立 CPU 核
IGH 主站的工作链路是"网卡中断 → ec_* 驱动 → 主站状态机 → 应用周期任务"。PREEMPT_RT 下中断线程化了,但不设 CPU 亲和性,调度器可能把中断派到任意核,周期任务的抖动就不受控。先找到网卡中断号:
# 第一列是中断号,找 eth0 那一行 cat /proc/interrupts | grep -i eth0 # 用上一步的实际中断号替换 82;2 是 0b10,表示绑定到 CPU1 echo 2 > /proc/irq/82/smp_affinitysmp_affinity 是 CPU 位图,2 表示第 1 号核。多网卡机器上我会给每个 EtherCAT 网卡一个独立核,应用周期任务再放一个核,并用 isolcpus 把应用核从普通调度中隔离开。绑定前后跑一轮 5.2 的 cyclictest,抖动峰值通常能降一个量级,这是 1.5.2 性价比最高的调优动作。
5.2 用 cyclictest 量化主站周期抖动
没有数据就没有优化。装 rt-tests 后,在 PREEMPT_RT 内核下跑一组和主站周期同频的测试:
# -S 每核一个测试线程;-p 95 实时优先级;-i 1000 周期 1ms;-l 100000 共 10 万次 sudo cyclictest -S -p 95 -i 1000 -l 100000结果里重点是 max 列。max 超过 50us 时,主站周期帧在从站侧就会产生可感知的抖动,伺服跟随误差直接反映出来。把中断绑定前后的 max 值对比记录,比任何口头描述都有说服力。注意测试要和主站运行同时进行,只测空闲内核测不出真实负载下的表现。
5.3 最后一步:应用时间轴对齐到 DC 参考时钟
有 DC 从站时,不要用应用本地时钟直接启动周期,而是激活主站后先调用一次 ecrt_master_application_time() 把时间基准交给应用,此后每个周期用 clock_gettime(CLOCK_MONOTONIC) 推进 application time,并同步参考时钟和从站时钟。这样所有 DC 从站跟随同一条时间轴,跨设备的位置采样点才有一致性。examples/simple_test 只演示了激活和收发,DC 对齐是它没展开的部分,但伺服同步和分布式 IO 的精度恰恰压在这一步。做完再把 cyclictest 的 max 值和 ethercat master 的丢帧统计记进验收单,IGH 1.5.2 主站的实时效果才算有据可查。
本文还有配套的精品资源,点击获取