【原创】IgH EtherCAT主站详解(二十二)--ENI XML 结构、生成与使用

ENI XML 配置文件解读

8.2 — ENI XML 结构、生成与使用

概览

什么是 ENI XML?

ENI XML (EtherCAT Network Information XML) 是一种基于 XML 的网络描述文件,用于完整描述 EtherCAT 主站的配置信息。它由 Beckhoff TwinCAT 等工程工具生成,定义了总线拓扑结构、从站配置、PDO 映射、Sync Manager 设置、FMMU 映射以及 DC 同步参数等全部网络参数。

ENI XML 的核心作用

ENI XML 在 EtherCAT 系统中扮演"网络蓝图"的角色,涵盖以下关键信息:

  • 总线拓扑:从站位置 (PhysAddr)、设备标识 (VendorId / ProductCode / RevisionNo)
  • 从站配置:每个从站的 SyncManager、FMMU、PDO 映射
  • DC 同步:分布式时钟的 AssignActivate 参数、周期时间、同步偏移
  • 初始化命令:从站状态转换过程中需要执行的初始化序列
  • 过程映像:主站侧完整的输入/输出过程数据布局
  • 循环任务:周期性帧的发送时序和命令编排

IgH 两种配置方式

API 配置方式:应用程序通过 ecrt API 在运行时动态配置(ecrt_slave_config_pdos()ecrt_slave_config_sync_manager() 等)。IgH 原生推荐方式,灵活且无需外部文件。
ENI 配置方式:由外部工具(如 TwinCAT)生成 ENI XML 文件,应用程序加载该文件进行配置。适合从 TwinCAT 工程迁移或需要完整初始化命令序列的场景。

项目 https://github.com/open-edge-platform/edge-ai-libraries/tree/main/libraries/edge-control-libraries/fieldbus/ecat-enablekit 提供了完整的 ENI XML 解析库(examples/eni_dc_demo/ecat/eniconfig/),支持从 ENI XML 文件自动提取配置并应用到 IgH 主站。

技术详情

ENI XML 根结构

ENI XML 文件以 <EtherCATConfig> 作为根元素,内部包含一个 <Config> 节点,<Config> 下分为四大块:

[流程图 - 结构化描述]

步骤描述
1 <EtherCATConfig>
2 <Config>
3 <Master>
4 <Slave> (可多个)
5 <Cyclic>
6 <ProcessImage>
7 <Info> — 主站设备信息
8 <MailboxStates> — 邮箱状态地址
9 <InitCmds> — 主站级初始化命令
10 <Info> — 从站标识
11 <ProcessData> — SM/PDO 配置
12 <Mailbox> — 邮箱与 CoE 配置
13 <InitCmds> — 从站初始化序列
14 <CycleTime> — 周期时间
15 <Frame> — 循环帧命令
16 <Inputs> — 输入过程映像
17 <Outputs> — 输出过程映像

关键元素详解

XML 元素层级说明
<Slave> Config 子元素 描述单个从站。包含 <Info>(PhysAddr 物理地址、Name 名称、VendorId/ProductCode/RevisionNo/SerialNo 设备标识)、<ProcessData><Mailbox><InitCmds>
<SyncManager> ProcessData 内 通过 <Sm2>/<Sm3> 子元素配置。定义 SM 方向(Outputs/Inputs)、物理起始地址(StartAddress)、默认大小(DefaultSize)、控制字节(ControlByte)以及关联的 PDO 索引
<TxPdo> / <RxPdo> ProcessData 内 PDO 映射描述。TxPDO(索引 0x1A00-0x1BFF)为从站到主站方向(输入),RxPDO(索引 0x1600-0x17FF)为主站到从站方向(输出)。Sm 属性指定所属 SyncManager 编号
<Entry> PDO 内 单个 PDO 条目。包含 <Index>(对象字典索引,如 0x6040)、<SubIndex>(子索引)、<BitLen>(位宽,如 16/32)、<Name>(名称)、<DataType>(数据类型)
<Fmmu> InitCmds 内 FMMU 映射通过 InitCmd 写入 ESC 寄存器(地址 0x0600 起)。配置逻辑地址到物理地址的映射,包含逻辑起始地址、长度、物理起始地址、读写使能等
<Dc> Slave 内 分布式时钟配置。包含 AssignActivate(激活参数)、CycleTime0/CycleTime1(SYNC0/SYNC1 周期)、ShiftTime0/ShiftTime1(偏移时间)
<InitCmd> 多层级 初始化命令。<Transition> 指定状态转换阶段(IP/PS/SO 等),<Cmd> 为 EtherCAT 命令类型,<Adp>/<Ado> 为地址,<Data> 为写入数据,<Validate> 为验证条件

