sitara_depot/components/free_rtos/ethernet/eth_rx_flow.cpp

211 lines
6.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* eth_rx_flow.cpp
*
* Created on: 7 мар. 2023 г.
* Author: sychev
*/
#include "free_rtos/ethernet/eth_rx_flow.hpp"
#include <networking/enet/core/include/core/enet_soc.h>
#include <networking/enet/core/src/dma/udma/enet_udma_priv.h> // Yes, it is forbidden !
#include <networking/enet/utils/include/enet_board.h>
#include <networking/enet/utils/include/enet_appmemutils.h>
#include <networking/enet/utils/include/enet_appmemutils_cfg.h>
#include <networking/enet/utils/include/enet_apputils.h>
/*----------------------------------------------------------------------*/
#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;
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::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.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 == port_id);
EnetAppUtils_assert(rxChInfo.useDefaultFlow == true);
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;
}