EtherCAT主站IGH-- 4 -- IGH之datagram_pair.h/c文件解析

EtherCAT主站IGH-- 4 -- IGH之datagram_pair.h/c文件解析

  • 0 预览
  • 一 该文件功能
    • `datagram_pair.c` 文件功能函数预览
  • 二 函数功能介绍
    • `datagram_pair.c` 中主要函数的作用
        • 1. `ec_datagram_pair_init`
        • 2. `ec_datagram_pair_clear`
        • 3. `ec_datagram_pair_process`
  • 三 h文件翻译
  • 四 c文件翻译
  • 该文档修改记录:
  • 总结

0 预览

一 该文件功能

该文件定义了 EtherCAT 数据报对的方法。EtherCAT 是一种实时以太网通信标准,广泛用于工业自动化控制系统。数据报对用于在 EtherCAT 主站和从站之间传输数据的成对数据报。文件中包含的数据报对方法涵盖了初始化、清理和处理接收到的数据等操作。

datagram_pair.c 文件功能函数预览

函数功能和用途使用场景
ec_datagram_pair_init初始化 EtherCAT 数据报对。在创建新的数据报对时调用。
ec_datagram_pair_clear清理 EtherCAT 数据报对。在数据报对不再使用时调用以释放资源。
ec_datagram_pair_process处理接收到的数据,计算工作计数总和。在需要处理接收到的数据并计算工作计数时调用。

二 函数功能介绍

datagram_pair.c 中主要函数的作用

1. ec_datagram_pair_init
int ec_datagram_pair_init(
        ec_datagram_pair_t *pair, /**< Datagram pair. */
        ec_domain_t *domain, /**< Parent domain. */
        uint32_t logical_offset, /**< Logical offset. */
        uint8_t *data, /**< Data pointer. */
        size_t data_size, /**< Data size. */
        const unsigned int used[] /**< input/output use count. */
        )
{
    ec_device_index_t dev_idx;
    int ret;

    INIT_LIST_HEAD(&pair->list);
    pair->domain = domain;

    for (dev_idx = EC_DEVICE_MAIN;
            dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
        ec_datagram_init(&pair->datagrams[dev_idx]);
        snprintf(pair->datagrams[dev_idx].name,
                EC_DATAGRAM_NAME_SIZE, "domain%u-%u-%s", domain->index,
                logical_offset, ec_device_names[dev_idx != 0]);
        pair->datagrams[dev_idx].device_index = dev_idx;
    }

    pair->expected_working_counter = 0U;

    for (dev_idx = EC_DEVICE_BACKUP;
            dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
        /* backup datagrams have their own memory */
        ret = ec_datagram_prealloc(&pair->datagrams[dev_idx], data_size);
        if (ret) {
            goto out_datagrams;
        }
    }

#if EC_MAX_NUM_DEVICES > 1
    if (!(pair->send_buffer = kmalloc(data_size, GFP_KERNEL))) {
        EC_MASTER_ERR(domain->master,
                "Failed to allocate domain send buffer!\n");
        ret = -ENOMEM;
        goto out_datagrams;
    }
#endif

    /* The ec_datagram_lxx() calls below can not fail, because either the
     * datagram has external memory or it is preallocated. */

    if (used[EC_DIR_OUTPUT] && used[EC_DIR_INPUT]) { // inputs and outputs
        ec_datagram_lrw_ext(&pair->datagrams[EC_DEVICE_MAIN],
                logical_offset, data_size, data);

        for (dev_idx = EC_DEVICE_BACKUP;
                dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
            ec_datagram_lrw(&pair->datagrams[dev_idx],
                    logical_offset, data_size);
        }

        // If LRW is used, output FMMUs increment the working counter by 2,
        // while input FMMUs increment it by 1.
        pair->expected_working_counter =
            used[EC_DIR_OUTPUT] * 2 + used[EC_DIR_INPUT];
    } else if (used[EC_DIR_OUTPUT]) { // outputs only
        ec_datagram_lwr_ext(&pair->datagrams[EC_DEVICE_MAIN],
                logical_offset, data_size, data);
        for (dev_idx = EC_DEVICE_BACKUP;
                dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
            ec_datagram_lwr(&pair->datagrams[dev_idx],
                    logical_offset, data_size);
        }

        pair->expected_working_counter = used[EC_DIR_OUTPUT];
    } else { // inputs only (or nothing)
        ec_datagram_lrd_ext(&pair->datagrams[EC_DEVICE_MAIN],
                logical_offset, data_size, data);
        for (dev_idx = EC_DEVICE_BACKUP;
                dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
            ec_datagram_lrd(&pair->datagrams[dev_idx], logical_offset,
                    data_size);
        }

        pair->expected_working_counter = used[EC_DIR_INPUT];
    }

    for (dev_idx = EC_DEVICE_MAIN;
            dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
        ec_datagram_zero(&pair->datagrams[dev_idx]);
    }

    return 0;

out_datagrams:
    for (dev_idx = EC_DEVICE_MAIN;
            dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
        ec_datagram_clear(&pair->datagrams[dev_idx]);
    }

    return ret;
}
  • 功能和用途:初始化 EtherCAT 数据报对。
  • 使用场景:在创建新的数据报对时调用。
