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

关于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日

悬赏问题

  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥15 绘制多分类任务的roc曲线时只画出了一类的roc,其它的auc显示为nan
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?