IgH EtherCAT 从入门到精通:第 3 章 第一次运行 Hello EtherCAT
第 3 章 第一次运行 Hello EtherCAT
导读摘要:完成编译安装后,接下来要让 EtherCAT Master 真正跑起来。本章将带你从配置文件开始,逐步加载内核模块、启动 Master、用命令行工具探索总线,最后分别运行内核态和用户态示例程序。读完本章,你将完成从"装好了"到"跑通了"的关键一步。
3.1 配置文件 ethercat.conf 详解
EtherCAT Master 的运行参数集中在一个配置文件中:/etc/ethercat.conf。启动脚本ethercatctl会在启动时 source 这个文件,把其中的 Shell 变量读入内存。
核心配置项
配置文件中最重要的变量有三组:
1) MASTER0_DEVICE —— 指定主网卡
# 方式一:使用 MAC 地址MASTER0_DEVICE="00:00:08:44:ab:66"# 方式二:使用网卡接口名(脚本会自动解析为 MAC)MASTER0_DEVICE="eth0"# 方式三:广播地址,表示接受任意网卡(仅用于快速测试)MASTER0_DEVICE="ff:ff:ff:ff:ff:ff"如果需要多个 Master 实例,依次设置MASTER1_DEVICE、MASTER2_DEVICE即可。脚本会从MASTER0开始循环,遇到空值即停止,变量个数决定了 Master 实例数量。
2) MASTER0_BACKUP —— 冗余备份网卡(可选)
#MASTER0_BACKUP=""冗余模式(Cable Redundancy)下使用。如果你只有一块网卡,可以忽略此项。
3) DEVICE_MODULES —— 网卡驱动模块
# 可选值: 8139too, e100, e1000, e1000e, r8169, generic, igb, igc 等DEVICE_MODULES="generic"这个变量告诉启动脚本加载哪个 EtherCAT 专用网卡驱动。generic是通用驱动,兼容性最好,适合入门。专用驱动(如e1000e、igb)性能更优,但需要在编译时用--enable-<driver>开启。
4) UPDOWN_INTERFACES —— 自动启停的网络接口
UPDOWN_INTERFACES="eth0"使用generic驱动时,网卡必须在 Master 启动前处于 UP 状态,否则所有帧都会超时。将接口名填入此变量,脚本会在 start 时自动执行ip link set dev eth0 up。
最小可运行配置
对于只有一块 Intel 网卡的测试环境,最小配置如下:
MASTER0_DEVICE="eth0"DEVICE_MODULES="generic"UPDOWN_INTERFACES="eth0"3.2 加载内核模块与启动 Master
IgH EtherCAT Master 的启动由 systemd 服务 + 控制脚本协同完成。下面是它们的协作流程:
┌──────────────────────────────────────────────────────┐ │ systemd: ethercat.service │ │ │ │ ExecStart = /usr/sbin/ethercatctl start │ │ ExecStop = /usr/sbin/ethercatctl stop │ └─────────────────────┬────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────┐ │ ethercatctl start 流程 │ │ │ │ 1. source /etc/ethercat.conf │ │ 2. ip link set dev <UPDOWN_INTERFACES> up │ │ 3. 解析 MASTER*_DEVICE → MAC 地址列表 │ │ 4. modprobe ec_master main_devices=<MAC> │ │ 5. rmmod 原生驱动 (如 e1000e) │ │ 6. modprobe ec_<DEVICE_MODULES> │ └──────────────────────────────────────────────────────┘使用 systemd 启动
# 启动 Mastersudosystemctl start ethercat# 查看状态sudosystemctl status ethercat# 设置开机自启sudosystemctlenableethercat手动启动(调试用)
有时候我们需要绕过 systemd 直接操作,便于观察错误输出:
# 手动加载主模块,指定网卡 MACsudomodprobe ec_mastermain_devices="00:00:08:44:ab:66"# 加载网卡驱动模块(以 generic 为例)sudomodprobe ec_generic# 验证模块加载lsmod|grepec_成功加载后,ec_master模块会在内核日志中打印版本信息。我们可以通过dmesg确认:
dmesg|grep-iethercat# 预期输出类似:# EtherCAT: Master driver 1.6.x# EtherCAT: 1 master waiting for devices.# EtherCAT: Accepting eth0 as main device for master 0.当ec_master加载后,它会进入 Idle 阶段(Phase),等待网卡驱动通过ecdev_offer()接口提供网络设备。一旦驱动加载并完成匹配,Master 即进入正常工作状态。
停止 Master
# 通过 systemdsudosystemctl stop ethercat# 或手动卸载sudormmod ec_genericsudormmod ec_master停止顺序与启动相反:先卸载网卡驱动模块,再卸载主模块。脚本还会重新加载原生网卡驱动,恢复普通网络功能。
3.3 使用 ethercat 命令行工具探索总线
Master 启动后,我们可以用ethercat命令行工具与之交互。这是日常调试最常用的工具。
查看 Master 状态
ethercat master输出示例:
Master0 Phase: Idle Active: no Slaves: 3 ...扫描从站
# 列出总线上所有从站ethercat slaves# 输出示例:# 0 0:0 PREOP + EK1100 EtherCAT Coupler# 1 0:1 PREOP + EL2004 4Ch. Dig. Output 24V# 2 0:2 PREOP + EL3152 2Ch. Ana. Input 4-20mA每行含义依次为:从站绝对位置(Absolute Position)、别名:位置、当前 AL 状态(Application Layer State)、连接标志、设备描述。
常用子命令速查
| 命令 | 说明 |
|---|---|
ethercat master | 查看 Master 概要信息 |
ethercat slaves | 列出所有从站及其状态 |
ethercat pdos | 查看从站 PDO(Process Data Object)映射 |
ethercat sdos | 查看从站 SDO(Service Data Object)字典 |
ethercat upload -p0 --type uint16 0x1018 1 | 读取从站 SDO 条目 |
ethercat xml | 导出从站信息为 XML 格式 |
ethercat graph | 输出拓扑结构(Graphviz DOT 格式) |
这些命令通过/dev/EtherCAT0字符设备与内核 Master 通信。如果遇到权限问题,请确保当前用户在正确的用户组中,或使用sudo。
3.4 运行 mini 内核示例程序
examples/mini/mini.c是一个内核模块(Kernel Module)形式的示例,演示了在内核态使用 EtherCAT 实时接口的完整流程。
核心流程
示例代码的init_mini_module()函数展示了标准的初始化步骤:
// 1. 请求 Master 实例master=ecrt_request_master(0);// 2. 创建过程数据域(Domain)domain1=ecrt_master_create_domain(master);// 3. 获取从站配置sc_ana_in=ecrt_master_slave_config(master,AnaInSlavePos,Beckhoff_EL3152);// 4. 配置 PDO 映射ecrt_slave_config_pdos(sc_ana_in,EC_END,el3152_syncs);// 5. 注册 PDO 条目ecrt_domain_reg_pdo_entry_list(domain1,domain1_regs);// 6. 激活 Masterecrt_master_activate(master);// 7. 启动周期性任务(100 Hz 定时器)timer_setup(&timer,cyclic_task,0);周期性任务cyclic_task()中的数据交换循环是 EtherCAT 通信的核心:
// 接收数据ecrt_master_receive(master);ecrt_domain_process(domain1);// 写过程数据EC_WRITE_U8(domain1_pd+off_dig_out,blink?0x06:0x09);// 发送数据ecrt_domain_queue(domain1);ecrt_master_send(master);编译与运行
# 进入示例目录cdexamples/mini# 编译(需要已安装的内核头文件和 EtherCAT 头文件)make# 加载模块(确保 Master 已启动)sudoinsmod ec_mini.ko# 观察内核日志dmesg|tail-20# 卸载模块sudormmod ec_mini加载成功后,dmesg中会看到类似输出:
ec_mini: Starting... ec_mini: Registering domain... ec_mini: Configuring PDOs... ec_mini: Activating master... ec_mini: Started. ec_mini: 3 slave(s). ec_mini: AL states: 0x08. ec_mini: Link is up.注意:mini 示例使用内核定时器(Timer),周期为 10ms(100Hz),精度有限。生产环境中通常使用 RTAI、Xenomai 或 PREEMPT_RT 内核配合更高精度的定时机制。
3.5 运行 user 用户空间示例程序
examples/user/main.c演示了在用户空间(User Space)使用 EtherCAT 的方法。与内核态相比,用户态程序更容易开发和调试,是大多数应用的推荐起点。
与内核态的关键差异
用户态示例使用了 POSIX 实时调度机制代替内核定时器:
// 设置 FIFO 实时调度策略structsched_paramparam={};param.sched_priority=sched_get_priority_max(SCHED_FIFO);sched_setscheduler(0,SCHED_FIFO,¶m);// 锁定内存,防止页面换出mlockall(MCL_CURRENT|MCL_FUTURE);// 使用 clock_nanosleep 实现 1ms 周期#definePERIOD_NS(1000000)// 1msclock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME,&wakeup_time,NULL);EtherCAT API 调用方式与内核态完全一致——ecrt_request_master()、ecrt_master_create_domain()、ecrt_master_activate()等函数签名和语义不变。这是 IgH Master 设计的一大优点:同一套 API,内核态和用户态通用。
编译与运行
# 编译(安装时已生成 Makefile)cdexamples/usermake# 运行(需要 root 权限,因为要访问 /dev/EtherCAT0 和设置实时优先级)sudo./ec_user_example预期输出:
Configuring PDOs... Activating master... Using priority 99. Starting RT task with dt=1000000 ns. 3 slave(s). AL states: 0x08. Link is up. Domain1: WC 3.按Ctrl+C终止程序。用户态程序退出时会自动释放 Master,Master 回到 Idle 阶段。
用户态 vs 内核态选择建议
| 维度 | 内核态 (mini) | 用户态 (user) |
|---|---|---|
| 开发难度 | 高,需内核编程经验 | 低,标准 C 编程 |
| 调试手段 | printk / dmesg | printf / gdb |
| 实时性 | 极高(配合 RT 内核) | 高(PREEMPT_RT 内核下) |
| 稳定性风险 | bug 可能导致内核崩溃 | bug 只影响用户进程 |
| 推荐场景 | 极端实时要求 | 绝大多数工业应用 |
3.6 常见启动问题排查
初次运行时,以下问题出现频率最高。我们逐一解析。
问题 1:No network cards for EtherCAT specified
原因:ethercat.conf中MASTER0_DEVICE为空。
解决:填写正确的网卡 MAC 地址或接口名。
# 查看可用网卡iplinkshow问题 2:Master 一直卡在waiting for devices
原因:ec_master已加载,但没有网卡驱动向它注册设备。
排查步骤:
- 检查
DEVICE_MODULES是否设置且模块已编译 - 确认
ec_generic(或对应驱动)已加载:lsmod | grep ec_ - 使用 generic 驱动时,确认网卡接口已 UP
问题 3:Master already in use!
原因:已有程序(如 mini 模块)占用了 Master。每个 Master 实例同一时间只能被一个应用请求。
解决:先卸载或终止占用程序,再运行新程序。
问题 4:Failed to enter OPERATION phase
原因:网卡驱动未正确绑定,或网线未连接。
排查:
# 检查内核日志dmesg|grep-iethercat# 确认物理连接ethtooleth0|grep"Link detected"问题 5:权限不足,无法访问/dev/EtherCAT0
原因:用户态程序需要对字符设备的读写权限。
解决:
# 临时方案sudochmod666/dev/EtherCAT0# 永久方案:添加 udev 规则echo'KERNEL=="EtherCAT[0-9]*", MODE="0666"'|\sudotee/etc/udev/rules.d/99-ethercat.rules问题 6:所有帧超时(Timeout)
原因:使用 generic 驱动时,网卡接口未激活。
解决:在ethercat.conf中设置UPDOWN_INTERFACES,或手动执行ip link set dev eth0 up。
3.7 小结
本章我们完成了 EtherCAT Master 的首次运行全流程:
- 配置:
ethercat.conf中的三个核心变量(MASTER0_DEVICE、DEVICE_MODULES、UPDOWN_INTERFACES)决定了 Master 的基本行为 - 启动:通过 systemd 服务或手动 modprobe 加载
ec_master和网卡驱动模块 - 探索:
ethercat命令行工具可以查看 Master 状态、扫描从站、读写 SDO - 内核态示例:mini 模块展示了
ecrt_request_master()→ecrt_master_activate()→ 周期任务的标准流程 - 用户态示例:user 程序使用相同的 API,配合 POSIX 实时调度实现毫秒级周期控制
- 排查:大多数启动问题源于配置遗漏或驱动未正确加载
如果你能看到ethercat slaves输出从站列表,并且示例程序正常打印状态信息,恭喜你——EtherCAT 总线已经跑通了。
下一章预告:第 4 章将深入讲解网络设备驱动的选型与配置,帮助你在 Generic 通用驱动和各种 Native 原生驱动之间做出正确选择,并掌握驱动的配置方法。