2. ec_datagram_pair_clear
void ec_datagram_pair_clear(
        ec_datagram_pair_t *pair /**< Datagram pair. */
        )
{
    unsigned int dev_idx;

    for (dev_idx = EC_DEVICE_MAIN;
            dev_idx < ec_master_num_devices(pair->domain->master);
            dev_idx++) {
        ec_datagram_clear(&pair->datagrams[dev_idx]);
    }

#if EC_MAX_NUM_DEVICES > 1
    if (pair->send_buffer) {
        kfree(pair->send_buffer);
    }
#endif
}
  • 功能和用途:清理 EtherCAT 数据报对。
  • 使用场景:在数据报对不再使用时调用以释放资源。
3. ec_datagram_pair_process
uint16_t ec_datagram_pair_process(
        ec_datagram_pair_t *pair, /**< Datagram pair. */
        uint16_t wc_sum[] /**< Working counter sums. */
        )
{
    unsigned int dev_idx;
    uint16_t pair_wc = 0;

    for (dev_idx = 0; dev_idx < ec_master_num_devices(pair->domain->master);
            dev_idx++) {
        ec_datagram_t *datagram = &pair->datagrams[dev_idx];

#ifdef EC_RT_SYSLOG
        ec_datagram_output_stats(datagram);
#endif

        if (datagram->state == EC_DATAGRAM_RECEIVED) {
            pair_wc += datagram->working_counter;
            wc_sum[dev_idx] += datagram->working_counter;
        }
    }

    return pair_wc;
}
  • 功能和用途:处理接收到的数据,计算工作计数总和。
  • 使用场景:在需要处理接收到的数据并计算工作计数时调用。

三 h文件翻译

/******************************************************************************\
 *
 *  $Id$
 *
 *  版权所有 (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
 *
 *  本文件是 IgH EtherCAT 主站的一部分。
 *
 *  IgH EtherCAT 主站是免费软件;您可以根据自由软件基金会发布的 GNU 通用公共许可证第2版的条款重新分发和/或修改它。
 *
 *  IgH EtherCAT 主站的分发目的是希望它有用,但没有任何保证;甚至没有适销性或特定用途适用性的隐含保证。详情请参阅 GNU 通用公共许可证。
 *
 *  您应该已经收到了与 IgH EtherCAT 主站一起提供的 GNU 通用公共许可证的副本;如果没有,请写信给自由软件基金会,地址是:51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA。
 *
 *  ---
 *
 *  上述许可证仅适用于源代码。使用 EtherCAT 技术和品牌仅允许在遵守 Beckhoff Automation GmbH 的工业产权和类似权利的情况下使用。
 *****************************************************************************/

/**
   \file
   EtherCAT 数据报对结构。
*/

/*****************************************************************************/

#ifndef __EC_DATAGRAM_PAIR_H__
#define __EC_DATAGRAM_PAIR_H__

#include <linux/list.h>

#include "globals.h"
#include "datagram.h"

/*****************************************************************************/

/** 域数据报对。
 */
typedef struct {
    struct list_head list; /**< 链表头。 */
    ec_domain_t *domain; /**< 父域。 */
    ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]; /**< 数据报。 */
#if EC_MAX_NUM_DEVICES > 1
    uint8_t *send_buffer;
#endif
    unsigned int expected_working_counter; /**< 期望的工作计数器。 */
} ec_datagram_pair_t;

/*****************************************************************************/

int ec_datagram_pair_init(ec_datagram_pair_t *pair, ec_domain_t *domain,
        uint32_t logical_offset, uint8_t *data, size_t data_size,
        const unsigned int used[]);
void ec_datagram_pair_clear(ec_datagram_pair_t *pair);
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *pair,
        uint16_t wc_sum[]);

/*****************************************************************************/

#endif

四 c文件翻译

