Hi Wesley,
I think I can share the revised ethernetif_input(). But I do this without any warranty.
This job should be done by NXP...
Take care... this function sometime needs a big local buffer with size ENET_FRAME_MAX_FRAMELEN !!!
Best regards
Manfred
void ethernetif_input(enet_handle_t *handle, void *param)
{
struct eth_hdr *ethhdr;
struct pbuf *packetTempBuffer;
status_t status;
uint32_t length = 0;
struct netif *netif = param;
static enet_data_error_stats_t eErrStatic; // to get the error statically
// by MS enet_data_error_stats_t eErrStatic;
uint32_t localLen;
uint32_t workedBytes;
uint32_t lengthToCopy;
static uint16_t type;
/* Check input parameter */
if (netif == NULL)
{
LWIP_ASSERT("Input param is NULL", 0);
/* Should not reach this statement if error occurs */
return;
}
/* Read all data from ring buffer and send to uper layer */
do
{
/* Get the Frame size */
status = ENET_GetRxFrameSize(handle, &length);
/* Call ENET_ReadFrame when there is a received frame. */
if (length != 0)
{
uint8_t *receivedDataBuffer;
struct pbuf *packetBuffer;
packetBuffer = pbuf_alloc(PBUF_RAW, length, PBUF_POOL);
/* Received valid frame. Deliver the rx buffer with the size equal to length. */
if ((packetBuffer == NULL) || (packetBuffer->payload == NULL))
{
pbuf_free(packetBuffer);
packetBuffer = NULL;
LWIP_ASSERT("Fail to allocate new memory space", 0);
LINK_STATS_INC(link.memerr);
/* Should not reach this statement if error occurs */
return;
}
if ( length <= PBUF_POOL_BUFSIZE ) {
// target buffer
receivedDataBuffer = packetBuffer->payload;
packetBuffer->len = (u16_t)length;
// read direct to one buffer
ENET_ReadFrame(ENET, handle, receivedDataBuffer, packetBuffer->len);
LINK_STATS_INC(link.recv);
}
else {
// read to one temp buffer and copy then to allocated memory
unsigned char ucBuffer[ENET_FRAME_MAX_FRAMELEN];
if ( length > ENET_FRAME_MAX_FRAMELEN ) {
pbuf_free(packetBuffer);
packetBuffer = NULL;
LWIP_ASSERT("Fail length > ENET_FRAME_MAX_FRAMELEN", 0);
LINK_STATS_INC(link.lenerr);
/* Should not reach this statement if error occurs */
return;
}
// read local
ENET_ReadFrame(ENET, handle, ucBuffer, length);
LINK_STATS_INC(link.recv);
// take the total length
localLen = length;
workedBytes = 0;
packetTempBuffer = packetBuffer;
while ( (localLen) && (packetTempBuffer != NULL) ) {
lengthToCopy = localLen;
if ( lengthToCopy > packetTempBuffer->len ) {
lengthToCopy = packetTempBuffer->len;
}
// copy one part
memcpy(packetTempBuffer->payload, &ucBuffer[workedBytes], lengthToCopy);
// next buffer in chain
packetTempBuffer = packetTempBuffer->next;
localLen -= lengthToCopy;
workedBytes += lengthToCopy;
};
}
/* points to packet payload, which starts with an Ethernet header */
ethhdr = packetBuffer->payload;
type = htons(ethhdr->type);
switch (type)
{
/* IP or ARP packet? */
case ETHTYPE_IP:
case ETHTYPE_ARP:
#if PPPOE_SUPPORT
/* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* full packet send to tcpip_thread to process */
if (netif->input(packetBuffer, netif) != ERR_OK)
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(packetBuffer);
packetBuffer = NULL;
}
break;
default:
pbuf_free(packetBuffer);
packetBuffer = NULL;
LINK_STATS_INC(link.drop);
break;
}
}
else
{
/* Update the received buffer when error happened. */
if ( (status != kStatus_Success) && (status != kStatus_ENET_RxFrameEmpty) )
{
/* Get the error information of the received g_frame. */
ENET_GetRxErrBeforeReadFrame(handle, &eErrStatic);
/* update the receive buffer. */
ENET_ReadFrame(ENET, handle, NULL, 0);
LINK_STATS_INC(link.err);
}
}
} while (kStatus_ENET_RxFrameEmpty != status);
}