EtherCAT的igh学习与研究(二)

简述

此部分内容主要基于EtherCAT的igh学习与研究(一)的后续记录

正文

1.1 双主站与多主站配置

IgH EtherCAT Master 支持多个主站实例,每个主站独立管理自己的 EtherCAT 从站网络。

多主站应用场景

  • 🔴 冗余备份 - 主主站故障时备用主站接管

  • 🔵 网络隔离 - 不同物理网络使用不同主站

  • 🟢 负载分担 - 大型系统分散到多个主站

  • 🟡 功能分区 - 不同安全等级设备使用不同主站

1.1.1 多主站架构概述

1.1.1双主站配置示例

方案 A:双网卡冗余配置(推荐)

硬件配置

  • 主站 0:eth0 (MAC: c4:83:4f:27:30:5a) - 主用

  • 主站 1:eth1 (MAC: c4:83:4f:27:30:5b) - 备用

配置文件 (/etc/ethercat.conf):

复制代码
# ===== 主站 0 配置 =====
MASTER0_DEVICE="c4:83:4f:27:30:5a"
MASTER0_NAME="Primary_Master"

# ===== 主站 1 配置 =====
MASTER1_DEVICE="c4:83:4f:27:30:5b"
MASTER1_NAME="Backup_Master"

# 设备驱动(两个主站使用相同驱动)
DEVICE_MODULES="dwmac-rk dwmac-rk"

# 可选:启动时设置网口 UP
LINK_DEVICES="eth0 eth1"

用户空间应用

复制代码
// 应用 1 - 使用主站 0
ec_master_t *master0 = ecrt_request_master(0);  // 主用
ec_domain_t *domain0 = ecrt_master_create_domain(master0);

// 应用 2 - 使用主站 1
ec_master_t *master1 = ecrt_request_master(1);  // 备用
ec_domain_t *domain1 = ecrt_master_create_domain(master1);

1.1.3 多主站配置示例

四主站配置
复制代码
# 主站 0 - 生产网络
MASTER0_DEVICE="c4:83:4f:27:30:50"
# 主站 1 - 测试网络
MASTER1_DEVICE="c4:83:4f:27:30:51"
# 主站 2 - 冗余备份
MASTER2_DEVICE="c4:83:4f:27:30:52"
# 主站 3 - 扩展网络
MASTER3_DEVICE="c4:83:4f:27:30:53"

# 四个主站使用相同或不同驱动
DEVICE_MODULES="dwmac-rk dwmac-rk dwmac-rk dwmac-rk"

# 启动所有网口
LINK_DEVICES="eth0 eth1 eth2 eth3"

**设备节点**:

- `/dev/EtherCAT0` - 主站 0
- `/dev/EtherCAT1` - 主站 1
- `/dev/EtherCAT2` - 主站 2
- `/dev/EtherCAT3` - 主站 3

1.1.4 主站间关系与通信

主站独立性

关键特性

  1. 独立运行 - 每个主站独立管理自己的从站网络

  2. 无共享状态 - 主站间不共享配置和状态

  3. 独立应用 - 不同应用可以访问不同主站

  4. 物理隔离 - 每个主站使用独立网卡和网络

主站间协调(需要用户空间实现):

复制代码
// 示例:主从备份逻辑
if (master0_active()) {
    use_master(0);  // 使用主站 0
} else if (master1_active()) {
    use_master(1);  // 切换到主站 1
}

1.1.5 启动脚本示例

systemd 服务(多主站)

创建多个服务文件:

/etc/systemd/system/ethercat0.service (主站 0):

复制代码
[Unit]
Description=EtherCAT Master 0 Service
After=network.target

[Service]
Type=oneshot
ExecStart=/sbin/modprobe ec_master MASTER0_DEVICE=c4:83:4f:27:30:5a
ExecStart=/sbin/modprobe ec_dwmac-rk
RemainAfterExit=yes
ExecStop=/sbin/rmmod ec_dwmac-rk
ExecStop=/sbin/rmmod ec_master

[Install]
WantedBy=multi-user.target

/etc/systemd/system/ethercat1.service (主站 1):

复制代码
[Unit]
Description=EtherCAT Master 1 Service
After=ethercat0.service

