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日

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。