ENI XML 示例解析

以下摘录自本项目 examples/eni_dc_demo/pansonic-a6b-eni-1-axis.xml,展示松下 A6B 伺服驱动的 ENI 配置:

从站标识

<Slave>
  <Info>
    <Name><![CDATA[Drive 1 (MBDLN25BE)]]></Name>
    <PhysAddr>1001</PhysAddr>       <!-- 物理地址 (站号) -->
    <AutoIncAddr>0</AutoIncAddr>    <!-- 自动增量地址 -->
    <VendorId>1647</VendorId>       <!-- 厂商 ID: 0x066F -->
    <ProductCode>1614282757</ProductCode> <!-- 产品代码: 0x60380006 -->
    <RevisionNo>65536</RevisionNo>  <!-- 版本号 -->
  </Info>
  ...
</Slave>

SyncManager 与 PDO 映射

<ProcessData>
  <!-- SM2: 输出 (主站 -> 从站) -->
  <Sm2>
    <Type>Outputs</Type>
    <DefaultSize>9</DefaultSize>         <!-- 9 字节 = 72 bit -->
    <StartAddress>5120</StartAddress>   <!-- 0x1400 -->
    <ControlByte>100</ControlByte>
    <Enable>1</Enable>
    <Pdo>5632</Pdo>                     <!-- 0x1600 (RxPDO) -->
  </Sm2>

  <!-- SM3: 输入 (从站 -> 主站) -->
  <Sm3>
    <Type>Inputs</Type>
    <DefaultSize>23</DefaultSize>        <!-- 23 字节 = 184 bit -->
    <StartAddress>5632</StartAddress>   <!-- 0x1600 -->
    <ControlByte>32</ControlByte>
    <Enable>1</Enable>
    <Pdo>6656</Pdo>                     <!-- 0x1A00 (TxPDO) -->
  </Sm3>

  <!-- TxPDO: 从站反馈数据 -->
  <TxPdo Sm="3">
    <Index>#x1a00</Index>
    <Name>Transmit PDO mapping 1</Name>
    <Entry>
      <Index>#x603f</Index><SubIndex>0</SubIndex>
      <BitLen>16</BitLen>
      <Name>Error code</Name>
    </Entry>
    <Entry>
      <Index>#x6041</Index><SubIndex>0</SubIndex>
      <BitLen>16</BitLen>
      <Name>Statusword</Name>
    </Entry>
    <Entry>
      <Index>#x6064</Index><SubIndex>0</SubIndex>
      <BitLen>32</BitLen>
      <Name>Position actual value</Name>
    </Entry>
  </TxPdo>

  <!-- RxPDO: 主站控制数据 -->
  <RxPdo Sm="2">
    <Index>#x1600</Index>
    <Name>Receive PDO mapping 1</Name>
    <Entry>
      <Index>#x6040</Index><SubIndex>0</SubIndex>
      <BitLen>16</BitLen>
      <Name>Controlword</Name>
    </Entry>
    <Entry>
      <Index>#x607a</Index><SubIndex>0</SubIndex>
      <BitLen>32</BitLen>
      <Name>Target position</Name>
    </Entry>
  </RxPdo>
</ProcessData>

CoE 邮箱初始化命令 (PDO 下载)

ENI XML 的 <Mailbox> 节点内包含 CoE 初始化命令序列,用于在 PREOP 到 SAFEOP 转换期间配置从站 PDO 映射:

