/* * 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 /*----------------------------------------------------------------------*/ /** * ����� ������������ sysconfig. * ������������ ����� ������� � ���������� � ����� /syscfg */ #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->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_free_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; for (i = 0U; i < qCount; ++i) { pPktInfo = EnetMem_allocEthPkt(appPriv, ENET_MEM_LARGE_POOL_PKT_SIZE, ENETDMA_CACHELINE_ALIGNMENT); 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::submitFreeRxPkts(uint32_t qCount) { EnetDma_PktQ rxSubmitQ; EnetDma_Pkt* rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rx_free_pktq_); int32_t status; EnetQueue_initQ(&rxSubmitQ); while((qCount > 0) && (rxPktInfo != nullptr)) { EnetQueue_enq(&rxSubmitQ, &rxPktInfo->node); rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rx_free_pktq_); qCount--; } EnetAppUtils_validatePacketState(&rxSubmitQ, ENET_PKTSTATE_APP_WITH_FREEQ, ENET_PKTSTATE_APP_WITH_DRIVER); status = EnetDma_submitRxPktQ(dma_handle_, &rxSubmitQ); EnetAppUtils_assert(status == ENET_SOK); qCount = EnetQueue_getQCount(&rxSubmitQ); /* 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 rxReadyQ; uint32_t readyQCount; int32_t status; while(1) { if(enetDmaRxChId_ != ENET_DMA_RX_CH0) { status = sem_[e_signalRxPkt].pend(); } else { status = sem_[e_signalRxPkt].pend(semaphore_timeout_ticks_); } if(status != SystemP_SUCCESS) { EnetAppUtils_print("RX Timeout "); continue; } do { EnetDma_PktQ rxFreeQ; EnetQueue_initQ(&rxFreeQ); status = EnetDma_retrieveRxPktQ(dma_handle_, &rxReadyQ); EnetAppUtils_assert(status == ENET_SOK); readyQCount = EnetQueue_getQCount(&rxReadyQ); if(readyQCount == 0) { break; } // Reload DMA with a new rx free queue as fast as possible submitFreeRxPkts(readyQCount); rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ); 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); } //} EnetQueue_enq(&rxFreeQ, &rxPktInfo->node); rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ); } EnetAppUtils_validatePacketState(&rxFreeQ, ENET_PKTSTATE_APP_WITH_DRIVER, ENET_PKTSTATE_APP_WITH_FREEQ); EnetQueue_append(&rx_free_pktq_, &rxFreeQ); } while(readyQCount > 0); } } bool free_rtos::EthRxFlow::open(uint32_t 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", id); if (open_) { EnetAppUtils_print("rx_flow %u: rx flow is already open. Do nothing.\r\n", 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", id_); return false; } id_ = id; enetDmaRxChId_ = enetDmaRxChId; /// ������������ ���������� �� ������ ������ 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.macAddressValid) { EnetUtils_copyMacAddr(mac_addr_.bytes, rxChInfo.macAddr); 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 == id_); EnetAppUtils_assert(rxChInfo.useDefaultFlow == true); if (dma_handle_ == nullptr) { EnetAppUtils_print("rx_flow %u: failed to open rx dma flow\r\n", id_); EnetAppUtils_assert(dma_handle_ != nullptr); return false; } /// ������������� ������� ������� initRxFreePktQ(this, &rx_free_pktq_, numPkts[enetDmaRxChId]); submitFreeRxPkts(numPkts[enetDmaRxChId]/2); open_ = true; EnetAppUtils_print("rx_flow %u: rx flow open successfully\r\n", id); return true; }