最近研究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的这部分代码,好像也是类似的。
这是ethercat的数据包格式。没看出需要去掉两次包头的情况啊。