<Mailbox DataLinkLayer="true">
  <Protocol>CoE</Protocol>
  <CoE>
    <InitCmds>
      <!-- Step 1: 清空 TxPDO 0x1A00 的所有条目 -->
      <InitCmd Fixed="true">
        <Transition>PS</Transition>
        <Comment><![CDATA[clear pdo 0x1A00 entries]]></Comment>
        <Index>6656</Index>  <!-- 0x1A00 -->
        <SubIndex>0</SubIndex>
        <Data>00</Data>
      </InitCmd>

      <!-- Step 2: 逐个下载 PDO Entry -->
      <InitCmd Fixed="true">
        <Transition>PS</Transition>
        <Comment><![CDATA[download pdo 0x1A00 entry]]></Comment>
        <Index>6656</Index>
        <SubIndex>1</SubIndex>
        <Data>10003f60</Data>  <!-- BitLen=16, Index=0x603F -->
      </InitCmd>
      ...

      <!-- Step 3: 设置 PDO 条目数量 -->
      <InitCmd Fixed="true">
        <Transition>PS</Transition>
        <Comment><![CDATA[download pdo 0x1A00 entry count]]></Comment>
        <Index>6656</Index>
        <SubIndex>0</SubIndex>
        <Data>08</Data>  <!-- 8 个条目 -->
      </InitCmd>

      <!-- Step 4: 设置 SM PDO 分配 (0x1C12/0x1C13) -->
      <InitCmd Fixed="true">
        <Transition>PS</Transition>
        <Comment><![CDATA[download pdo 0x1C12:01 index]]></Comment>
        <Index>7186</Index>  <!-- 0x1C12: RxPDO 分配 -->
        <SubIndex>1</SubIndex>
        <Data>0016</Data>  <!-- 指向 0x1600 -->
      </InitCmd>
    </InitCmds>
  </CoE>
</Mailbox>

过程映像 (ProcessImage)

<ProcessImage> 描述了主站侧完整的输入/输出数据布局,包含每个变量的名称、数据类型、位宽和在过程映像中的位偏移:

<ProcessImage>
  <Inputs>
    <ByteSize>1536</ByteSize>
    <Variable>
      <Name>Drive 1 (MBDLN25BE).Transmit PDO mapping 1.Statusword</Name>
      <DataType>UINT</DataType>
      <BitSize>16</BitSize>
      <BitOffs>328</BitOffs>
    </Variable>
    <Variable>
      <Name>Drive 1 (MBDLN25BE).Transmit PDO mapping 1.Position actual value</Name>
      <DataType>DINT</DataType>
      <BitSize>32</BitSize>
      <BitOffs>352</BitOffs>
    </Variable>
  </Inputs>
  <Outputs>
    <ByteSize>1536</ByteSize>
    <Variable>
      <Name>Drive 1 (MBDLN25BE).Receive PDO mapping 1.Controlword</Name>
      <DataType>UINT</DataType>
      <BitSize>16</BitSize>
      <BitOffs>312</BitOffs>
    </Variable>
  </Outputs>
</ProcessImage>

ENI XML 的生成

ENI XML 文件通常由以下工具生成:

工具命令/方式说明
TwinCAT 工程导出 Beckhoff TwinCAT 工程工具可导出完整的 ENI XML 文件,包含所有配置细节和初始化命令
IgH ethercat 命令行工具 ethercat xml 基于当前在线从站的 EEPROM 信息生成 XML 描述,仅包含从站基本信息和默认 PDO 映射
第三方配置工具 各种 如 acontis EC-Engineer、KPA EtherCAT Studio 等支持导出 ENI XML 格式

ethercat xml 的局限

ethercat xml 命令从在线从站的 SII/EEPROM 生成 XML,但它不包含主站级别的初始化命令序列(如 SM/FMMU 配置写入、状态转换命令)。完整的 ENI XML(如 TwinCAT 导出的)包含 <InitCmds> 中的所有底层 EtherCAT 命令,可以直接用于控制从站的完整启动流程。

在 IgH 中加载 ENI XML

IgH EtherCAT Master 本身不直接加载 ENI XML 文件进行配置。标准方式是通过 ecrt API 在应用程序中动态配置。本项目提供了 ENI XML 解析库来实现从 ENI 文件到 IgH API 调用的转换。

方式一:ecrt API 动态配置 (IgH 原生)

/* 标准的 IgH API 配置方式 */
ec_slave_config_t *sc = ecrt_master_slave_config(
    master, 0x0000, 0x0000, vendor_id, product_code);

/* 配置 Sync Manager */
ecrt_slave_config_sync_manager(sc, 2, EC_DIR_OUTPUT, EC_WD_DEFAULT);
ecrt_slave_config_sync_manager(sc, 3, EC_DIR_INPUT, EC_WD_DEFAULT);

