EtherCAT主站IGH-- 4 -- IGH之datagram_pair.h/c文件解析
- [0 预览](#0 预览)
- [一 该文件功能](#一 该文件功能)
-
- [`datagram_pair.c` 文件功能函数预览](#
datagram_pair.c
文件功能函数预览)
- [`datagram_pair.c` 文件功能函数预览](#
- [二 函数功能介绍](#二 函数功能介绍)
-
- [`datagram_pair.c` 中主要函数的作用](#
datagram_pair.c
中主要函数的作用) -
-
- [1. `ec_datagram_pair_init`](#1.
ec_datagram_pair_init
) - [2. `ec_datagram_pair_clear`](#2.
ec_datagram_pair_clear
) - [3. `ec_datagram_pair_process`](#3.
ec_datagram_pair_process
)
- [1. `ec_datagram_pair_init`](#1.
-
- [`datagram_pair.c` 中主要函数的作用](#
- [三 h文件翻译](#三 h文件翻译)
- [四 c文件翻译](#四 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
c
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
c
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
c
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文件翻译
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 数据报对结构。
*/
/*****************************************************************************/
#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文件翻译
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文件解析的内容。
有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。
创作不容,如果文档对您有帮助,记得给个赞。