[Service]
Type=oneshot
ExecStart=/sbin/modprobe ec_master MASTER1_DEVICE=c4:83:4f:27:30:5b
ExecStart=/sbin/modprobe ec_dwmac-rk
RemainAfterExit=yes
ExecStop=/sbin/rmmod ec_dwmac-rk
ExecStop=/sbin/rmmod ec_master

[Install]
WantedBy=multi-user.target

启动命令

复制代码
# 启动主站 0
sudo systemctl start ethercat0.service

# 启动主站 1
sudo systemctl start ethercat1.service

# 查看状态
systemctl status ethercat0.service
systemctl status ethercat1.service

# 查看设备节点
ls -l /dev/EtherCAT*

1.1.6 配置对比表

配置项 单主站 双主站 多主站
配置文件 MASTER0_DEVICE MASTER0_DEVICE MASTER1_DEVICE MASTER0_DEVICE MASTER1_DEVICE MASTER2_DEVICE...
设备节点 /dev/EtherCAT0 /dev/EtherCAT0 /dev/EtherCAT1 /dev/EtherCAT0 /dev/EtherCAT1 /dev/EtherCAT2...
驱动实例 1 个 2 个 N 个
网卡数量 1 个 2 个 N 个
应用访问 ecrt_request_master(0) ecrt_request_master(0) ecrt_request_master(1) ecrt_request_master(0~N)
适用场景 简单系统 冗余备份 大型分布式系统

1.2 多主站时钟同步

1.2.1 DC 同步原理

分布式时钟(Distributed Clocks, DC) 是 EtherCAT 实现高精度同步的核心机制。

单主站 DC 同步

多主站同步挑战

  • ❌ 每个主站有独立的参考从站

  • ❌ 不同主站的时钟源可能不同步

  • ❌ 需要跨主站的时间基准统一

1.2.2 多主站同步方案

方案 A:统一时钟源(推荐)

原理:所有主站使用同一个外部时钟源(如 PTP、GPS、IRIG-B)

实现步骤

  1. 安装 PTP 服务(linuxptp):

    安装 PTP 守护进程

    sudo apt install linuxptp

    启动 PTP 从时钟(同步到 PTP 主时钟)

    sudo ptp4l -i eth0 -s -m
    sudo phc2sys -s eth0 -c CLOCK_REALTIME -m

2. 应用层同步代码

复制代码
/ 每个主站的应用都从系统时钟获取时间
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
uint64_t app_time = TIMESPEC2NS(ts);

// 同步到各自的主站
ecrt_master_application_time(master0, app_time);
ecrt_master_sync_reference_clock(master0);
ecrt_master_sync_slave_clocks(master0);

ecrt_master_application_time(master1, app_time);
ecrt_master_sync_reference_clock(master1);
ecrt_master_sync_slave_clocks(master1);

3.周期性同步(每 10 个周期同步一次):

复制代码
static int sync_counter = 0;

void cyclic_task(void) {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    uint64_t app_time = TIMESPEC2NS(ts);
    
    // 每 10 周期同步一次 DC
    if (++sync_counter >= 10) {
        sync_counter = 0;
        
        // 同步主站 0
        ecrt_master_application_time(master0, app_time);
        ecrt_master_sync_reference_clock(master0);
        ecrt_master_sync_slave_clocks(master0);
        
        // 同步主站 1
        ecrt_master_application_time(master1, app_time);
        ecrt_master_sync_reference_clock(master1);
        ecrt_master_sync_slave_clocks(master1);
    }
    
    // 发送过程数据
    ecrt_domain_queue(domain0);
    ecrt_master_send(master0);
    
    ecrt_domain_queue(domain1);
    ecrt_master_send(master1);
}
方案 B:主从主站同步

原理:一个主站作为时间主站,其他主站同步到主站的时间

复制代码
// 主站 0 - 时间主站
void master0_sync_task(void) {
    static int counter = 0;
    
    if (++counter >= 10) {
        counter = 0;
        
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        uint64_t app_time = TIMESPEC2NS(ts);
        
        // 正常同步
        ecrt_master_application_time(master0, app_time);
        ecrt_master_sync_reference_clock(master0);
        ecrt_master_sync_slave_clocks(master0);
    }
    
    ecrt_domain_queue(domain0);
    ecrt_master_send(master0);
}

