status_t ENET_GetRxFrame(ENET_Type *base, enet_handle_t *handle, enet_rx_frame_struct_t *rxFrame, uint8_t ringId) { assert(handle != NULL); assert(ringId < (uint8_t)FSL_FEATURE_ENET_QUEUE); assert(handle->rxBdRing[ringId].rxBdBase != NULL); assert(rxFrame != NULL); assert(rxFrame->rxBuffArray != NULL); status_t result = kStatus_ENET_RxFrameEmpty; enet_rx_bd_ring_t *rxBdRing = &handle->rxBdRing[ringId]; volatile enet_rx_bd_struct_t *curBuffDescrip = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; bool isLastBuff = false; uintptr_t newBuff = 0; uint16_t buffLen = 0; enet_buffer_struct_t *rxBuffer; uintptr_t address; uintptr_t buffer; uint16_t index; /* Check the current buffer descriptor's empty flag. If empty means there is no frame received. */ index = rxBdRing->rxGenIdx; while (0U == (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK)) { /* Find the last buffer descriptor. */ if (0U != (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK)) { /* The last buffer descriptor stores the error status of this received frame. */ result = ENET_GetRxFrameErr((enet_rx_bd_struct_t *)(uint32_t)curBuffDescrip, &rxFrame->rxFrameError); break; } /* Get feedback that no-empty BD takes frame length of 0. Probably an IP issue and drop this BD. */ if (curBuffDescrip->length == 0U) { /* Set LAST bit manually to let following drop error frame operation drop this abnormal BD. */ curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_RX_LAST_MASK; result = kStatus_ENET_RxFrameError; break; } index = ENET_IncreaseIndex(index, rxBdRing->rxRingLen); curBuffDescrip = rxBdRing->rxBdBase + index; /* Can't find the last BD flag, no valid frame. */ if (index == rxBdRing->rxGenIdx) { /* kStatus_ENET_RxFrameEmpty. */ break; } } /* Drop the error frame. */ if (result == kStatus_ENET_RxFrameError) { curBuffDescrip = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; do { /* The last buffer descriptor of a frame. */ if (0U != (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK)) { isLastBuff = true; } /* Clears status including the owner flag. */ curBuffDescrip->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; /* Sets the receive buffer descriptor with the empty flag. */ curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; /* Increase current buffer descriptor to the next one. */ rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen); curBuffDescrip = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; } while (!isLastBuff); ENET_ActiveReadRing(base, ringId); return result; } else if (result != kStatus_Success) { return result; } else { /* Intentional empty */ } /* Get the valid frame */ curBuffDescrip = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; index = 0; do { newBuff = (uintptr_t)(uint8_t *)handle->rxBuffAlloc(base, handle->userData, ringId); if (newBuff != 0U) { assert((uint64_t)newBuff + handle->rxBuffSizeAlign[ringId] - 1U <= UINT32_MAX); rxBuffer = &rxFrame->rxBuffArray[index]; #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET address = MEMORY_ConvertMemoryMapAddress(curBuffDescrip->buffer, kMEMORY_DMA2Local); #else address = curBuffDescrip->buffer; #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL if (handle->rxMaintainEnable[ringId]) { DCACHE_InvalidateByRange(address, handle->rxBuffSizeAlign[ringId]); } #endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ rxBuffer->buffer = (void *)(uint8_t *)address; /* The last buffer descriptor of a frame. */ if (0U != (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK)) { /* This is a valid frame. */ isLastBuff = true; rxFrame->totLen = curBuffDescrip->length; rxBuffer->length = curBuffDescrip->length - buffLen; rxFrame->rxAttribute.promiscuous = false; if (0U != (base->RCR & ENET_RCR_PROM_MASK)) { if (0U != (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_MISS_MASK)) { rxFrame->rxAttribute.promiscuous = true; } } #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE rxFrame->rxAttribute.timestamp = curBuffDescrip->timestamp; #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } else { rxBuffer->length = curBuffDescrip->length; buffLen += rxBuffer->length; } /* Give new buffer from application to BD */ #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET buffer = MEMORY_ConvertMemoryMapAddress(newBuff, kMEMORY_Local2DMA); #else buffer = newBuff; #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL if (handle->rxMaintainEnable[ringId]) { DCACHE_InvalidateByRange(buffer, handle->rxBuffSizeAlign[ringId]); } #endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ curBuffDescrip->buffer = (uint32_t)buffer; /* Clears status including the owner flag. */ curBuffDescrip->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; /* Sets the receive buffer descriptor with the empty flag. */ curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; /* Increase Rx array index and the buffer descriptor address. */ index++; rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen); curBuffDescrip = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; } else { /* Drop frame if there's no new buffer memory */ /* Free the incomplete frame buffers. */ while (index-- != 0U) { handle->rxBuffFree(base, &rxFrame->rxBuffArray[index].buffer, handle->userData, ringId); } /* Update left buffers as ready for next coming frame */ do { /* The last buffer descriptor of a frame. */ if (0U != (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK)) { isLastBuff = true; } /* Clears status including the owner flag. */ curBuffDescrip->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; /* Sets the receive buffer descriptor with the empty flag. */ curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; /* Increase current buffer descriptor to the next one. */ rxBdRing->rxGenIdx = ENET_IncreaseIndex(rxBdRing->rxGenIdx, rxBdRing->rxRingLen); curBuffDescrip = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; } while (!isLastBuff); result = kStatus_ENET_RxFrameDrop; break; } } while (!isLastBuff); ENET_ActiveReadRing(base, ringId); return result; }