SOEM源码解析——ec_init(初始化单网卡主站)

news2024/12/25 17:16:27

0 工具准备

1.SOEM-master-1.4.0源码

1 ec_init总览

/** Initialise lib in single NIC mode:初始化库在单网卡模式
 * @param[in] ifname   = Dev name, f.e. "eth0" 设备名
 * @return >0 if OK
 * @see ecx_init
 */
int ec_init(const char * ifname)
{
   return ecx_init(&ecx_context, ifname);
}
/** Initialise lib in single NIC mode:初始化库在单网卡模式
 * @param[in]  context = context struct SOEM句柄
 * @param[in] ifname   = Dev name, f.e. "eth0" 设备名
 * @return >0 if OK
 */
int ecx_init(ecx_contextt *context, const char * ifname)
{
   return ecx_setupnic(context->port, ifname, FALSE);
}

当我们的主站工作模式为单网卡而非冗余模式时会使用ec_init函数初始化SOEM库,ec_init函数是主站初始化时第一个执行的函数。它真正调用的是ecx_setupnic函数,该函数具体操作如下:

/** Basic setup to connect NIC to socket.
 * @param[in] port        = port context struct
 * @param[in] ifname      = Name of NIC device, f.e. "eth0"
 * @param[in] secondary   = if >0 then use secondary stack instead of primary
 * @return >0 if succeeded
 */
int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary) 
{
   int i;
   int *psock;
     
   if (secondary)
   {
      /* secondary port stuct available? */
      /* 冗余端口结构体有效? */
      if (port->redport)
      {
         /* when using secondary socket it is automatically a redundant setup */
         /* 当使用冗余套接字时,切换到冗余状态*/
         psock = &(port->redport->sockhandle);
         *psock = -1;
         port->redstate                   = ECT_RED_DOUBLE;
         port->redport->stack.sock        = &(port->redport->sockhandle);
         port->redport->stack.txbuf       = &(port->txbuf);
         port->redport->stack.txbuflength = &(port->txbuflength);
         port->redport->stack.tempbuf     = &(port->redport->tempinbuf);
         port->redport->stack.rxbuf       = &(port->redport->rxbuf);
         port->redport->stack.rxbufstat   = &(port->redport->rxbufstat);
         port->redport->stack.rxsa        = &(port->redport->rxsa);
         ecx_clear_rxbufstat(&(port->redport->rxbufstat[0]));
      }
      else
      {
         /* fail */
         return 0;
      }
   }
   else
   {
      port->sockhandle        = -1;
      port->lastidx           = 0;
      port->redstate          = ECT_RED_NONE;
      port->stack.sock        = &(port->sockhandle);
      port->stack.txbuf       = &(port->txbuf);
      port->stack.txbuflength = &(port->txbuflength);
      port->stack.tempbuf     = &(port->tempinbuf);
      port->stack.rxbuf       = &(port->rxbuf);
      port->stack.rxbufstat   = &(port->rxbufstat);
      port->stack.rxsa        = &(port->rxsa);
      ecx_clear_rxbufstat(&(port->rxbufstat[0]));
      psock = &(port->sockhandle);
   }  

   /* setup ethernet headers in tx buffers so we don't have to repeat it */
   /* 在tx buffers里设置以太网帧头,这样就不必重复设置了 */
   for (i = 0; i < EC_MAXBUF; i++)
   {
      ec_setupheader(&(port->txbuf[i]));
      port->rxbufstat[i] = EC_BUF_EMPTY;
   }
   ec_setupheader(&(port->txbuf2));

   return 1;
}

该函数的功能可以分为2块:
(1)根据传进来的secondary分别设置传入句柄的普通端口或冗余端口,当secondary为FALSE也就是0时设置普通端口,当secondary为TRUE也就是1时设置冗余端口。
(2)设置发送缓冲区的以太网帧头,在后续的报文发送中就不必重复设置了。
上面的(1)、(2)步骤中涉及到ecx_clear_rxbufstat和ec_setupheader这2个函数,下面一起来看看它们的具体工作。

2 ecx_clear_rxbufstat函数解析

/**
 * @brief 将接收缓冲区状态设置为EC_BUF_EMPTY(空)
 * @param rxbufstat 接收缓冲区状态
 */
static void ecx_clear_rxbufstat(int *rxbufstat)
{
   int i;
   for(i = 0; i < EC_MAXBUF; i++)
   {
      rxbufstat[i] = EC_BUF_EMPTY;
   }
}

该函数主要工作就是将主站接收缓冲区所有buffer的状态设置为EC_BUF_EMPTY,也就是空,初始化接收缓冲区状态到正确的状态以便于后面的正常工作。

3 ec_setupheader函数解析

/** Fill buffer with ethernet header structure. 将以太网帧头填充到buffer
 * Destination MAC is allways broadcast. 目的mac地址是广播mac地址
 * Ethertype is allways ETH_P_ECAT. 帧类型是ETH_P_ECAT(0x88A4)
 * @param[out] p = buffer
 */
