VxWorks: Remove usage of muxTkSend, improve abandoned frame handling. bugfix for msgQRecv return value, add cleanup on NIC close

feature/soem_140
Andreas Karlsson 2019-05-24 13:58:41 +02:00
parent c220255604
commit 49810a5adf
2 changed files with 170 additions and 129 deletions

View File

@ -31,10 +31,12 @@
* This layer if fully transparent for the higher layers. * This layer if fully transparent for the higher layers.
*/ */
#include <vxWorks.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <muxLib.h>
#include <ipProto.h> #include <ipProto.h>
#include <vxWorks.h>
#include <wvLib.h> #include <wvLib.h>
#include "oshw.h" #include "oshw.h"
@ -146,7 +148,7 @@ int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary)
pPktDev->overrun_count = 0; pPktDev->overrun_count = 0;
/* Create multi-thread support semaphores */ /* Create multi-thread support semaphores */
port->sem_get_index = semBCreate(SEM_Q_FIFO, SEM_FULL); port->sem_get_index = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
/* Get the dev name and unit from ifname /* Get the dev name and unit from ifname
* We assume form gei1, fei0... * We assume form gei1, fei0...
@ -172,12 +174,21 @@ int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary)
* as user reference * as user reference
*/ */
/* Bind to mux */ /* Bind to mux */
pPktDev->pCookie = muxBind(ifn, unit_no, mux_rx_callback, NULL, NULL, NULL, MUX_PROTO_SNARF, "ECAT SNARF", pPktDev); pPktDev->pCookie = muxBind(ifn,
unit_no,
mux_rx_callback,
NULL,
NULL,
NULL,
MUX_PROTO_SNARF,
"ECAT SNARF",
pPktDev);
if (pPktDev->pCookie == NULL) if (pPktDev->pCookie == NULL)
{ {
/* fail */ /* fail */
NIC_LOGMSG("ecx_setupnic: muxBind init for gei: %d failed\n", unit_no, 2, 3, 4, 5, 6); NIC_LOGMSG("ecx_setupnic: muxBind init for gei: %d failed\n",
unit_no, 2, 3, 4, 5, 6);
goto exit; goto exit;
} }
@ -271,6 +282,7 @@ int ecx_closenic(ecx_portt *port)
{ {
int i; int i;
ETHERCAT_PKT_DEV * pPktDev; ETHERCAT_PKT_DEV * pPktDev;
M_BLK_ID trash_can;
pPktDev = &(port->pktDev); pPktDev = &(port->pktDev);
@ -278,6 +290,16 @@ int ecx_closenic(ecx_portt *port)
{ {
if (port->msgQId[i] != MSG_Q_ID_NULL) if (port->msgQId[i] != MSG_Q_ID_NULL)
{ {
if (msgQReceive(port->msgQId[i],
(char *)&trash_can,
sizeof(M_BLK_ID),
NO_WAIT) != ERROR)
{
NIC_LOGMSG("ecx_closenic: idx %d MsgQ close\n", i,
2, 3, 4, 5, 6);
/* Free resources */
netMblkClChainFree(trash_can);
}
msgQDelete(port->msgQId[i]); msgQDelete(port->msgQId[i]);
} }
} }
@ -295,6 +317,16 @@ int ecx_closenic(ecx_portt *port)
{ {
if (port->redport->msgQId[i] != MSG_Q_ID_NULL) if (port->redport->msgQId[i] != MSG_Q_ID_NULL)
{ {
if (msgQReceive(port->redport->msgQId[i],
(char *)&trash_can,
sizeof(M_BLK_ID),
NO_WAIT) != ERROR)
{
NIC_LOGMSG("ecx_closenic: idx %d MsgQ close\n", i,
2, 3, 4, 5, 6);
/* Free resources */
netMblkClChainFree(trash_can);
}
msgQDelete(port->redport->msgQId[i]); msgQDelete(port->redport->msgQId[i]);
} }
} }
@ -333,8 +365,6 @@ int ecx_getindex(ecx_portt *port)
{ {
int idx; int idx;
int cnt; int cnt;
MSG_Q_ID msgQId;
M_BLK_ID trash_can;
semTake(port->sem_get_index, WAIT_FOREVER); semTake(port->sem_get_index, WAIT_FOREVER);
@ -356,27 +386,6 @@ int ecx_getindex(ecx_portt *port)
} }
} }
port->rxbufstat[idx] = EC_BUF_ALLOC; port->rxbufstat[idx] = EC_BUF_ALLOC;
/* Clean up any abandoned frames */
msgQId = port->msgQId[idx];
if (msgQReceive(msgQId, (char *)&trash_can, sizeof(M_BLK_ID), NO_WAIT) == OK)
{
/* Free resources */
netMblkClChainFree(trash_can);
}
if (port->redstate != ECT_RED_NONE)
{
port->redport->rxbufstat[idx] = EC_BUF_ALLOC;
/* Clean up any abandoned frames */
msgQId = port->redport->msgQId[idx];
if (msgQReceive(msgQId, (char *)&trash_can, sizeof(M_BLK_ID), NO_WAIT) == OK)
{
/* Free resources */
netMblkClChainFree(trash_can);
}
}
port->lastidx = idx; port->lastidx = idx;
semGive(port->sem_get_index); semGive(port->sem_get_index);
@ -399,18 +408,41 @@ void ecx_setbufstat(ecx_portt *port, int idx, int bufstat)
/** Low level transmit buffer over mux layer 2 driver /** Low level transmit buffer over mux layer 2 driver
* *
* @param[in] pPktDev = packet device to send buffer over * @param[in] pPktDev = packet device to send buffer over
* @param[in] idx = index in tx buffer array
* @param[in] buf = buff to send * @param[in] buf = buff to send
* @param[in] len = bytes to send * @param[in] len = bytes to send
* @return driver send result * @return driver send result
*/ */
static int ec_outfram_send(ETHERCAT_PKT_DEV * pPktDev, void * buf, int len) static int ec_outfram_send(ETHERCAT_PKT_DEV * pPktDev, int idx, void * buf, int len)
{ {
STATUS status = OK; STATUS status = OK;
M_BLK_ID pPacket; M_BLK_ID pPacket = NULL;
int rval = 0; int rval = 0;
END_OBJ *endObj = (END_OBJ *)pPktDev->endObj;
MSG_Q_ID msgQId;
/* Clean up any abandoned frames and re-use the allocated buffer*/
msgQId = pPktDev->port->msgQId[idx];
if(msgQNumMsgs(msgQId) > 0)
{
pPktDev->abandoned_count++;
NIC_LOGMSG("ec_outfram_send: idx %d MsgQ abandoned\n", idx,
2, 3, 4, 5, 6);
if (msgQReceive(msgQId,
(char *)&pPacket,
sizeof(M_BLK_ID),
NO_WAIT) == ERROR)
{
pPacket = NULL;
NIC_LOGMSG("ec_outfram_send: idx %d MsgQ mBlk handled by receiver\n", idx,
2, 3, 4, 5, 6);
}
}
if (pPacket == NULL)
{
/* Allocate m_blk to send */ /* Allocate m_blk to send */
if ((pPacket = netTupleGet(pPktDev->endObj->pNetPool, if ((pPacket = netTupleGet(endObj->pNetPool,
len, len,
M_DONTWAIT, M_DONTWAIT,
MT_DATA, MT_DATA,
@ -419,14 +451,15 @@ static int ec_outfram_send(ETHERCAT_PKT_DEV * pPktDev, void * buf, int len)
NIC_LOGMSG("ec_outfram_send: Could not allocate MBLK memory!\n", 1, 2, 3, 4, 5, 6); NIC_LOGMSG("ec_outfram_send: Could not allocate MBLK memory!\n", 1, 2, 3, 4, 5, 6);
return ERROR; return ERROR;
} }
}
pPacket->mBlkHdr.mLen = len; pPacket->mBlkHdr.mLen = len;
pPacket->mBlkHdr.mFlags |= M_HEADER; pPacket->mBlkHdr.mFlags |= M_PKTHDR;
pPacket->mBlkHdr.mData = pPacket->pClBlk->clNode.pClBuf; pPacket->mBlkHdr.mData = pPacket->pClBlk->clNode.pClBuf;
pPacket->mBlkPktHdr.len = len; pPacket->mBlkPktHdr.len = pPacket->m_len;
netMblkFromBufCopy(pPacket, buf, 0, pPacket->mBlkHdr.mLen, M_DONTWAIT, NULL); netMblkFromBufCopy(pPacket, buf, 0, pPacket->mBlkHdr.mLen, M_DONTWAIT, NULL);
status = muxTkSend(pPktDev->pCookie, pPacket, NULL, htons(ETH_P_ECAT), NULL); status = muxSend(endObj, pPacket);
if (status == OK) if (status == OK)
{ {
@ -475,7 +508,7 @@ int ecx_outframe(ecx_portt *port, int idx, int stacknumber)
} }
(*stack->rxbufstat)[idx] = EC_BUF_TX; (*stack->rxbufstat)[idx] = EC_BUF_TX;
rval = ec_outfram_send(pPktDev, (char*)(*stack->txbuf)[idx], rval = ec_outfram_send(pPktDev, idx, (char*)(*stack->txbuf)[idx],
(*stack->txbuflength)[idx]); (*stack->txbuflength)[idx]);
if (rval > 0) if (rval > 0)
{ {
@ -516,7 +549,7 @@ int ecx_outframe_red(ecx_portt *port, int idx)
ehp->sa1 = htons(secMAC[1]); ehp->sa1 = htons(secMAC[1]);
/* transmit over secondary interface */ /* transmit over secondary interface */
port->redport->rxbufstat[idx] = EC_BUF_TX; port->redport->rxbufstat[idx] = EC_BUF_TX;
rval = ec_outfram_send(&(port->redport->pktDev), &(port->txbuf2), port->txbuflength2); rval = ec_outfram_send(&(port->redport->pktDev), idx, &(port->txbuf2), port->txbuflength2);
if (rval <= 0) if (rval <= 0)
{ {
port->redport->rxbufstat[idx] = EC_BUF_EMPTY; port->redport->rxbufstat[idx] = EC_BUF_EMPTY;
@ -545,6 +578,7 @@ static int mux_rx_callback(void* pCookie, long type, M_BLK_ID pMblk, LL_HDR_INFO
MSG_Q_ID msgQId; MSG_Q_ID msgQId;
ETHERCAT_PKT_DEV * pPktDev; ETHERCAT_PKT_DEV * pPktDev;
int length; int length;
int bufstat;
/* check if it is an EtherCAT frame */ /* check if it is an EtherCAT frame */
if (type == ETH_P_ECAT) if (type == ETH_P_ECAT)
@ -567,16 +601,19 @@ static int mux_rx_callback(void* pCookie, long type, M_BLK_ID pMblk, LL_HDR_INFO
/* Check if it is the redundant port or not */ /* Check if it is the redundant port or not */
if (pPktDev->redundant == 1) if (pPktDev->redundant == 1)
{ {
bufstat = port->redport->rxbufstat[idxf];
msgQId = port->redport->msgQId[idxf]; msgQId = port->redport->msgQId[idxf];
} }
else else
{ {
bufstat = port->rxbufstat[idxf];
msgQId = port->msgQId[idxf]; msgQId = port->msgQId[idxf];
} }
if (length > 0) /* Check length and if someone expects the frame */
if (length > 0 && bufstat == EC_BUF_TX)
{ {
/* Post the frame to the reqceive Q for the EtherCAT stack */ /* Post the frame to the receive Q for the EtherCAT stack */
STATUS status; STATUS status;
status = msgQSend(msgQId, (char *)&pMblk, sizeof(M_BLK_ID), status = msgQSend(msgQId, (char *)&pMblk, sizeof(M_BLK_ID),
NO_WAIT, MSG_PRI_NORMAL); NO_WAIT, MSG_PRI_NORMAL);
@ -596,15 +633,19 @@ static int mux_rx_callback(void* pCookie, long type, M_BLK_ID pMblk, LL_HDR_INFO
NIC_LOGMSG("mux_rx_callback: idx %d MsgQ overrun\n", idxf, NIC_LOGMSG("mux_rx_callback: idx %d MsgQ overrun\n", idxf,
2, 3, 4, 5, 6); 2, 3, 4, 5, 6);
M_BLK_ID trash_can; M_BLK_ID trash_can;
if (msgQReceive(msgQId, (char *)&trash_can, if (msgQReceive(msgQId,
sizeof(M_BLK_ID), NO_WAIT) == OK) (char *)&trash_can,
sizeof(M_BLK_ID),
NO_WAIT) != ERROR)
{ {
/* Free resources */ /* Free resources */
netMblkClChainFree(trash_can); netMblkClChainFree(trash_can);
} }
status = msgQSend(msgQId,
status = msgQSend(msgQId, (char *)&pMblk, sizeof(M_BLK_ID), (char *)&pMblk,
NO_WAIT, MSG_PRI_NORMAL); sizeof(M_BLK_ID),
NO_WAIT,
MSG_PRI_NORMAL);
if (status == OK) if (status == OK)
{ {
NIC_WVEVENT(ECAT_RECV_RETRY_OK, (char *)&length, sizeof(length)); NIC_WVEVENT(ECAT_RECV_RETRY_OK, (char *)&length, sizeof(length));
@ -912,9 +953,9 @@ int ec_outframe_red(int idx)
return ecx_outframe_red(&ecx_port, idx); return ecx_outframe_red(&ecx_port, idx);
} }
int ec_inframe(int idx, int stacknumber) int ec_inframe(int idx, int stacknumber, int timeout)
{ {
return ecx_inframe(&ecx_port, idx, stacknumber); return ecx_inframe(&ecx_port, idx, stacknumber, timeout);
} }
int ec_waitinframe(int idx, int timeout) int ec_waitinframe(int idx, int timeout)

View File

@ -17,18 +17,18 @@ extern "C"
#endif #endif
#include <vxWorks.h> #include <vxWorks.h>
#include <muxLib.h>
/** structure to connect EtherCAT stack and VxWorks device */ /** structure to connect EtherCAT stack and VxWorks device */
typedef struct ETHERCAT_PKT_DEV typedef struct ETHERCAT_PKT_DEV
{ {
struct ecx_port *port; struct ecx_port *port;
void *pCookie; void *pCookie;
END_OBJ *endObj; void *endObj;
UINT32 redundant; UINT32 redundant;
UINT32 tx_count; UINT32 tx_count;
UINT32 rx_count; UINT32 rx_count;
UINT32 overrun_count; UINT32 overrun_count;
UINT32 abandoned_count;
}ETHERCAT_PKT_DEV; }ETHERCAT_PKT_DEV;
/** pointer structure to Tx and Rx stacks */ /** pointer structure to Tx and Rx stacks */