// 主站 1 - 时间从站
void master1_sync_task(void) {
    static int counter = 0;
    
    if (++counter >= 100) {  // 每 100ms 同步一次到主站 0
        counter = 0;
        
        // 从主站 0 获取参考时间
        uint32_t ref_time;
        if (ecrt_master_reference_clock_time(master0, &ref_time) == 0) {
            // 使用主站 0 的时间同步自己的从站
            ecrt_master_application_time(master1, ref_time);
            ecrt_master_sync_reference_clock(master1);
            ecrt_master_sync_slave_clocks(master1);
        }
    }
    
    ecrt_domain_queue(domain1);
    ecrt_master_send(master1);
}
方案 C:共享参考从站(特殊场景)

说明:如果两个主站连接到同一个物理从站网络,可以让一个主站的参考从站作为另一个主站的参考

复制代码
# 主站 0 - 使用从站 1 作为参考
MASTER0_DEVICE="c4:83:4f:27:30:5a"
DEVICE_MODULES="dwmac-rk"

# 主站 1 - 使用相同的参考从站
MASTER1_DEVICE="c4:83:4f:27:30:5b"
DEVICE_MODULES="dwmac-rk"

1.2.3 同步精度对比

同步方案 精度 实现复杂度 适用场景
方案 A:统一时钟源 ±1μs 中等 高精度要求系统
方案 B:主从主站 ±10μs 简单 一般工业应用
方案 C:共享参考 ±5μs 复杂 特殊网络拓扑

1.2.4 完整同步示例代码

双主站同步应用

复制代码
#include <ecrt.h>
#include <time.h>
#include <pthread.h>

// 主站句柄
static ec_master_t *master0 = NULL;
static ec_master_t *master1 = NULL;
static ec_domain_t *domain0 = NULL;
static ec_domain_t *domain1 = NULL;

// 同步计数器
static int sync_counter = 0;
static const int SYNC_INTERVAL = 10;  // 每 10 个周期同步一次

// 初始化主站
int init_masters(void) {
    // 获取主站 0
    master0 = ecrt_request_master(0);
    if (!master0) {
        fprintf(stderr, "Failed to get master 0\n");
        return -1;
    }
    
    // 获取主站 1
    master1 = ecrt_request_master(1);
    if (!master1) {
        fprintf(stderr, "Failed to get master 1\n");
        ecrt_release_master(master0);
        return -1;
    }
    
    // 创建域
    domain0 = ecrt_master_create_domain(master0);
    domain1 = ecrt_master_create_domain(master1);
    
    return 0;
}

// 同步任务(实时线程)
void cyclic_sync_task(void) {
    struct timespec ts;
    uint64_t app_time;
    
    // 获取当前时间
    clock_gettime(CLOCK_REALTIME, &ts);
    app_time = TIMESPEC2NS(ts);
    
    // 周期性同步 DC
    if (++sync_counter >= SYNC_INTERVAL) {
        sync_counter = 0;
        
        // 同步主站 0
        ecrt_master_application_time(master0, app_time);
        ecrt_master_sync_reference_clock(master0);
        ecrt_master_sync_slave_clocks(master0);
        
        // 同步主站 1
        ecrt_master_application_time(master1, app_time);
        ecrt_master_sync_reference_clock(master1);
        ecrt_master_sync_slave_clocks(master1);
        
        // 可选:监控同步误差
        uint32_t sync_diff0, sync_diff1;
        ecrt_master_sync_monitor_queue(master0);
        ecrt_master_sync_monitor_queue(master1);
        sync_diff0 = ecrt_master_sync_monitor_process(master0);
        sync_diff1 = ecrt_master_sync_monitor_process(master1);
        
        if (sync_diff0 > 1000 || sync_diff1 > 1000) {
            fprintf(stderr, "Sync error too large: %u, %u\n", 
                    sync_diff0, sync_diff1);
        }
    }
    
    // 发送过程数据
    ecrt_domain_queue(domain0);
    ecrt_master_send(master0);
    
    ecrt_domain_queue(domain1);
    ecrt_master_send(master1);
}

