zhiyaormb 2022-08-10 12:29 采纳率: 23.1%
浏览 151
已结题

关于EtherCAT协议栈SOEM的问题

最近研究SOEM的源代码,版本1.4.0,发现一个问题:
这里以win版本举例,大概看了一下intime和rtk,里面也类似:
ecx_setupnic函数里(nidrv.c),关于接收缓冲区,是这样处理的:

int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary) 
{
  ……
  port->stack.tempbuf     = &(port->tempinbuf);
  port->stack.rxbuf       = &(port->rxbuf);
  ……
}
typedef struct
{
   ……
   /** temporary receive buffer */
   ec_bufT     *tempbuf;
   /** rx buffers */
   ec_bufT     (*rxbuf)[EC_MAXBUF];
   ……
} ec_stackT;  

typedef struct
{
  ec_stackT   stack;
   ……
   /** rx buffers */
   ec_bufT rxbuf[EC_MAXBUF];
   ……
   /** temporary rx buffer */
   ec_bufT tempinbuf;
  ……
} ecx_portt;

在接收的时候,有类似这样的处理:

int ecx_inframe(ecx_portt *port, int idx, int stacknumber)
{
if (!stacknumber)
   {
      stack = &(port->stack);
   }
   else
   {
      stack = &(port->redport->stack);
   }
   rval = EC_NOFRAME;
   rxbuf = &(*stack->rxbuf)[idx];
  ……
    memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idx] - ETH_HEADERSIZE);
}

这里显然,rxbuf里面,包头部分已经去掉了,没有拷贝过来。但是,ethercatbase.c里面的很多函数却有类似这样的处理:

int ecx_BRD(ecx_portt* port, uint16 ADP, uint16 ADO, uint16 length, void* data, int timeout)
{
    uint8 idx;
    int wkc;

    /* get fresh index */
    idx = ecx_getindex(port);
    /* setup datagram */
    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_BRD, idx, ADP, ADO, length, data);
    /* send data and wait for answer */
    wkc = ecx_srconfirm(port, idx, timeout);
    if (wkc > 0)
    {
        /* copy datagram to data buffer */
        //ppout = &(port->rxbuf[idx][EC_HEADERSIZE]);
        memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);//**注意这里!!!!!!!!!!!**
    }
    /* clear buffer status */
    ecx_setbufstat(port, idx, EC_BUF_EMPTY);

    return wkc;
}

还有几个函数也是类似的处理:ecx_APRD,ecx_ARMW,ecx_FRMW,ecx_FPRD,ecx_LRW,ecx_LRD,ecx_LRWDC。牵扯的面还挺广。
这里包头的长度是这样的:

PACKED_BEGIN
typedef struct PACKED
{
   /** destination MAC */
   uint16  da0,da1,da2;
   /** source MAC */
   uint16  sa0,sa1,sa2;
   /** ethernet type */
   uint16  etype;
} ec_etherheadert;
PACKED_END
/** ethernet header size */
#define ETH_HEADERSIZE      sizeof(ec_etherheadert)

这里面,ecx_srconfirm函数里面调用的ecx_inframe,得到的rxbuf里面的数据已经是去掉了包头的。那么这里就有个大问题,为什么先前已经去掉了一次包头,这里是需要再去掉一次,还是nicdrv.h里面的处理有错误?我对比了一下1.3.1的这部分代码,好像也是类似的。

img


这是ethercat的数据包格式。没看出需要去掉两次包头的情况啊。

  • 写回答

2条回答 默认 最新

  • qllaoda 2022-08-10 13:19
    关注

    网络协议是分层的,每一层有每一层的包头,你说的包头可能不是同一层的。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 8月18日
  • 已采纳回答 8月10日
  • 创建了问题 8月10日

悬赏问题

  • ¥15 关于#python#的问题:我知道这个问题对你们来说肯定so easy
  • ¥15 wpf datagrid如何实现多层表头
  • ¥15 为啥画版图在Run DRC会出现Connect Error?可我Calibre的hostname和计算机的hostname已经设置成一样的了。
  • ¥20 网站后台使用极速模式非常的卡
  • ¥20 Keil uVision5创建project没反应
  • ¥15 mmseqs内存报错
  • ¥15 vika文档如何与obsidian同步
  • ¥15 华为手机相册里面的照片能够替换成自己想要的照片吗?
  • ¥15 陆空双模式无人机飞控设置
  • ¥15 sentaurus lithography