SVG架构图总结了EtherCAT实时控制程序的所有关键要素:

图表包含以下主要部分:

  1. 主线程流程

     - 显示程序初始化、配置和清理的完整生命周期

  2. 实时任务循环

     - 详细展示1ms周期的实时控制循环,包括:

  • EtherCAT帧的接收和发送

  • 域数据处理

  • 状态监控

  • 数字输出控制

  • 信号处理机制

     - 展示如何通过SIGTERM/SIGINT信号优雅地停止程序

  • EtherCAT网络拓扑

     - 可视化硬件配置:

    • 主站 (Master)

    • 总线耦合器 (EK1100)

    • 数字输出模块 (EL2004) 及其4个输出通道

  • 技术特性说明

     - 总结关键的技术参数:

    • 实时性能 (Xenomai, 1ms周期)

    • 通信协议 (EtherCAT)

    • 控制逻辑 (LED闪烁, 状态监控)

    • 硬件配置 (Beckhoff模块)

  • 数据流可视化

     - 用不同颜色的箭头表示数据发送、接收和控制流

  • 这个图表清晰地展示了工业自动化中EtherCAT实时通信系统的完整架构和工作原理。

    这是一个基于 IgH EtherCAT Master 和 Xenomai 实时扩展的 C 语言示例程序。其核心功能是建立一个简单的 EtherCAT 网络,并以硬实时的方式周期性地控制一个数字量输出模块

    程序的主要流程如下:

    1. 初始化与配置

    • 在 main 函数中,程序首先设置了信号处理(用于安全退出)和内存锁定(mlockall,防止内存交换以保证实时性)。

    • 请求并获取一个 EtherCAT 主站实例。

    • 创建一个过程数据域 (Domain),用于管理周期性交换的数据。

    • 为总线上的两个从站(一个 EK1100 总线耦合器和一个 EL2004 四通道数字量输出模块)创建配置。

    • 为 EL2004 配置其 PDO (过程数据对象),并将其中一个输出通道的 PDO 条目注册到之前创建的域中,这样就可以通过读写域的内存来控制该输出。

  • 激活与实时任务

    • 激活 EtherCAT 主站,使其开始在总线上与从站进行周期性通信。

    • 获取指向域过程数据内存区域的指针 domain1_pd

    • 创建一个高优先级的 Xenomai 实时任务 (my_task),并启动它。这个任务将以 1毫秒 的固定周期运行。

  • 实时循环 (my_task_proc)

    • ecrt_master_receive()

      : 接收从站发回的数据帧。

    • ecrt_domain_process()

      : 将接收到的数据更新到域内存中。

    • 应用逻辑

      : 程序的核心逻辑在这里。它维护一个 blink 变量,每 200ms 翻转一次状态(0/1切换)。然后,根据 blink 的状态,通过 EC_WRITE_U8 宏向过程数据内存区写入 0x0F (全开) 或 0x00 (全关),从而控制 EL2004 的输出通道。

    • ecrt_domain_queue()

      : 将要发送的数据(即刚刚写入的控制命令)准备好。

    • ecrt_master_send()

      : 将数据帧发送给从站。

    • 在每个 1ms 的周期内,任务执行标准的 EtherCAT 通信流程:

    • 任务还周期性地检查并打印主站和域的状态,用于监控和调试。

  • 程序终止

    • main

       函数在启动实时任务后,会进入一个低优先级的 while 循环,通过 sched_yield() 让出CPU。

    • 当用户按下 Ctrl+C 或发送 SIGTERM 信号时,signal_handler 会被调用,将全局标志 run 置为0。

    • 实时任务的 while 循环和主函数的 while 循环都会因此而退出。

    • 程序随后执行清理工作:删除实时任务,释放 EtherCAT 主站资源,然后正常退出。

    总而言之,这是一个教科书式的 EtherCAT 硬实时控制示例,展示了从硬件配置、实时任务创建到周期性数据交换和应用逻辑实现的完整过程。

    这个图表展示了程序的三个主要执行线程:

    1. 主线程

      :负责初始化EtherCAT系统、创建和管理实时任务

    2. 实时任务线程

      :执行1ms周期的实时控制循环,处理EtherCAT通信

    3. 信号处理

      :异步处理系统信号以优雅地停止程序

    图中的关键要素包括:

    • 初始化阶段

      :内存锁定、主站请求、域创建、从站配置

    • 实时循环

      :1ms周期的EtherCAT通信(接收→处理→发送)

    • 状态监控

      :定期检查主站和域的工作状态

    • 数字输出控制

      :200ms周期的LED闪烁控制

    • 优雅退出

      :通过信号处理机制安全停止程序

    这个泳道图清晰地展示了Xenomai实时系统中多线程并行执行的特点,以及EtherCAT实时通信的周期性特征。

    #include <errno.h> // 包含C标准库头文件,用于错误码处理(例如 strerror 函数)#include <signal.h> // 包含信号处理头文件,用于捕获如 SIGINT, SIGTERM 等中断信号#include <stdio.h> // 包含标准输入输出头文件,用于 printf, fprintf 等函数#include <string.h> // 包含字符串处理头文件,用于 strerror 等函数#include <sys/resource.h> // 包含系统资源操作头文件,虽然在此代码中未直接使用其函数,但常用于实时系统设置优先级#include <sys/time.h> // 包含时间相关头文件,定义了时间结构体#include <sys/types.h> // 包含基本系统数据类型头文件#include <unistd.h> // 包含 POSIX 标准 API 头文件,提供对操作系统服务的访问(如 sched_yield)#include <sys/mman.h> // 包含内存管理声明头文件,用于 mlockall 函数,防止内存交换#ifdef XENOMAI_API_V3 // C预处理器指令,检查是否定义了 XENOMAI_API_V3 宏#include <alchemy/task.h> // 如果是 Xenomai 3.x,包含 Alchemy API 的任务管理头文件#include <alchemy/sem.h> // 如果是 Xenomai 3.x,包含 Alchemy API 的信号量头文件enum {T_FPU = 0}; // 为 Xenomai 3.x 定义 T_FPU 枚举(表示不使用FPU),以兼容 2.x 的 API#else // 如果没有定义 XENOMAI_API_V3#include <rtdm/rtdm.h> // 包含实时驱动模型(RTDM)头文件#include <native/task.h> // 包含 Xenomai 2.x Native API 的任务管理头文件#include <native/sem.h> // 包含 Xenomai 2.x Native API 的信号量头文件#include <native/mutex.h> // 包含 Xenomai 2.x Native API 的互斥锁头文件#include <native/timer.h> // 包含 Xenomai 2.x Native API 的定时器头文件#include <rtdk.h> // 包含 Xenomai 的实时打印(rt_printf)头文件#endif // 结束 #ifdef 条件编译块#include <pthread.h> // 包含 POSIX 线程库头文件,虽然主实时逻辑用Xenomai,但可能用于非实时部分#include "ecrt.h" // 包含 IgH EtherCAT 主站的核心应用层 API 头文件RT_TASK my_task; // 声明一个 Xenomai 实时任务(RT_TASK)变量,名为 my_taskstatic volatile sig_atomic_t run = 1; // 声明一个静态的、易失的、信号安全的整型变量 run,并初始化为1。用作主循环的运行标志。/****************************************************************************/ // 分隔注释// EtherCAT // 区域注释:EtherCAT 相关变量static ec_master_t *master = NULL; // 声明一个静态的 EtherCAT 主站对象指针,并初始化为 NULLstatic ec_master_state_t master_state = {}; // 声明一个静态的主站状态结构体变量,并使用聚合初始化将其清零static ec_domain_t *domain1 = NULL; // 声明一个静态的 EtherCAT 过程数据域(Domain)指针,并初始化为 NULLstatic ec_domain_state_t domain1_state = {}; // 声明一个静态的域状态结构体变量,并清零static uint8_t *domain1_pd = NULL; // 声明一个静态的指向过程数据(Process Data)内存区域的8位无符号整型指针,并初始化为 NULLstatic ec_slave_config_t *sc_dig_out_01 = NULL; // 声明一个静态的从站配置对象指针,用于配置数字量输出从站,并初始化为 NULL/****************************************************************************/ // 分隔注释// process data // 区域注释:过程数据相关定义#define BusCoupler01_Pos  0, 0 // 宏定义:总线耦合器(Bus Coupler)的位置,别名 (主站索引0, 站地址0)#define DigOutSlave01_Pos 0, 1 // 宏定义:数字量输出从站(Digital Out Slave)的位置,别名 (主站索引0, 站地址1)#define Beckhoff_EK1100 0x00000002, 0x044c2c52 // 宏定义:倍福 EK1100 的厂商ID和产品代码#define Beckhoff_EL2004 0x00000002, 0x07d43052 // 宏定义:倍福 EL2004 的厂商ID和产品代码// offsets for PDO entries // 注释:PDO条目的偏移量static unsigned int off_dig_out0 = 0; // 声明一个静态无符号整型变量,用于存储某个PDO条目在过程数据域中的字节偏移量// process data // 区域注释:过程数据const static ec_pdo_entry_reg_t domain1_regs[] = { // 定义一个静态常量数组,用于注册需要映射到域的PDO条目   {DigOutSlave01_Pos, Beckhoff_EL2004, 0x7000, 0x01, &off_dig_out0, NULL}, // 第一个条目:从站位置、厂商/产品ID、PDO索引、PDO子索引、偏移量存储地址、无bit偏移   {} // 数组结束标志,一个内容全为0的空结构体};/****************************************************************************/ // 分隔注释/* Slave 1, "EL2004" // 注释:从站1 "EL2004" 的详细信息 * Vendor ID:       0x00000002 // 厂商ID * Product code:    0x07d43052 // 产品代码 * Revision number: 0x00100000 // 修订号 */const ec_pdo_entry_info_t slave_1_pdo_entries[] = { // 定义一个静态常量数组,描述 EL2004 从站的所有可用 PDO 条目   {0x7000, 0x01, 1}, /* Output */ // 条目1:索引0x7000,子索引0x01,位长度1 (第一个输出通道)   {0x7010, 0x01, 1}, /* Output */ // 条目2:索引0x7010,子索引0x01,位长度1 (第二个输出通道)   {0x7020, 0x01, 1}, /* Output */ // 条目3:索引0x7020,子索引0x01,位长度1 (第三个输出通道)   {0x7030, 0x01, 1}, /* Output */ // 条目4:索引0x7030,子索引0x01,位长度1 (第四个输出通道)};const ec_pdo_info_t slave_1_pdos[] = { // 定义一个静态常量数组,描述 EL2004 从站的 PDO 配置   {0x1600, 1, slave_1_pdo_entries + 0}, /* Channel 1 */ // PDO 1: RxPDO 0x1600, 包含1个条目, 条目信息从 slave_1_pdo_entries[0] 开始   {0x1601, 1, slave_1_pdo_entries + 1}, /* Channel 2 */ // PDO 2: RxPDO 0x1601, 包含1个条目, 条目信息从 slave_1_pdo_entries[1] 开始   {0x1602, 1, slave_1_pdo_entries + 2}, /* Channel 3 */ // PDO 3: RxPDO 0x1602, 包含1个条目, 条目信息从 slave_1_pdo_entries[2] 开始   {0x1603, 1, slave_1_pdo_entries + 3}, /* Channel 4 */ // PDO 4: RxPDO 0x1603, 包含1个条目, 条目信息从 slave_1_pdo_entries[3] 开始};ec_sync_info_t slave_1_syncs[] = { // 定义一个数组,描述 EL2004 从站的同步管理器(Sync Manager)配置   {0, EC_DIR_OUTPUT, 4, slave_1_pdos + 0, EC_WD_ENABLE}, // Sync Manager 0: 类型为输出(OUTPUT), 关联4个PDO, PDO信息从 slave_1_pdos[0] 开始, 启用看门狗(Watchdog)   {0xff} // 数组结束标志,同步管理器索引为0xff};/***************************************************************************** * Realtime task // 区域注释:实时任务相关函数 ****************************************************************************/void rt_check_domain_state(void) // 定义一个函数,用于检查并打印域的状态变化{    ec_domain_state_t ds = {}; // 声明一个局部的域状态结构体变量 ds,并清零ecrt_domain_state(domain1, &ds); // 调用 ecrt API,获取 domain1 的当前状态,并存入 ds    if (ds.working_counter != domain1_state.working_counter) { // 比较当前工作计数器(WC)与上次记录的WC        rt_printf("Domain1: WC %u.\n", ds.working_counter); // 如果不一致,使用实时打印函数输出新的WC值    }    if (ds.wc_state != domain1_state.wc_state) { // 比较当前工作计数器状态与上次记录的状态        rt_printf("Domain1: State %u.\n", ds.wc_state); // 如果不一致,输出新的WC状态值    }    domain1_state = ds; // 将当前状态 ds 赋值给全局的 domain1_state,用于下次比较}/****************************************************************************/ // 分隔注释void rt_check_master_state(void) // 定义一个函数,用于检查并打印主站的状态变化{    ec_master_state_t ms; // 声明一个局部的主站状态结构体变量 msecrt_master_state(master, &ms); // 调用 ecrt API,获取主站的当前状态,并存入 ms    if (ms.slaves_responding != master_state.slaves_responding) { // 比较当前响应的从站数量与上次记录的数量        rt_printf("%u slave(s).\n", ms.slaves_responding); // 如果不一致,输出新的从站数量    }    if (ms.al_states != master_state.al_states) { // 比较当前应用层(AL)状态与上次记录的状态        rt_printf("AL states: 0x%02X.\n", ms.al_states); // 如果不一致,以十六进制格式输出新的AL状态    }    if (ms.link_up != master_state.link_up) { // 比较当前链路连接状态与上次记录的状态        rt_printf("Link is %s.\n", ms.link_up ? "up" : "down"); // 如果不一致,输出链路是 "up" 还是 "down"    }    master_state = ms; // 将当前状态 ms 赋值给全局的 master_state,用于下次比较}/****************************************************************************/ // 分隔注释void my_task_proc(void *arg) // 定义实时任务的主体函数,参数为 void 指针{int cycle_counter = 0; // 定义一个整型变量,用作周期计数器,并初始化为0    unsigned int blink = 0; // 定义一个无符号整型变量,用作闪烁标志,并初始化为0rt_task_set_periodic(NULL, TM_NOW, 1000000); // 设置当前任务(NULL表示自身)为周期性任务,立即(TM_NOW)开始,周期为 1,000,000 纳秒 (1毫秒)while (run) { // 循环,只要全局变量 run 为1就一直执行rt_task_wait_period(NULL); // 等待下一个周期性调度点的到来(阻塞当前任务)		cycle_counter++; // 周期计数器加1// receive EtherCAT frames // 注释:接收 EtherCAT 帧ecrt_master_receive(master); // 从网络接口接收数据帧,放入主站的内部缓冲区ecrt_domain_process(domain1); // 处理域的数据,将接收到的数据解包到过程数据(PD)内存区rt_check_domain_state(); // 调用函数检查并打印域的状态变化if (!(cycle_counter % 1000)) { // 判断周期计数器是否是1000的倍数(即每1000个周期/1秒执行一次)rt_check_master_state(); // 调用函数检查并打印主站的状态变化		}if (!(cycle_counter % 200)) { // 判断周期计数器是否是200的倍数(即每200个周期/200毫秒执行一次)			blink = !blink; // 对 blink 变量取反(0变1,1变0),实现闪烁逻辑		}EC_WRITE_U8(domain1_pd + off_dig_out0, blink ? 0x0 : 0x0F); // 将数据写入过程数据区。如果blink为true(1),写入0x00;如果为false(0),写入0x0F。这里控制4个通道同时开关// send process data // 注释:发送过程数据ecrt_domain_queue(domain1); // 将域中需要发送的数据(刚写入的)放入主站的发送队列ecrt_master_send(master); // 将发送队列中的数据帧通过网络接口发送出去	}}/**************************************************************************** * Signal handler // 区域注释:信号处理器 ***************************************************************************/void signal_handler(int sig) // 定义信号处理函数,参数为信号编号{    run = 0; // 将全局运行标志 run 设置为0,使主循环和实时任务循环 gracefully 退出}/**************************************************************************** * Main function // 区域注释:主函数 ***************************************************************************/int main(int argc, char *argv[]) // C程序的入口主函数{    ec_slave_config_t *sc; // 声明一个局部的从站配置对象指针    int ret; // 声明一个整型变量,用于存储函数返回值#ifndef XENOMAI_API_V3 // C预处理器指令,检查是否没有定义 XENOMAI_API_V3 (即 Xenomai 2.x)    /* Perform auto-init of rt_print buffers if the task doesn't do so */ // 注释:如果任务不自己初始化,则自动初始化rt_print缓冲区    rt_print_auto_init(1); // 自动初始化 Xenomai 的实时打印缓冲区#endif // 结束 #ifndef 条件编译块    signal(SIGTERM, signal_handler); // 注册信号处理器,当收到终止信号(SIGTERM)时调用 signal_handler 函数    signal(SIGINT, signal_handler); // 注册信号处理器,当收到中断信号(SIGINT, e.g., Ctrl+C)时调用 signal_handler 函数    mlockall(MCL_CURRENT | MCL_FUTURE); // 锁定当前和未来所有分配的内存,防止被交换到磁盘,确保实时性    printf("Requesting master...\n"); // 在控制台打印提示信息    master = ecrt_request_master(0); // 请求索引为0的 EtherCAT 主站实例    if (!master) { // 检查主站请求是否成功        return -1; // 如果失败(返回NULL),程序返回-1并退出    }    domain1 = ecrt_master_create_domain(master); // 在主站上创建一个过程数据域    if (!domain1) { // 检查域创建是否成功        return -1; // 如果失败,程序返回-1并退出    }    printf("Creating slave configurations...\n"); // 在控制台打印提示信息    // Create configuration for bus coupler // 注释:为总线耦合器创建配置    sc = ecrt_master_slave_config(master, BusCoupler01_Pos, Beckhoff_EK1100); // 为位置(0,0)的EK1100总线耦合器创建从站配置    if (!sc) { // 检查配置创建是否成功        return -1; // 如果失败,程序返回-1并退出    }    sc_dig_out_01 = // 为数字量输出从站创建配置,并将其地址存入全局指针        ecrt_master_slave_config(master, DigOutSlave01_Pos, Beckhoff_EL2004); // 为位置(0,1)的EL2004从站创建配置    if (!sc_dig_out_01) { // 检查配置创建是否成功        fprintf(stderr, "Failed to get slave configuration.\n"); // 向标准错误输出流打印错误信息        return -1; // 如果失败,程序返回-1并退出    }    if (ecrt_slave_config_pdos(sc_dig_out_01, EC_END, slave_1_syncs)) { // 为 EL2004 从站配置 PDO 和同步管理器        fprintf(stderr, "Failed to configure PDOs.\n"); // 如果配置失败,打印错误信息        return -1; // 并返回-1退出    }    if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) { // 将定义的 PDO 注册列表注册到域中        fprintf(stderr, "PDO entry registration failed!\n"); // 如果注册失败,打印错误信息        return -1; // 并返回-1退出    }    printf("Activating master...\n"); // 在控制台打印提示信息    if (ecrt_master_activate(master)) { // 激活主站,开始进行总线通信        return -1; // 如果激活失败,返回-1退出    }    if (!(domain1_pd = ecrt_domain_data(domain1))) { // 获取域的过程数据内存区的指针        fprintf(stderr, "Failed to get domain data pointer.\n"); // 如果获取失败(返回NULL),打印错误信息        return -1; // 并返回-1退出    }    ret = rt_task_create(&my_task, "my_task", 0, 80, T_FPU); // 创建一个 Xenomai 实时任务    // 参数:任务句柄地址, 任务名, 栈大小(0=默认), 优先级(80), 浮点运算单元(FPU)选项    if (ret < 0) { // 检查任务创建是否成功        fprintf(stderr, "Failed to create task: %s\n", strerror(-ret)); // 如果失败,打印错误信息(使用strerror将错误码转为字符串)        return -1; // 并返回-1退出    }    printf("Starting my_task...\n"); // 在控制台打印提示信息    ret = rt_task_start(&my_task, &my_task_proc, NULL); // 启动已创建的实时任务    // 参数:任务句柄, 任务函数指针, 传递给任务的参数    if (ret < 0) { // 检查任务启动是否成功        fprintf(stderr, "Failed to start task: %s\n", strerror(-ret)); // 如果失败,打印错误信息        return -1; // 并返回-1退出    }while (run) { // 主线程进入一个等待循环,只要 run 标志为1sched_yield(); // 主动让出 CPU,让其他任务(特别是实时任务)运行	}    printf("Deleting realtime task...\n"); // 在收到退出信号后,打印提示信息    rt_task_delete(&my_task); // 删除 Xenomai 实时任务    printf("End of Program\n"); // 打印程序结束信息    ecrt_release_master(master); // 释放之前请求的 EtherCAT 主站资源    return 0; // 程序正常退出,返回0}

    IgH EtherCAT 是一个专为 Linux 平台设计的 开源 EtherCAT 主站协议栈,由德国 EtherLab 项目开发,广泛应用于工业自动化、机器人控制和实时运动控制系统中。下面是它的简要介绍:


    🧠 项目概述

    • 全称

      :IgH EtherCAT Master

    • 开发平台

      :Linux(支持 RTAI、Xenomai、RT-Preempt 等实时扩展)

    • 协议支持

      :完整支持 EtherCAT 协议,包括 COE、SOE、EOE、分布式时钟(DC)等

    • 开源协议

      :GPL 许可,免费使用和修改

    • 官网

      :etherlab.org


    🔧 核心功能

    • 构建 Linux 字符设备,应用程序通过访问该设备与主站模块通信

    • 提供命令行工具,可直接操作从站设备(如设置地址、读写 PDO/SDO)

    • 支持多种网卡驱动方式:

      • Generic 驱动

        :适用于所有网卡,依赖 Linux 网络协议栈

      • Native 驱动

        :针对特定网卡,可直接操作硬件,实时性更强


    🧩 使用场景

    • 实时控制系统(如机器人、数控机床、自动化产线)

    • 教育与研究(开源特性便于教学和实验)

    • 商业应用(已有多个专利和产品基于该项目)


    🔍 与 SOEM 的对比

    特性

    IgH EtherCAT Master

    SOEM (Simple Open EtherCAT Master)

    功能完整性

    ✅ 高

    ⚠️ 较简化

    平台依赖

    Linux + 实时内核

    可移植至嵌入式平台(如 MCU)

    实时性支持

    强(支持 DC、RT 扩展)

    中等

    使用复杂度

    较高

    较低

    适用场景

    工业级控制系统

    资源受限的嵌入式应用


    如果你正在做机器人控制或工业自动化项目,IgH EtherCAT 是一个功能强大且成熟的主站实现。需要我帮你梳理它的架构或如何将它集成到你的系统中吗?我可以按模块逐步解析。

    🏗️ IgH EtherCAT 主站结构图

    IgH EtherCAT 主站 ec_master.ko ec_generic.ko / ec_igb.ko /dev/EtherCATX ethercatctl libethercat ethercat.conf / systemd scripts State Machines Mailbox Protocols 绑定网卡 创建设备节点 用户空间控制 用户程序接口 启动 & 参数配置 总线状态管理 协议解析(CoE/SoE/EoE)


    📌 图示说明

    • 每个组件对应一个功能模块或设备节点

    • 箭头代表控制流或数据流方向

    • Driver

       可以是通用或原生网卡驱动,取决于配置

    • FSM

       和 Mailbox 是主站内部的子模块,但在源码中也有较独立的逻辑实现

    🔄 状态机模块结构图(State Machines)

    状态机模块 Master State Machine Slave Scan State Machine Slave Config State Machine State Change State Machine SII State Machine PDO State Machine 扫描从站 配置从站 状态切换 读取 EEPROM 映射 PDO

    📌 说明

    • 每个状态机模块负责 EtherCAT 总线的某一阶段。

    • 状态机之间是顺序执行关系,支持嵌套与子状态机调用。

    • 可扩展为状态图或流程图,适合教学用途。


    📡 Mailbox 协议模块结构图(Mailbox Protocols)

    Mailbox 协议支持 CoE Handler SoE Handler EoE Handler VoE Handler ec_master.ko

    📌 说明

    • 所有协议处理器由主模块调用,处理 Mailbox 通信。

    • 可根据从站类型启用不同协议(如伺服驱动器使用 SoE)。

    下面我将为你逐一介绍 IgH EtherCAT Master 的主要模块及其具体功能,保持模块级粒度,便于你后续做文档映射或教学拆解:


    🧠 1. ec_master.ko(主站内核模块)

    • 创建 EtherCAT 主站实例,每个实例对应 /dev/EtherCATX 字符设备

    • 管理从站扫描、状态切换、PDO 映射、DC 同步等核心流程

    • 支持多个主站并行运行(通过 master_count 参数)

    • 提供统一的设备接口供网卡驱动绑定

    • 实现 Mailbox 协议解析(CoE、SoE、EoE、VoE)


    🔌 2. 网卡驱动模块(如 ec_igb.koec_generic.ko

    • Native 驱动

      :直接操作网卡硬件,禁用中断,实现高实时性

    • Generic 驱动

      :使用 Linux 网络协议栈,兼容性强但实时性较弱

    • 通过 MAC 地址与主站实例绑定,实现数据收发

    • 可支持冗余网卡配置(主/备网卡)


    📁 3. 字符设备接口(/dev/EtherCATX

    • 用户空间程序通过 ioctl 与主站通信

    • 支持并发访问、线程安全

    • 提供从站配置、PDO 映射、状态查询等接口

    • 是用户态与内核态的桥梁


    🧰 4. 用户空间工具与库

    a. ethercatctl(命令行工具)
    • 扫描从站设备

    • 显示设备信息(如 ethercat slaves -v

    • 设置 PDO 映射、状态切换、DC 同步等

    b. libethercat(用户态 C 接口库)
    • 提供应用程序访问 EtherCAT 主站的 API

    • 支持周期性数据交换、状态监控

    • 可嵌入实时任务中运行(如周期性 cyclic_task()


    ⚙️ 5. 启动与配置脚本

    • ethercat.conf

      :配置网卡、驱动类型、调试级别等

    • init.d

       / systemd 脚本:加载主站模块、驱动、创建设备节点

    • 支持自动创建 EoE handler、设置 pcap 缓冲区等高级参数


    🔄 6. 状态机模块(State Machines)

    模块名称

    功能描述

    主站状态机

    管理主站生命周期(Orphaned → Idle → Operational)

    从站扫描状态机

    自动发现连接的从站设备

    从站配置状态机

    配置 PDO 映射、同步管理

    状态变更状态机

    控制从站状态切换(Init → PreOp → SafeOp → Op)

    SII 状态机

    读取从站 EEPROM 中的配置信息

    PDO 状态机

    管理过程数据交换的映射与更新


    📡 7. Mailbox 协议支持模块

    协议类型

    功能描述

    CoE(CANopen)

    访问对象字典,配置参数

    SoE(Servo)

    控制伺服驱动器

    EoE(Ethernet)

    实现 IP 通信透传

    VoE(Vendor)

    支持厂商自定义协议

    参考网址

    https://wenku.csdn.net/column/ganm3d55zd

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