// 主函数
int main(void) {
    if (init_masters() != 0) {
        return 1;
    }
    
    printf("Dual-master EtherCAT system started\n");
    
    // 实时循环
    while (1) {
        cyclic_sync_task();
        usleep(1000);  // 1ms 周期
    }
    
    ecrt_release_master(master0);
    ecrt_release_master(master1);
    return 0;
}

1.2.5 最佳实践建议

  1. 使用 PTP 统一时钟源 - 最高精度和可靠性

  2. 降低同步频率 - 每 10-100 个周期同步一次即可

  3. 监控同步误差 - 实时检测同步质量

  4. 选择稳定从站 - 参考从站应连接稳定

  5. 网络隔离 - 不同主站使用独立物理网络

  6. 避免频繁同步 - 过度同步会增加网络负载

  7. 避免多个参考源 - 会导致时钟漂移

1.3 实际部署步骤

1.3.1 文件部署清单

解压 rk3576-ethercat-6.1-*.tar.gz 后,需要配置以下文件:

文件 源位置 目标位置 是否需配置
ethercat.conf /usr/local/etc/ethercat.conf /etc/ethercat.conf ✅ 需修改
ethercat.service /usr/local/lib/systemd/system/ethercat.service /etc/systemd/system/ethercat.service 可选
ec_master.ko /lib/modules/ethercat/ec_master.ko /lib/modules/$(uname -r)/kernel/drivers/ethercat/ ✅ 需加载
ec_dwmac-rk.ko /lib/modules/ethercat/ec_dwmac-rk.ko /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/ ✅ 需加载

1.3.2 部署步骤(RK3576)

步骤 1: 加载内核模块

复制代码
# 创建模块目录
sudo mkdir -p /lib/modules/$(uname -r)/kernel/drivers/ethercat/
sudo mkdir -p /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/stmmac/