/******************************************************************************\
 *
 *  $Id$
 *
 *  版权所有 (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH
 *
 *  本文件是 IgH EtherCAT 主站的一部分。
 *
 *  IgH EtherCAT 主站是免费软件;您可以根据自由软件基金会发布的 GNU 通用公共许可证第2版的条款重新分发和/或修改它。
 *
 *  IgH EtherCAT 主站的分发目的是希望它有用,但没有任何保证;甚至没有适销性或特定用途适用性的隐含保证。详情请参阅 GNU 通用公共许可证。
 *
 *  您应该已经收到了与 IgH EtherCAT 主站一起提供的 GNU 通用公共许可证的副本;如果没有,请写信给自由软件基金会,地址是:51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA。
 *
 *  ---
 *
 *  上述许可证仅适用于源代码。使用 EtherCAT 技术和品牌仅允许在遵守 Beckhoff Automation GmbH 的工业产权和类似权利的情况下使用。
 *****************************************************************************/

/**
   \file
   EtherCAT 数据报对的方法。
*/

/*****************************************************************************/

#include <linux/slab.h>

#include "master.h"
#include "datagram_pair.h"

/*****************************************************************************/

/** 数据报对构造函数。
 *
 * \return 成功时返回零,否则返回负错误代码。
 */
int ec_datagram_pair_init(
        ec_datagram_pair_t *pair, /**< 数据报对。 */
        ec_domain_t *domain, /**< 父域。 */
        uint32_t logical_offset, /**< 逻辑偏移。 */
        uint8_t *data, /**< 数据指针。 */
        size_t data_size, /**< 数据大小。 */
        const unsigned int used[] /**< 输入/输出使用计数。 */
        )
{
    ec_device_index_t dev_idx;
    int ret;

    INIT_LIST_HEAD(&pair->list);
    pair->domain = domain;

    for (dev_idx = EC_DEVICE_MAIN;
            dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
        ec_datagram_init(&pair->datagrams[dev_idx]);
        snprintf(pair->datagrams[dev_idx].name,
                EC_DATAGRAM_NAME_SIZE, "domain%u-%u-%s", domain->index,
                logical_offset, ec_device_names[dev_idx != 0]);
        pair->datagrams[dev_idx].device_index = dev_idx;
    }

    pair->expected_working_counter = 0U;

    for (dev_idx = EC_DEVICE_BACKUP;
            dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
        /* 备份数据报有自己的内存 */
        ret = ec_datagram_prealloc(&pair->datagrams[dev_idx], data_size);
        if (ret) {
            goto out_datagrams;
        }
    }

#if EC_MAX_NUM_DEVICES > 1
    if (!(pair->send_buffer = kmalloc(data_size, GFP_KERNEL))) {
        EC_MASTER_ERR(domain->master,
                "分配域发送缓冲区失败!\n");
        ret = -ENOMEM;
        goto out_datagrams;
    }
#endif

    /* 下面的 ec_datagram_lxx() 调用不会失败,因为数据报有外部内存或已预分配。 */

    if (used[EC_DIR_OUTPUT] && used[EC_DIR_INPUT]) { // 输入和输出
        ec_datagram_lrw_ext(&pair->datagrams[EC_DEVICE_MAIN],
                logical_offset, data_size, data);

        for (dev_idx = EC_DEVICE_BACKUP;
                dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
            ec_datagram_lrw(&pair->datagrams[dev_idx],
                    logical_offset, data_size);
        }

        // 如果使用 LRW,则输出 FMMU 将工作计数器增加 2,
        // 而输入 FMMU 将其增加 1。
        pair->expected_working_counter =
            used[EC_DIR_OUTPUT] * 2 + used[EC_DIR_INPUT];
    } else if (used[EC_DIR_OUTPUT]) { // 仅输出
        ec_datagram_lwr_ext(&pair->datagrams[EC_DEVICE_MAIN],
                logical_offset, data_size, data);
        for (dev_idx = EC_DEVICE_BACKUP;
                dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
            ec_datagram_lwr(&pair->datagrams[dev_idx],
                    logical_offset, data_size);
        }

        pair->expected_working_counter = used[EC_DIR_OUTPUT];
    } else { // 仅输入(或没有)
        ec_datagram_lrd_ext(&pair->datagrams[EC_DEVICE_MAIN],
                logical_offset, data_size, data);
        for (dev_idx = EC_DEVICE_BACKUP;
                dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
            ec_datagram_lrd(&pair->datagrams[dev_idx], logical_offset,
                    data_size);
        }

        pair->expected_working_counter = used[EC_DIR_INPUT];
    }

    for (dev_idx = EC_DEVICE_MAIN;
            dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
        ec_datagram_zero(&pair->datagrams[dev_idx]);
    }

    return 0;

out_datagrams:
    for (dev_idx = EC_DEVICE_MAIN;
            dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
        ec_datagram_clear(&pair->datagrams[dev_idx]);
    }

    return ret;
}

