in lib/nxp/drivers/fsl_enet.c [1498:1670]
status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length, uint8_t channel)
{
assert(handle);
uint32_t len = 0;
uint32_t offset = 0;
uint32_t control;
bool isLastBuff = false;
enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&handle->rxBdRing[channel];
enet_rx_bd_struct_t *rxDesc;
status_t result = kStatus_Fail;
uint16_t index = rxBdRing->rxGenIdx;
bool suspend = false;
#ifdef ENET_PTP1588FEATURE_REQUIRED
uint32_t buffer;
uint32_t bufferAdd;
#endif /* ENET_PTP1588FEATURE_REQUIRED */
/* Suspend and command for rx. */
if (base->DMA_CH[channel].DMA_CHX_STAT & ENET_DMA_CH_DMA_CHX_STAT_RBU_MASK)
{
suspend = true;
}
/* For data-NULL input, only update the buffer descriptor. */
if ((!data))
{
do
{
/* Get the control flag. */
rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
control = rxDesc->control;
/* Updates the receive buffer descriptors. */
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
/* Find the last buffer descriptor for the frame. */
if (control & ENET_RXDESCRIP_WR_LD_MASK)
{
#ifdef ENET_PTP1588FEATURE_REQUIRED
/* Reinit for the context descritor which has been updated by DMA. */
rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
if (rxDesc->control & ENET_RXDESCRIP_WR_CTXT_MASK)
{
if (!handle->doubleBuffEnable)
{
buffer = handle->rxbuffers[rxBdRing->rxGenIdx];
ENET_UpdateRxDescriptor(rxDesc, (void *)buffer, NULL, handle->rxintEnable,
handle->doubleBuffEnable);
}
else
{
buffer = handle->rxbuffers[2 * rxBdRing->rxGenIdx];
bufferAdd = handle->rxbuffers[2 * rxBdRing->rxGenIdx + 1];
ENET_UpdateRxDescriptor(rxDesc, (void *)buffer, (void *)bufferAdd, handle->rxintEnable,
handle->doubleBuffEnable);
}
rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
}
#endif /* ENET_PTP1588FEATURE_REQUIRED */
break;
}
} while (rxBdRing->rxGenIdx != index);
result = kStatus_Success;
}
else
{
#ifdef ENET_PTP1588FEATURE_REQUIRED
enet_ptp_time_data_t ptpTsData;
bool ptp1588 = false;
#endif /* ENET_PTP1588FEATURE_REQUIRED */
while ((!isLastBuff))
{
/* The last buffer descriptor of a frame. */
rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
#ifdef ENET_PTP1588FEATURE_REQUIRED
if (rxDesc->control & ENET_RXDESCRIP_WR_FD_MASK)
{
ptp1588 = ENET_Ptp1588ParseFrame((uint8_t *)rxDesc->buff1Addr, &ptpTsData, false);
}
#endif
if (rxDesc->control & ENET_RXDESCRIP_WR_LD_MASK)
{
/* This is a valid frame. */
isLastBuff = true;
if (length == (rxDesc->control & ENET_RXDESCRIP_WR_PACKETLEN_MASK))
{
/* Copy the frame to user's buffer. */
len = (rxDesc->control & ENET_RXDESCRIP_WR_PACKETLEN_MASK) - offset;
if (len > rxBdRing->rxBuffSizeAlign)
{
memcpy(data + offset, (void *)rxDesc->buff1Addr, rxBdRing->rxBuffSizeAlign);
offset += rxBdRing->rxBuffSizeAlign;
memcpy(data + offset, (void *)rxDesc->buff2Addr, len - rxBdRing->rxBuffSizeAlign);
}
else
{
memcpy(data + offset, (void *)rxDesc->buff1Addr, len);
}
result = kStatus_Success;
}
/* Updates the receive buffer descriptors. */
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
#ifdef ENET_PTP1588FEATURE_REQUIRED
/* Store the rx timestamp which is in the next buffer descriptor of the last
* descriptor of a frame. */
rxDesc = rxBdRing->rxBdBase + rxBdRing->rxGenIdx;
/* Reinit for the context descritor which has been updated by DMA. */
if (rxDesc->control & ENET_RXDESCRIP_WR_CTXT_MASK)
{
if (ptp1588)
{
ENET_StoreRxFrameTime(base, handle, rxDesc, channel, &ptpTsData);
}
if (!handle->doubleBuffEnable)
{
buffer = handle->rxbuffers[rxBdRing->rxGenIdx];
ENET_UpdateRxDescriptor(rxDesc, (void *)buffer, NULL, handle->rxintEnable,
handle->doubleBuffEnable);
}
else
{
buffer = handle->rxbuffers[2 * rxBdRing->rxGenIdx];
bufferAdd = handle->rxbuffers[2 * rxBdRing->rxGenIdx + 1];
ENET_UpdateRxDescriptor(rxDesc, (void *)buffer, (void *)bufferAdd, handle->rxintEnable,
handle->doubleBuffEnable);
}
rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen);
}
base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR;
#endif /* ENET_PTP1588FEATURE_REQUIRED */
}
else
{
/* Store a frame on several buffer descriptors. */
isLastBuff = false;
/* Length check. */
if (offset >= length)
{
/* Updates the receive buffer descriptors. */
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
break;
}
memcpy(data + offset, (void *)rxDesc->buff1Addr, rxBdRing->rxBuffSizeAlign);
offset += rxBdRing->rxBuffSizeAlign;
if ((rxDesc->buff2Addr) && (handle->doubleBuffEnable))
{
memcpy(data + offset, (void *)rxDesc->buff2Addr, rxBdRing->rxBuffSizeAlign);
offset += rxBdRing->rxBuffSizeAlign;
}
/* Updates the receive buffer descriptors. */
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, handle->rxintEnable, handle->doubleBuffEnable);
}
}
}
/* Set command for rx when it is suspend. */
if (suspend)
{
base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR = base->DMA_CH[channel].DMA_CHX_RXDESC_TAIL_PTR;
}
return result;
}