zhiyaormb 2022-08-10 04:29 采纳率: 21.4%
浏览 174
已结题

关于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 05:19
    关注

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

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

报告相同问题?

问题事件

  • 系统已结题 8月17日
  • 已采纳回答 8月10日
  • 创建了问题 8月10日
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部