/*****************************************************************************/

/** 数据报对析构函数。
 */
void ec_datagram_pair_clear(
        ec_datagram_pair_t *pair /**< 数据报对。 */
        )
{
    unsigned int dev_idx;

    for (dev_idx = EC_DEVICE_MAIN;
            dev_idx < ec_master_num_devices(pair->domain->master);
            dev_idx++) {
        ec_datagram_clear(&pair->datagrams[dev_idx]);
    }

#if EC_MAX_NUM_DEVICES > 1
    if (pair->send_buffer) {
        kfree(pair->send_buffer);
    }
#endif
}

/*****************************************************************************/

/** 处理接收的数据。
 *
 * \return 所有设备的工作计数器总和。
 */
uint16_t ec_datagram_pair_process(
        ec_datagram_pair_t *pair, /**< 数据报对。 */
        uint16_t wc_sum[] /**< 工作计数器总和。 */
        )
{
    unsigned int dev_idx;
    uint16_t pair_wc = 0;

    for (dev_idx = 0; dev_idx < ec_master_num_devices(pair->domain->master);
            dev_idx++) {
        ec_datagram_t *datagram = &pair->datagrams[dev_idx];

#ifdef EC_RT_SYSLOG
        ec_datagram_output_stats(datagram);
#endif

        if (datagram->state == EC_DATAGRAM_RECEIVED) {
            pair_wc += datagram->working_counter;
            wc_sum[dev_idx] += datagram->working_counter;
        }
    }

    return pair_wc;
}

/*****************************************************************************/


该文档修改记录:

修改时间修改说明
2024年7月1日EtherCAT主站IGH 该 文件解析

总结

以上就是EtherCAT主站IGH文件解析的内容。
有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。
创作不容,如果文档对您有帮助,记得给个赞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/762548.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【创建者模式-建造者模式】

概要 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 建造者模式包含以下角色 抽象建造者类&#xff08;Builder&#xff09;&#xff1a;这个接口规定要实现复杂对象的那些部分的创建&#xff0c;并不涉及具体的部件对象的创建。具体建…

使用explain优化慢查询的业务场景分析

问&#xff1a;你最害怕的事情是什么&#xff1f;答&#xff1a;搓澡问&#xff1a;为什么&#xff1f;答&#xff1a;因为有些人一旦错过&#xff0c;就不在了 Explain 这个词在不同的上下文中有不同的含义。在数据库查询优化的上下文中&#xff0c;“EXPLAIN” 是一个常用的 …

基于PHP的初中数学题库管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的初中数学题库管理系统 一 介绍 此初中数学题库管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;系统角色分为学生&#xff0c;教师和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqlphpstudyvscode 二 功能 …

YOLOv10改进教程|C2f-CIB加入注意力机制

一、 导读 论文链接&#xff1a;https://arxiv.org/abs/2311.11587 代码链接&#xff1a;GitHub - CV-ZhangXin/AKConv YOLOv10训练、验证及推理教程 二、 C2f-CIB加入注意力机制 2.1 复制代码 打开ultralytics->nn->modules->block.py文件&#xff0c;复制SE注意力机…

Android 大话binder通信

戳蓝字“牛晓伟”关注我哦&#xff01; 用心坚持输出易读、有趣、有深度、高质量、体系化的技术文章 由于 Android 大话binder通信(上) 和 Android 大话binder通信(下) 分为两篇阅读体验不好&#xff0c;顾合并为一篇。 本文摘要 用故事的方式把binder通信的整个过程都描述…

分享一个在 WinForm 桌面程序中使用进度条展示报表处理进度的例子,提升用户体验

前言 在有些比较消耗时间的业务场景中&#xff0c;比如生成报表等&#xff0c;如果没有在操作的过程中向用户反馈操作进度&#xff0c;会让用户以为程序 “死” 掉了&#xff0c;用户体验非常不好。 WinForm 桌面程序项目与 Console 项目不一样&#xff0c;如果 Console 项目…

C++ initializer_list类型推导

目录 initializer_list C自动类型推断 auto typeid decltype initializer_list<T> C支持统一初始化{ }&#xff0c;出现了一个新的类型initializer_list<T>&#xff0c;一切类型都可以用列表初始化。提供了一种更加灵活、安全和明确的方式来初始化对象。 class…

