/* * 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; EnetDma_Pkt* rxPktInfo; EnetDma_PktQ rxReadyQ; uint32_t readyQCount; int32_t status; if(rx_flow == nullptr) { return; } //status = EnetDma_retrieveRxPktQ(rx_flow->dma_handle_, &rxReadyQ); //EnetAppUtils_assert(status == ENET_SOK); // Shortcut. Requires access to private header enet_udma_priv.h EnetQueue_initQ(&rxReadyQ); EnetQueue_append(&rxReadyQ, &rx_flow->dma_handle_->cqIsrQ); EnetQueue_initQ(&rx_flow->dma_handle_->cqIsrQ); readyQCount = EnetQueue_getQCount(&rxReadyQ); // Reload DMA with a new rx free queue as fast as possible rx_flow->submitFreeRxPkts(readyQCount); //EnetQueue_append(&rx_flow->rx_ready_pktq_, &rxReadyQ); //rx_flow->sem_[EthRxFlow::e_signalRxPkt].post(); rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ); while(rxPktInfo != nullptr) { /// � ��������� ������ �������� ������ �� ������������ if (!rx_flow->passive_mode_) { /// � ����� ������ ����� ���� ��������� ��������� for (int j = 0 ; j < rxPktInfo->sgList.numScatterSegments; ++j) { rx_flow->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(&rx_flow->rx_free_pktq_, &rxPktInfo->node); /// ��������� ��������� ���� �� ������� rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ); /// ����������� ������� �������� ������� ++rx_flow->rx_pkt_counter_; } } 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_); EnetQueue_initQ(&rx_ready_pktq_); } void free_rtos::EthRxFlow::initRxFreePktQ(uint32_t qCount, void * appPriv) { 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(&rx_free_pktq_, &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((rxPktInfo != nullptr) && (qCount > 0)) { 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); if(status != ENET_SOK) { EnetAppUtils_print("rx_flow %u: failed to reload rx dma flow\r\n", id_); EnetAppUtils_assert(status == ENET_SOK); return; } 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 */ if(qCount != 0U) { EnetAppUtils_print("rx_flow %u: number of DMA descriptors should be equal to the number of free Ethernet buffers\r\n", id_); EnetAppUtils_assert(qCount == 0U); } } void free_rtos::EthRxFlow::rxProcessPktTask() { EnetDma_Pkt* rxPktInfo; /// ����� � ������� EnetDma_PktQ rxReadyQ; uint32_t readyQCount; int32_t status; while(1) { /// ������� ������� status = sem_[e_signalRxPkt].pend(e_signalRxPkt_timeout_ticks_); if(status != SystemP_SUCCESS) { //EnetAppUtils_print("rx_flow %u: Warning ! No rx packets timeout.\r\n", id_); continue; } /* status = EnetDma_retrieveRxPktQ(dma_handle_, &rxReadyQ); EnetAppUtils_assert(status == ENET_SOK); readyQCount = EnetQueue_getQCount(&rxReadyQ); if(readyQCount == 0) { continue; } // Reload DMA with a new rx free queue as fast as possible submitFreeRxPkts(readyQCount); EnetQueue_append(&rx_ready_pktq_, &rxReadyQ); */ 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(&rx_free_pktq_, &rxPktInfo->node); /// ��������� ��������� ���� �� ������� rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rx_ready_pktq_); /// ����������� ������� �������� ������� ++rx_pkt_counter_; } } } 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; 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", task_priority, rxTaskHandler, this, 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; } /// ������������� ������� ������� initRxFreePktQ(ENET_SYSCFG_TOTAL_NUM_RX_PKT/2, this); submitFreeRxPkts(ENET_SYSCFG_TOTAL_NUM_RX_PKT/4); open_ = true; EnetAppUtils_print("rx_flow %u: rx flow open successfully\r\n", id); return true; }