void ec_setupheader(void *p) 
{
   ec_etherheadert *bp;
   bp = p;
   bp->da0 = oshw_htons(0xffff);
   bp->da1 = oshw_htons(0xffff);
   bp->da2 = oshw_htons(0xffff);
   bp->sa0 = oshw_htons(priMAC[0]);
   bp->sa1 = oshw_htons(priMAC[1]);
   bp->sa2 = oshw_htons(priMAC[2]);
   bp->etype = oshw_htons(ETH_P_ECAT);
}

前面的ecx_clear_rxbufstat函数是为了设置接收缓冲区到争取的状态,这个函数则是为了设置发送缓冲区。
我们都知道,EtherCAT报文组成框图如下:
在这里插入图片描述
其中目的地址、源地址都可以设置为固定值,SOEM主站将目的地址设置为ff:ff:ff:ff:ff:ff、源地址设置为01:01:01:01:01:01、帧类型规定为0x88A4。SOEM主站这样设置以后便不需要每次组帧时设置以太网帧头,可以提高组帧效率。
还有一个地方需要特别注意,就是oshw_htons函数,用于将主机序(小端)设置为网络序(大端)。

4 总结

(1)SOEM主站初始化以太网帧为广播帧,主站所连接的网络中所有设备都会接收到EtherCAT报文。
(2)SOEM主站支持冗余模式,设置时和单网卡主站不同。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

构建高性能嵌入式系统的技术要求

目录 关键的技术要求 硬件设计 嵌入式操作系统&#xff08;Embedded Operating System&#xff09; 内存管理 电源管理 通信接口 实时性能 软件优化 安全性 关键的技术要求 硬件设计&#xff1a; 处理器选择&#xff1a; 选择适当的处理器架构&#xff0c;考虑性能、功…

点大商城V2版 2.5.2.1 全开源独立版 多小程序端+unipp安装教程

点大商城V2是一款采用全新界面设计支持多端覆盖的小程序应用&#xff0c;支持H5、微信公众号、微信小程序、头条小程序、支付宝小程序、百度小程序&#xff0c;本程序是点大商城V2独立版&#xff0c;包含全部插件&#xff0c;代码全开源&#xff0c;并且有VUE全端代码。分销&am…

MMDetection 系列(一): 初步入门配置文件

参考文档 不得不知的 MMDetection 学习路线(个人经验版) 轻松掌握 MMDetection 整体构建流程(一) 学习配置文件 MaskRCNN 配置文件的逻辑 整体来说&#xff0c;配置文件包含以下几个部分&#xff1a; 数据集和评测器配置模型配置训练和测试的配置优化相关配置钩子配置(TODO…

Web测试与APP测试详解

前言 单纯从功能测试的层面上来讲的话&#xff0c;App 测试、Web 测试在流程和功能测试上是没有区别的&#xff0c;但由于系统结构方面存在差异&#xff08;web 项目&#xff0c;b/s 架构&#xff1b;app 项目&#xff0c;c/s 结构&#xff09;在测试中还是有不同的侧重点内容…

使用opencv和dlib库(C++代码)实现人脸活体检测(眨眼、张嘴、摇头检测)

前言 本文章使用opencv和dlib库,使用C++代码实现了人脸活体检测,包括眨眼检测、张嘴检测以及摇头检测,可以对静态图片和活体进行有效区分。效果展示 Dlib库介绍 dlib是一个开源的C++机器学习库,它提供了一系列用于图像处理、人脸检测、人脸识别、物体检测、图像标注等功能的…

stable diffusion公司发布4款LLM大语言模型,为何大家都喜爱LLM?

stable diffusion模型是Stability AI开源的一个text-to-image的扩散模型&#xff0c;其模型在速度与质量上面有了质的突破&#xff0c;玩家们可以在自己消费级GPU上面来运行此模型&#xff0c;本模型基于CompVis 和 Runway 团队的Latent Diffusion Models。本期我们不介绍stabl…

口才不好可以做管理岗吗?

口才不好也可以选择管理岗位 口才是很重要的职场技能之一&#xff0c;但是并不代表没有口才就不能从事管理工作。管理岗位需要的不仅是口才&#xff0c;还包括组织能力、决策能力、问题解决能力等多种素质。下面我从以下几个方面来分析一下&#xff0c;口才不好的人也有可能选…

MySQL(8):聚合函数

聚合函数介绍 聚合函数&#xff1a; 对一组数据进行汇总的函数&#xff0c;输入的是一组数据的集合&#xff0c;输出的是单个值。 聚合函数类型&#xff1a;AVG(),SUM(),MAX(),MIN(),COUNT() AVG / SUM 只适用于数值类型的字段&#xff08;或变量&#xff09; SELECT AVG(…

C++prime之输入输出文件