MIT6.s081 2021 Lab Page tables

Speed up system calls 思路 题目要求在每个进程初始化时为它的页表插入一个页表项&#xff0c;内核通过这样预先缓存页表项的操作&#xff0c;来加速特定系统调用的执行速度。 由于前不久刚过完一遍《OSTEP》&#xff0c;因此我认为自己对页表机制还算比较熟悉&#xff0c;…

Open AI Stream Completion Set Variable Inside Function PHP With Openai-php SDK

题意&#xff1a;使用 OpenAI 的 PHP SDK&#xff08;例如 openai-php&#xff09;来在函数内部设置和完成一个流&#xff08;stream&#xff09;相关的变量 问题背景&#xff1a; How to set variable inside this openai-php sdk function in stream completion ? I am usi…

【笔记】手工部署之linux中开放已安装的mysql与tomcat端口

在需要打包的springboot项目中输入mvn clean package 在target下面获得jar包 进入linux中你想要该jar包存在的位置 将jar包上传至linux中 此时在浏览器中输入linux的ip地址&#xff1a;端口号/mapping路径为404 故&#xff1a; 在linux中另开一个标签页 检查mysql和tomcat已…

JavaFX布局-BorderPane

JavaFX布局-BorderPane 实现方式Java实现FXML实现 综合案例 将容器空间分成五个区域&#xff1a;顶部&#xff08;Top&#xff09;、底部&#xff08;Bottom&#xff09;、左侧&#xff08;Left&#xff09;、右侧&#xff08;Right&#xff09;和中心&#xff08;Center&#…

Java案例找素数(三种方法)

目录 一&#xff1a;问题&#xff1a; 二&#xff1a;思路分析&#xff1a; 三&#xff1a;具体代码&#xff1a; 四&#xff1a;运行结果&#xff1a; 一&#xff1a;问题&#xff1a; 二&#xff1a;思路分析&#xff1a; 三&#xff1a;具体代码&#xff1a; Ⅰ&#xf…

03 _ 类型基础(2):动态类型与静态类型

静态类型语言与动态类型语言 通俗定义 静态类型语言&#xff1a;在编译 阶段确定所有变量的类型 动态类型语言&#xff1a;在执行阶段确定所有变量的类型 Javascript 与 C 对比 静态类型与动态类型对比 其他定义 强类型语言&#xff1a;不允许程序在发生错误后继续执行 语…

【STM32】温湿度采集与OLED显示

一、任务要求 1. 学习I2C总线通信协议&#xff0c;使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集&#xff0c;并将采集的温度-湿度值通过串口输出。 任务要求&#xff1a; 1&#xff09;解释什么是“软件I2C”和“硬件I2C”&#xff1f;&#xff08;阅读野火配…

视频号视频怎么下载保存到手机,视频号视频如何下载到电脑本地

在数字化浪潮的推动下&#xff0c;视频号成为了我们获取信息、分享生活的重要平台。但有时候&#xff0c;我们遇到一些精彩的内容&#xff0c;想要保存下来以便日后观看&#xff0c;却发现视频号并不提供直接的下载功能。下面我就来为大家详细介绍视频号视频下载的方法&#xf…

Datax快速使用之牛刀小试

前言 一次我发现业务他们在用 datax数据同步工具&#xff0c;我尤记得曾经 19 年使用过&#xff0c;并且基于当时的版本还修复了个 BUG并且做了数据同步管道的集成开发。没想到时间过的飞快&#xff0c;业务方基于海豚调度 2.0.6 的版本中有在使用&#xff0c;由于业务方还没有…

大促前夕即高点,综合电商平台的“稀缺”魔法正在消失?

新一期618大促早已结束良久了&#xff0c;但似乎其产生的余韵却仍旧未消散。 从最直观的资本市场走势来看&#xff0c;自这一波618大促陆续开展之后&#xff0c;包括京东、阿里巴巴、拼多多等港美股股价就一改此前的上行态势&#xff0c;持续下滑至今。 事实上&#xff0c;早…

【计算机网络期末复习】例题汇总(一)

重点例题选择填空简答题与传输媒体的接口的特性重点 计算机网络的性能指标计算机网络体系结构例题 选择

【Linux】线程id与互斥(线程三)

上一期我们进行了线程控制的了解与相关操作&#xff0c;但是仍旧有一些问题没有解决 本章第一阶段就是解决tid的问题&#xff0c;第二阶段是进行模拟一个简易线程库&#xff08;为了加深对于C库封装linux原生线程的理解&#xff09;&#xff0c;第三阶段就是互斥。 目录 线程id…