/* * eth_rx_flow.cpp * * Created on: 7 ���. 2023 �. * Author: sychev */ #include "free_rtos/ethernet/eth_rx_flow.hpp" #include #include #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) { 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(); } } static void eth_initRxReadyPktQ(EnetDma_RxChHandle hRxCh, void * appPriv) { EnetDma_PktQ rxReadyQ; EnetDma_PktQ rxFreeQ; EnetDma_Pkt *pPktInfo; uint32_t i; int32_t status; EnetQueue_initQ(&rxFreeQ); for (i = 0U; i < (ENET_SYSCFG_TOTAL_NUM_RX_PKT/2); ++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(&rxFreeQ, &pPktInfo->node); } /* Retrieve any packets which are ready */ EnetQueue_initQ(&rxReadyQ); status = EnetDma_retrieveRxPktQ(hRxCh, &rxReadyQ); EnetAppUtils_assert(status == ENET_SOK); /* There should not be any packet with DMA during init */ EnetAppUtils_assert(EnetQueue_getQCount(&rxReadyQ) == 0U); EnetAppUtils_validatePacketState(&rxFreeQ, ENET_PKTSTATE_APP_WITH_FREEQ, ENET_PKTSTATE_APP_WITH_DRIVER); EnetDma_submitRxPktQ(hRxCh, &rxFreeQ); /* 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(EnetQueue_getQCount(&rxFreeQ) == 0U); } free_rtos::EthRxFlow::EthRxFlow(TEthFrameMacAddr& mac_addr, EthStackIface& eth_stack) : mac_addr_{mac_addr}, eth_stack_{eth_stack}, passive_mode_{false} { } void free_rtos::EthRxFlow::rxProcessPktTask() { EnetDma_PktQ rxReadyQ; /// ������� ������� ������� (������ � �������) EnetDma_PktQ rxFreeQ; /// ������� ��������� ������� EnetDma_Pkt* rxPktInfo; /// ����� � ������� int32_t status; while(1) { /// ������� ������� sem_[e_signalRxPkt].pend(); /// �������������� ������� (�������� ���� ��������) EnetQueue_initQ(&rxReadyQ); EnetQueue_initQ(&rxFreeQ); /// ��������� ������� � � �������� � rxReadyQ status = EnetDma_retrieveRxPktQ(dma_handle_, &rxReadyQ); EnetAppUtils_assert(status == ENET_SOK); // ��������� ����� �� ������� 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); } } /// �������� ��������� ������ �� ��������. ����� ����������� � ������������� ����� ��������. 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(&rxReadyQ); /// ����������� ������� �������� ������� ++rx_pkt_counter_; } /** * ��������� ��������� ���� ������� � �������(������ ���� ENET_PKTSTATE_APP_WITH_FREEQ) * � �������� ��� �� ENET_PKTSTATE_APP_WITH_DRIVER. �������� ����� �� ������ ��� ���� * ���� ������� ����� ������� EnetDma_checkPktState. */ EnetAppUtils_validatePacketState(&rxFreeQ, ENET_PKTSTATE_APP_WITH_FREEQ, ENET_PKTSTATE_APP_WITH_DRIVER); /// ���������� ������� � ������� EnetDma_submitRxPktQ(dma_handle_, &rxFreeQ); } } bool free_rtos::EthRxFlow::open(uint32_t id, int32_t enetDmaRxChId) { EnetApp_GetDmaHandleInArgs rxInArgs; EnetApp_GetRxDmaHandleOutArgs rxChInfo; EnetAppUtils_print("rx_flow %u: opening flow...\r\n", id); rx_pkt_counter_ = 0; 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", RX_TASK_PRIORITY, rxTaskHandler, this, RX_TASK_STACK_SIZE)) { EnetAppUtils_print("rx_flow %u: failed to create rx task.\r\n", id_); return false; } id_ = id; /// ������������ ���������� �� ������ ������ 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 >= (ENET_SYSCFG_TOTAL_NUM_RX_PKT/2U)); 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; } /// ������������� ������� ������� eth_initRxReadyPktQ(dma_handle_, this); open_ = true; EnetAppUtils_print("rx_flow %u: rx flow open successfully\r\n", id); return true; }