作为一种优秀的语言&#xff0c;C必然是能操作文件的&#xff0c;但是我们要知道&#xff0c;C是不直接处理输入输出的&#xff0c;而是通过一族定义在标准库中的类型来处理IO的。 ‘流’和‘缓冲区’ ‘流’和‘缓冲区’ C程序把输入输出看作字节流&#xff0c;并且其只检查…

【数据集处理】基于Python处理EAR5数据

基于Python处理EAR5数据 1 EAR5数据简介2 数据集处理准备工作&#xff1a;xarray库安装2.1 数据预处理-剔除异常值 参考 1 EAR5数据简介 ERA5是ECMWF&#xff08;欧洲中期天气预报中心&#xff09;对1950年1月至今全球气候的第五代大气再分析数据集。 包含了四个基本变量(日…

[SSD综述 1.4] SSD固态硬盘的结构和原理导论

依公知及经验整理,原创保护,禁止转载。 专栏 《SSD入门到精通系列》 <<<< 返回总目录 <<<< ​ 前言 机械硬盘的存储系统由于内部结构, 其IO访问性能无法进一步提高,CPU与存储器之间的性能差距逐渐扩大。以Nand Flash为存储介质的固态硬盘技术的发展,…

【Python实例】netCDF数据介绍及处理

netCDF数据处理 netCDF数据介绍1 netCDF数据结构1.1 维度(Dimensions)1.2 变量&#xff08;Variables&#xff09;1.3 坐标变量&#xff08;Coordinate Variables)1.4 属性&#xff08;Attributes&#xff09; 2 netCDF数据处理方法1&#xff1a;利用netCDF4打开nc格式数据2.1.…

Python基础入门例程33-NP33 乘法与幂运算(运算符)

最近的博文&#xff1a; Python基础入门例程32-NP32 牛牛的加减器&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程31-NP31 团队分组&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程30-NP30 用列表实现队列&#xff08;列表&#xff09;-CSDN博客 目…

水经微图Web版从入门到精通

我们在《47GB水经微图从入门到精通视频教程》和《163M水经微图从入门到精通文档教程》中&#xff0c;为大家分享了水经微图PC版的教程。 这里&#xff0c;我们再为大家分享水经微图Web版的文档教程。 水经微图Web版教程 水经微图Web版的教程&#xff0c;主要包括基础名词、…

【日常记录】关于LinkedHashMap中key为数字字符串根据compareTo排序的问题

今天在修复Bug的时候&#xff0c;在项目中发现有这样一段代码&#xff08;为了方便&#xff0c;下面用一个例子进行演示&#xff09;。 项目中使用了LinkedHashMap key为Long类型&#xff0c;value为String类型。 并且&#xff0c;LinkedHashMap 使用Stream流 对key进行升序的排…

Java web(六):FilterListenerAJAX

文章目录 一、Filter1.1 基本介绍1.2 过滤器的执行流程1.3 拦截路径配置1.4 过滤器链1.5 案例 二、Listener三、AJAX3.1 快速入门3.2 Axios异步框架 四、 JSON4.1 JSON基础语法4.2 Fastjson 五、 案例JSONAxiosServlet Java web的三大组件&#xff1a;Servlet、Filter、Listene…

2023最新版本 FreeRTOS教程 -5-切断驱动和应用的直接关联与多输入的编码思路

在多输入的场景方便添加新的设备如图 总体的思路框图 函数讲解&#xff08;图片太抽象通过这个函数理解&#xff09; 写入自己的队列 统一数据(建议读取自己的队列 再统一到应用的队列 这里图方便省略了) 通过统一的数据做出执行操作 验证 队列为空直接阻塞 通过三个按…

AST注入-从原型链污染到RCE

文章目录 概念漏洞Handlebarspug 例题 [湖湘杯 2021 final]vote 概念 什么是AST注入 在NodeJS中&#xff0c;AST经常被在JS中使用&#xff0c;作为template engines(引擎模版)和typescript等。对于引擎模版&#xff0c;结构如下图所示。 如果在JS应用中存在原型污染漏洞&…

Linux网络配置、ping不通外网解决办法

有很多说服务当中有五项才是对的&#xff0c;也不一定&#xff0c;我这里也只有四项&#xff0c;所以在尝试一些其他办法后再决定重新安装vmware吧&#xff0c;最开始我也ping不成功&#xff0c;查看也是四项&#xff0c;重新装了一次还是四项&#xff0c;找了一些办法&#xf…

芯片测试概述

芯片为什么要做测试 在芯片设计到制作的过程中 不可避免会出现缺陷 芯片测试就是为了发现产生缺陷的芯片 如果不加入测试环节 将有缺陷的芯片卖给顾客 受到的损失是测试的花费的数倍 芯片测试的作用 1. 保证芯片的质量 2. 缩短芯片上市时间 3. 提高公司利润 芯片的测试类型 …