/* * eth_rx_flow.cpp * * Created on: 7 мар. 2023 г. * Author: sychev */ #include "free_rtos/ethernet/eth_rx_flow.hpp" #include #include // Yes, it is forbidden ! #include #include #include #include /*----------------------------------------------------------------------*/ #include "ti_enet_config.h" /*----------------------------------------------------------------------*/ using namespace free_rtos; void free_rtos::rxIsrHandler(void *appData) { EthRxFlow * rx_flow = (EthRxFlow *)appData; if(rx_flow == nullptr) { return; } rx_flow->retrieveReadyRxPktQ(); rx_flow->sem_[EthRxFlow::e_signalRxPkt].post(); } void free_rtos::rxTaskHandler(void *appData) { EthRxFlow * rx_flow = (EthRxFlow *)appData; if (rx_flow != nullptr) { rx_flow->rxProcessPktTask(); } } free_rtos::EthRxFlow::EthRxFlow(TEthFrameMacAddr& mac_addr, EthStackIface& eth_stack) : mac_addr_{mac_addr}, eth_stack_{eth_stack}, passive_mode_{false} { EnetQueue_initQ(&rx_ready_pktq_); } void free_rtos::EthRxFlow::initRxFreePktQ(void * appPriv, EnetDma_PktQ * p_packet_queue, uint32_t qCount) { EnetDma_PktQ rxReadyQ; EnetDma_Pkt *pPktInfo; uint32_t i; int32_t status; uint32_t scatterSegmentSize[1] = {ENET_MEM_LARGE_POOL_PKT_SIZE}; for (i = 0U; i < qCount; ++i) { pPktInfo = EnetMem_allocEthPkt(appPriv, ENETDMA_CACHELINE_ALIGNMENT, 1, scatterSegmentSize); EnetAppUtils_assert(pPktInfo != NULL); ENET_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState, ENET_PKTSTATE_APP_WITH_FREEQ); EnetQueue_enq(p_packet_queue, &pPktInfo->node); } /* Retrieve any packets which are ready */ EnetQueue_initQ(&rxReadyQ); status = EnetDma_retrieveRxPktQ(dma_handle_, &rxReadyQ); EnetAppUtils_assert(status == ENET_SOK); /* There should not be any packet with DMA during init */ EnetAppUtils_assert(EnetQueue_getQCount(&rxReadyQ) == 0U); } void free_rtos::EthRxFlow::retrieveReadyRxPktQ() { int32_t status = EnetDma_retrieveRxPktQ(dma_handle_, &rx_ready_pktq_); EnetAppUtils_assert(status == ENET_SOK); } void free_rtos::EthRxFlow::submitFreeRxPktQ(EnetDma_PktQ * p_packet_queue) { int32_t status; uint32_t qCount; EnetAppUtils_validatePacketState(p_packet_queue, ENET_PKTSTATE_APP_WITH_FREEQ, ENET_PKTSTATE_APP_WITH_DRIVER); status = EnetDma_submitRxPktQ(dma_handle_, p_packet_queue); EnetAppUtils_assert(status == ENET_SOK); qCount = EnetQueue_getQCount(p_packet_queue); /* Assert here, as during init, the number of DMA descriptors should be equal to * the number of free Ethernet buffers available with app */ EnetAppUtils_assert(qCount == 0U); } void free_rtos::EthRxFlow::rxProcessPktTask() { EnetDma_Pkt* rxPktInfo; EnetDma_PktQ rxFreeQ; int32_t status; while(1) { status = sem_[e_signalRxPkt].pend(); if(status != SystemP_SUCCESS) { continue; } EnetQueue_initQ(&rxFreeQ); rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rx_ready_pktq_); while(rxPktInfo != nullptr) { //if (!passive_mode_) { for (int j = 0 ; j < rxPktInfo->sgList.numScatterSegments; ++j) { eth_stack_.rx_handler(rxPktInfo->sgList.list[j].bufPtr, rxPktInfo->sgList.list[j].segmentFilledLen); } //} EnetDma_checkPktState( &rxPktInfo->pktState, ENET_PKTSTATE_MODULE_APP, ENET_PKTSTATE_APP_WITH_DRIVER, ENET_PKTSTATE_APP_WITH_FREEQ); EnetQueue_enq(&rxFreeQ, &rxPktInfo->node); rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rx_ready_pktq_); } submitFreeRxPktQ(&rxFreeQ); } } bool free_rtos::EthRxFlow::open(TEthMacPorts port_id, int32_t enetDmaRxChId, UBaseType_t task_priority, UBaseType_t task_stack_size) { EnetApp_GetDmaHandleInArgs rxInArgs; EnetApp_GetRxDmaHandleOutArgs rxChInfo; constexpr uint32_t numPkts[2] = {ENET_DMA_RX_CH0_NUM_PKTS, ENET_DMA_RX_CH1_NUM_PKTS}; EnetAppUtils_print("rx_flow %u: opening flow...\r\n", port_id); if (open_) { EnetAppUtils_print("rx_flow %u: rx flow is already open. Do nothing.\r\n", port_id); return true; } if (!rx_task.Create("rx_task", task_priority, rxTaskHandler, this, task_stack_size)) { EnetAppUtils_print("rx_flow %u: failed to create rx task.\r\n", port_id); return false; } default_port_id_ = port_id; enetDmaRxChId_ = enetDmaRxChId; // Регистрация обработчика прерывания модуля DMA rxInArgs.notifyCb = rxIsrHandler; rxInArgs.cbArg = this; EnetApp_getRxDmaHandle(enetDmaRxChId, &rxInArgs, &rxChInfo); rx_start_flow_idx_ = rxChInfo.rxFlowStartIdx; rx_flow_idx_ = rxChInfo.rxFlowIdx; dma_handle_ = rxChInfo.hRxCh; if (rxChInfo.numValidMacAddress != 0) { EnetUtils_copyMacAddr(mac_addr_.bytes, rxChInfo.macAddr[0]); mac_addr_.addr&= ETH_FRAME_MAC_ADDR_MASK; eth_stack_.set_mac_address(mac_addr_.addr); } EnetAppUtils_assert(rxChInfo.useGlobalEvt == true); EnetAppUtils_assert(rxChInfo.sizeThreshEn == 0U); EnetAppUtils_assert(rxChInfo.maxNumRxPkts >= numPkts[enetDmaRxChId]); EnetAppUtils_assert(rxChInfo.chIdx == port_id); if (dma_handle_ == nullptr) { EnetAppUtils_print("rx_flow %u: failed to open rx dma flow\r\n", port_id); EnetAppUtils_assert(dma_handle_ != nullptr); return false; } EnetDma_PktQ rxFreeQ; EnetQueue_initQ(&rxFreeQ); initRxFreePktQ(this, &rxFreeQ, numPkts[enetDmaRxChId]); submitFreeRxPktQ(&rxFreeQ); open_ = true; EnetAppUtils_print("rx_flow %u: rx flow open successfully\r\n", port_id); return true; }