/* 配置 PDO 映射 */
ecrt_slave_config_pdos(sc, EC_END, 2, slave_syncs);

/* 配置 DC */
ecrt_slave_config_dc(sc, 0x0300, cycle_ns, 0, 0);

/* 注册 PDO Entry 到 Domain */
unsigned int offset = ecrt_slave_config_reg_pdo_entry(
    sc, 0x6040, 0, domain1, 0);

方式二:ENI XML 加载 (本项目提供)

/* 加载 ENI XML 文件 */
ecat_eni *eni = ecat_load_eni("pansonic-a6b-eni-1-axis.xml");
if (!eni) {
    fprintf(stderr, "Failed to load ENI XML\n");
    return -1;
}

/* 获取周期时间 */
uint32_t cycle_time = ecat_eni_get_cycletime(&eni->config);

/* 遍历从站配置 */
for (auto *slave : eni->config.slave_list) {
    /* 从 eni_config_slave 提取配置信息:
     *   slave->info          — 从站标识 (VendorId, ProductCode)
     *   slave->processdata   — SM 配置, PDO 映射 (TxPDO/RxPDO + Entry)
     *   slave->mailbox       — 邮箱配置, CoE 初始化命令
     *   slave->initcmds      — 底层初始化命令序列
     *   slave->dc            — DC 同步配置
     */
    ...
}

/* 使用完毕后释放 */
eni_config_free(eni);

XML 元素与 ecrt API 对照表

下表展示 ENI XML 元素到 IgH ecrt API 调用的对应关系:

ENI XML 元素/属性对应 ecrt API说明
<Slave> VendorId/ProductCode ecrt_master_slave_config() 根据厂商标识创建从站配置
<Sm2>/<Sm3> Type + ControlByte ecrt_slave_config_sync_manager() 配置 SyncManager 方向和看门狗
<TxPdo>/<RxPdo> + <Entry> ecrt_slave_config_pdos() 配置 PDO 映射表
<Entry> Index/SubIndex/BitLen ecrt_slave_config_reg_pdo_entry() 注册 PDO 条目到 Domain
<Dc> AssignActivate/CycleTime ecrt_slave_config_dc() 配置分布式时钟同步参数
<InitCmd> (CoE SDO 下载) ecrt_slave_config_complete_sdo() 配置 SDO 初始下载命令
<InitCmd> (寄存器写入) 无直接 API IgH 通过内部 FSM 处理 SM/FMMU 寄存器配置
<ProcessImage> Variable ecrt_domain_reg_pdo_entry_list() Domain 过程映像注册
<Cyclic> CycleTime ecrt_master_application_time() 设置应用周期时间
<Sm> Watchdog ecrt_slave_config_watchdog() 配置 SM 看门狗参数

源码分析

ENI XML 解析流程 (本项目)

本项目在 examples/eni_dc_demo/ecat/eniconfig/ 目录下提供了完整的 ENI XML 解析库。该库基于 libxml2 实现,将 ENI XML 文件解析为 C++ 结构体,供上层应用使用。

解析入口

核心入口函数 ecat_load_eni()(位于 eniconfig.cpp)执行以下流程:

[流程图 - 结构化描述]

步骤描述
1 ecat_load_eni(filename)
2 xmlParseFile() — libxml2 解析
3 xmlDocGetRootElement() — 获取根节点
4 根节点 == EtherCATConfig?
5 返回 NULL (解析失败)
6 遍历子节点找 Config
7 ecat_eni_parse_config()
8 解析 Master
9 解析 Slave (可多个)
10 解析 Cyclic
11 解析 ProcessImage
12 ecat_eni_parse_slaveconfig()
13 解析 Slave/Info — 从站标识
14 解析 ProcessData — SM + PDO
15 解析 Mailbox/CoE — 邮箱初始化
16 解析 InitCmds — 底层命令
17 解析 DC — 分布式时钟

关键数据结构

结构体文件说明
ecat_eni eniconfig.h 顶层结构,包含一个 eni_config 成员
eni_config eniconfig.h 包含 master、slave_list、cyclic、processimage 四大块
eni_config_slave enislave.h 从站配置:info、processdata、mailbox、initcmds、dc
eni_config_master enimaster.h 主站信息:states、eoe、initcmds
eni_config_cyclic enicyclic.h 循环任务:cycle_time、frame 及其中的 cmd 列表
eni_config_processimage eniprocessimage.h 过程映像:inputs/outputs 变量列表