# 拷贝模块
sudo cp /tmp/lib/modules/ethercat/*.ko /lib/modules/$(uname -r)/kernel/drivers/

# 更新模块依赖
sudo depmod -a

# 测试加载
sudo modprobe ec_master
sudo modprobe ec_dwmac-rk

# 验证加载
lsmod | grep ec

步骤 2: 配置 ethercat.conf

复制代码
 获取网卡 MAC 地址
ip link show eth0

# 编辑配置文件
sudo vi /etc/ethercat.conf

# 添加配置
MASTER0_DEVICE="c4:83:4f:27:30:5b"
DEVICE_MODULES="dwmac-rk"
LINK_DEVICES="eth0"

步骤 3: 配置 systemd 服务

复制代码
# 拷贝服务文件
sudo cp /tmp/usr/local/lib/systemd/system/ethercat.service /etc/systemd/system/

# 重载 systemd
sudo systemctl daemon-reload

# 启动服务
sudo systemctl start ethercat

# 设置开机自启
sudo systemctl enable ethercat

步骤 4: 验证状态

复制代码
# 查看服务状态
sudo systemctl status ethercat

# 查看主站状态
sudo ethercat master

# 查看从站状态
sudo ethercat slaves

# 查看内核日志
dmesg | grep -i ethercat

1.4 常见问题与调试

1.4.1 启动失败排查指南

步骤 问题 检查命令 解决方法
1 模块加载失败 lsmod | grep ec 重新编译匹配内核的模块
2 MAC 地址无效 ip link show 使用正确格式
3 驱动替换失败 lsmod | grep igb 先手动 rmmod 原驱动
4 设备节点不存在 ls /dev/EtherCAT* 重新加载 ec_master 模块
5 主站状态异常 ethercat master 检查网卡 link 状态

常用调试命令

复制代码
# 模块相关
lsmod | grep ec                 # 查看已加载的 EtherCAT 模块
dmesg | grep EtherCAT           # 查看内核日志
modinfo ec_master               # 查看模块信息

# 设备节点
ls -la /dev/EtherCAT*           # 查看设备节点
ls -la /sys/class/EtherCAT/     # 查看设备类

# 主站状态
ethercat master                 # 查看主站状态
ethercat slaves                 # 查看从站列表

1.4.2 内核日志分析

正常启动日志示例

复制代码
dmesg | grep -i ethercat

# 输出示例:
[  123.456789] EtherCAT: Master module initialized
[  123.567890] EtherCAT: Registered device /dev/EtherCAT0
[  123.678901] EtherCAT: Device c4:83:4f:27:30:5b attached
[  123.789012] EtherCAT: Master 0 is now IDLE

错误日志示例及解决方法

复制代码
# 错误 1: 找不到设备
[  123.456789] EtherCAT: ERROR: Device c4:83:4f:27:30:5b not found
# 解决:检查 MAC 地址是否正确,网卡是否已识别

# 错误 2: 模块版本不匹配
[  123.456789] ec_master: disagrees about version of symbol module_layout
# 解决:重新编译匹配当前内核版本的模块

# 错误 3: 驱动加载失败
[  123.456789] EtherCAT: Failed to load ec_dwmac-rk module
# 解决:检查模块路径,确认依赖关系

1.4.3 性能调试

查看主站周期时间

复制代码
# 使用 ethercat 工具
ethercat master -v

# 输出示例:
Master 0: State INIT, HW address: c4:83:4f:27:30:5b
  Cycle Time: 1000 us (configured: 1000 us)
  Jitter: 5 us

查看系统延迟

复制代码
# 安装 cyclictest
sudo apt install rt-tests

# 运行测试
sudo cyclictest -m -t -p 95 -n -D 10s

# 输出示例:
# Max Latencies: 00000015 00000012 00000010 00000008 00000005

优化建议

  1. 使用 Preempt-RT 内核

  2. 隔离 CPU 核心(isolcpus 内核参数)

  3. 设置 IRQ 亲和性

  4. 禁用节能模式(intel_idle.max_cstate=0)

1.5 小结

类别 内容
配置文件 ethercat.conf, sysconfig/ethercat, init.d/ethercat, ethercatctl, ethercat.service
启动方式 systemd(现代标准)/ SysV init(兼容性好)
启动流程 读取配置 → 设置网口 → 加载主站模块 → 替换网卡驱动 → 设备就绪
核心参数 MASTER0_DEVICE, DEVICE_MODULES, LINK_DEVICES
技术原理 MAC 地址匹配网卡、驱动替换、绕过网络栈、DMA 直接收发
部署步骤 拷贝模块 → 配置 MAC → 加载驱动 → 启动服务 → 验证状态
调试方法 dmesg 日志、lsmod 模块、ethercat 工具、cyclictest 性能测试

关键要点

  1. 配置文件决定行为 - MAC 地址必须与实际网卡匹配

  2. 驱动替换是关键 - 必须卸载原网卡驱动才能加载 EtherCAT 驱动

  3. 模块版本必须匹配 - 内核版本不一致会导致加载失败

  4. 实时性能优化 - Preempt-RT 内核 + CPU 隔离 + IRQ 亲和性

未完待续

相关推荐
炽烈小老头2 小时前
【每天学习一点算法 2026/04/11】Pow(x, n)
学习·算法
旖-旎2 小时前
哈希表(存在重复元素)(3)
数据结构·c++·学习·算法·leetcode·散列表
weixin_513449962 小时前
walk_these_ways项目学习记录第九篇(通过行为多样性 (MoB) 实现地形泛化)--学习算法
学习·算法·机器学习
chh5633 小时前
C++--内存管理
java·c语言·c++·windows·学习·面试
CNemon3 小时前
《怎样学习文言文》溯源
学习
wayz113 小时前
21天机器学习核心算法学习计划(量化方向)
学习·算法·机器学习
Flandern11113 小时前
Go程序员学习AI大模型项目实战02:给 AI 装上“大脑”:从配置解包到流式生成的深度拆解
人工智能·后端·python·学习·golang
weixin_513449964 小时前
walk_these_ways项目学习记录第十篇(通过行为多样性 (MoB) 实现地形泛化)--从仿真到部署
人工智能·学习·算法
EnglishJun4 小时前
ARM嵌入式学习(二十一)--- Platform总线结合dts、gpio子系统、中断和错误处理
arm开发·学习