【IgH EtherCAT】EtherCAT + Xenomai 实时任务:初始化、周期循环与PDO映射

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.koec_generic.ko / ec_igb.ko/dev/EtherCATXethercatctllibethercatethercat.conf / systemd scriptsState MachinesMailbox Protocols绑定网卡创建设备节点用户空间控制用户程序接口启动 & 参数配置总线状态管理协议解析(CoE/SoE/EoE)


    📌 图示说明

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

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

    • Driver

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

    • FSM

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

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

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

    📌 说明

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

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

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


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

    Mailbox 协议支持CoE HandlerSoE HandlerEoE HandlerVoE Handlerec_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.youkuaiyun.com/column/ganm3d55zd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值