解析代码摘要

eniconfig.cpp 中的解析逻辑:

ecat_eni* ecat_load_eni(const char* name)
{
    xmlDocPtr doc;
    xmlNodePtr cur;

    doc = xmlParseFile(name);       // 1. libxml2 解析 XML 文件
    cur = xmlDocGetRootElement(doc);

    // 2. 验证根节点为 EtherCATConfig
    if ((xmlStrcmp(cur->name, BAD_CAST "EtherCATConfig")))
        goto FAILED;

    eni = new ecat_eni;
    cur = cur->xmlChildrenNode;

    // 3. 遍历 Config 节点
    while (cur != NULL) {
        if ((!xmlStrcmp(cur->name, BAD_CAST "Config"))) {
            xmlNodePtr nodePtr = cur->xmlChildrenNode;
            ecat_eni_parse_config(nodePtr, &eni->config);
        }
        cur = cur->next;
    }
    return eni;
}

// 4. Config 内部解析:分发到 Master/Slave/Cyclic/ProcessImage
static void ecat_eni_parse_config(xmlNodePtr ptr, eni_config* config)
{
    while (ptr != NULL) {
        if ((!xmlStrcmp(ptr->name, BAD_CAST "Master")))
            ecat_eni_parse_masterconfig(nodePtr, &config->master);
        if ((!xmlStrcmp(ptr->name, BAD_CAST "Slave")))
            ecat_eni_parse_slaveconfig(nodePtr, &config->slave_list);
        if ((!xmlStrcmp(ptr->name, BAD_CAST "Cyclic")))
            ecat_eni_parse_cyclic(nodePtr, config->cyclic);
        if ((!xmlStrcmp(ptr->name, BAD_CAST "ProcessImage")))
            ecat_eni_parse_processimage(nodePtr, config->processimage);
        ptr = ptr->next;
    }
}

IgH 主站模块中的 ENI 处理

IgH EtherCAT Master 1.5.2 内核模块本身不直接处理 ENI XML 文件。IgH 采用的是"应用层配置 + 内核模块执行"的架构:

  • 用户态应用通过字符设备 (/dev/EtherCAT*) 与内核主站模块通信
  • ecrt API 封装为 ioctl 系统调用,传递配置参数到内核空间
  • 内核模块收到配置后通过 FSM 状态机执行实际的从站配置流程

这意味着 ENI XML 的解析完全在用户态完成。本项目的解析库将 ENI XML 转换为结构化数据后,应用代码再调用对应的 ecrt API 完成配置。

ENI 配置方式 vs API 配置方式 对比

对比维度API 配置 (ecrt)ENI 配置 (XML)
配置位置 应用程序源码中硬编码 外部 XML 文件
灵活性 高,可在运行时动态调整 低,需要重新生成 XML
初始化命令 IgH 内部 FSM 自动处理 XML 中显式定义全部命令序列
FMMU/SM 配置 IgH 根据 PDO 配置自动计算 XML 中通过 InitCmd 显式指定
多工具兼容性 IgH 专用 跨工具通用 (TwinCAT/acontis/KPA)
DC 配置 ecrt_slave_config_dc() XML <Dc> 节点,含完整参数
适用场景 IgH 原生开发,灵活快速迭代 从 TwinCAT 迁移、需要精确控制初始化流程
调试复杂度 低,IgH 处理大部分细节 高,需要理解 ENI XML 中每条命令的含义

实践建议

对于大多数 IgH 开发场景,推荐使用 API 配置方式(ecrt API),因为它更简洁、IgH 自动处理底层细节(SM/FMMU 配置、状态转换命令等)。

当需要从 TwinCAT 工程迁移配置,或者需要精确控制从站的每一步初始化过程(例如特定的 SDO 下载顺序、自定义邮箱初始化序列)时,使用 ENI 配置方式更为合适。本项目的 eni_dc_demo 示例展示了完整的 ENI 加载和使用流程。

posted @ 2026-04-15 08:10  沐多  阅读(465)  评论(0)    收藏  举报