sitara_depot/components/free_rtos/ethernet/eth.cpp

298 lines
9.0 KiB
C++
Raw Normal View History

/*
* eth.cpp
*
* Created on: 9 мар. 2023 г.
* Author: sychev
*/
#include "free_rtos/ethernet/eth.hpp"
#include "free_rtos/ethernet/eth_vlan.h"
#include "free_rtos/ethernet/eth_ioctl.h"
#include <networking/enet/core/include/core/enet_ioctl.h>
#include <kernel/dpl/DebugP.h>
#include <kernel/dpl/ClockP.h>
#include <cstring>
/*----------------------------------------------------------------------*/
#include "ti_enet_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "ti_enet_open_close.h"
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------*/
using namespace free_rtos;
free_rtos::Eth::Eth() :
rx_flow_{{hostMacAddr_, eth_stack_}, {hostMacAddr_, eth_stack_}},
sem_{Semaphore(Semaphore::e_semTypeCounting, 0, 10)},
eth_stack_{tx_flow_}
{
}
bool free_rtos::Eth::Init(Settings& sett)
{
id_ = sett.id;
name_ = sett.name;
enetType_ = sett.enetType;
instId_ = sett.instId;
macPortNum_ = sett.macPortNum;
vlan_id_ = sett.vlan_id;
if (instId_ != e_ethInstSwitch) {
EnetAppUtils_print("%s: Unsupported instId value: %u. Only %d(e_ethInstSwitch) instance id supported\r\n", name_.c_str(), instId_, e_ethInstSwitch);
return false;
}
if (enetType_ != ENET_ICSSG_SWITCH) {
EnetAppUtils_print("%s: Unsupported enetType value: %u. Only %d(ENET_ICSSG_SWITCH) enet type supported\r\n", name_.c_str(), enetType_, ENET_ICSSG_SWITCH);
return false;
}
if (sett.macPortNum != e_ethMacTotal) {
EnetAppUtils_print("%s: Invalid mac port number: %u. In SWITCH mode mac port number must be 2, current value: %u\r\n", name_.c_str(), macPortNum_);
return false;
}
for (int i = 0; i < macPortNum_; ++i) {
linkUp_[i] = false;
macPort_[i] = sett.macPort[i];
rxTaskPriority_[i] = sett.rxTaskPriority[i];
rxTaskStackSize_[i] = sett.rxTaskStackSize[i];
}
core_id_ = EnetSoc_getCoreId();
host_ready_ = false;
eth_stack_.init(sett.eth_stack_sett);
return true;
}
static void eth_asyncIoctlCb(Enet_Event evt,
uint32_t evtNum,
void *evtCbArgs,
void *arg1,
void *arg2)
{
Eth * eth = (Eth *)evtCbArgs;
if (eth != nullptr) {
eth->ioctl_callback();
}
}
void free_rtos::Eth::ioctl_callback()
{
sem_[e_signalIoctl].post();
}
static void eth_taskLinkTracking(void *args) {
Eth * eth = (Eth *)args;
if (eth != nullptr) {
eth->link_task();
}
}
bool free_rtos::Eth::host_init()
{
if (host_ready_) {
return true;
}
Enet_IoctlPrms prms;
int32_t status = ENET_SOK;
uint16_t vlanId = (uint16_t)vlan_id_;
if (enetType_ != ENET_ICSSG_SWITCH)
{
EnetAppUtils_print("%s: unsupported enet type: %u. Only %u(ENET_ICSSG_SWITCH) type supported\n\r",
name_.c_str(), enetType_, ENET_ICSSG_SWITCH);
return false;
}
EnetAppUtils_print("%s: Host initialisation\n\r", name_.c_str());
EnetAppUtils_print("%s: Set MAC addr: ", name_.c_str());
EnetAppUtils_printMacAddr(&hostMacAddr_.bytes[0U]);
Icssg_MacAddr addr; // FIXME Icssg_MacAddr type
/* Set host port's MAC address */
EnetUtils_copyMacAddr(&addr.macAddr[0U], &hostMacAddr_.bytes[0U]);
ENET_IOCTL_SET_IN_ARGS(&prms, &addr);
status = eth_ioctl(handleInfo_.hEnet, core_id_, ICSSG_HOSTPORT_IOCTL_SET_MACADDR, &prms);
if (ENET_SOK != status)
{
EnetAppUtils_print("%s: ERROR: Host initialisation failure\n\r", name_.c_str());
return false;
}
status = eth_vlan_init(handleInfo_.hEnet, core_id_, vlanId, enetType_);
if (ENET_SOK != status)
{
EnetAppUtils_print("%s: ERROR: Host initialisation failure\n\r", name_.c_str());
return false;
}
host_ready_ = true;
return true;
}
void free_rtos::Eth::link_task()
{
bool linkUp;
Enet_IoctlPrms prms;
IcssgMacPort_SetPortStateInArgs setPortStateInArgs;
int32_t status = ENET_SOK;
while(1)
{
for (int i = 0; i < macPortNum_; ++i)
{
linkUp = false;
ENET_IOCTL_SET_INOUT_ARGS(&prms, &macPort_[i], &linkUp);
status = eth_ioctl(handleInfo_.hEnet, core_id_, ENET_PER_IOCTL_IS_PORT_LINK_UP, &prms);
if (status != ENET_SOK)
{
EnetAppUtils_print("link_task: %s: Failed to get port %u link status: %d\r\n",
name_.c_str(), ENET_MACPORT_ID(macPort_[i]), status);
linkUp = false;
continue;
}
if (linkUp_[i] != linkUp)
{
EnetAppUtils_print("link_task: %s: Port %u link is %s\r\n",
name_.c_str(), ENET_MACPORT_ID(macPort_[i]), linkUp ? "up" : "down");
if (linkUp)
{
EnetAppUtils_print("link_task: %s: Set port state to 'Forward'\r\n", name_.c_str());
setPortStateInArgs.macPort = macPort_[i];
setPortStateInArgs.portState = ICSSG_PORT_STATE_FORWARD;
ENET_IOCTL_SET_IN_ARGS(&prms, &setPortStateInArgs);
status = eth_ioctl(handleInfo_.hEnet, core_id_, ICSSG_PER_IOCTL_SET_PORT_STATE, &prms);
if (status == ENET_SINPROGRESS)
{
/* Wait for asyc ioctl to complete */
do
{
Enet_poll(handleInfo_.hEnet, ENET_EVT_ASYNC_CMD_RESP, NULL, 0U);
status = sem_[e_signalIoctl].pend();
} while(status != SystemP_SUCCESS);
status = ENET_SOK;
}
else
{
EnetAppUtils_print("link_task: %s: Failed to set port state: %d\n", name_.c_str(), status);
continue;
}
if (!tx_flow_.open((TEthMacPorts)macPort_[i], ENET_DMA_TX_CH0))
{
EnetAppUtils_print("link_task: %s: Failed to open tx flow\n", name_.c_str());
continue;
}
if (!rx_flow_[i].open((TEthMacPorts)macPort_[i], ENET_DMA_RX_CH0 + i, rxTaskPriority_[i], rxTaskStackSize_[i]))
{
EnetAppUtils_print("link_task: %s: Failed to open rx flow: %u\n", name_.c_str(), i);
continue;
}
/// e_ethMac0
if (macPort_[i] == ENET_MAC_PORT_1)
{
if (!host_init()) {
EnetAppUtils_print("link_task: %s: Failed to init host\r\n", name_.c_str());
continue;
}
}
else if (macPort_[i] == ENET_MAC_PORT_2) {
//rx_flow_[i].set_passive();
}
tx_flow_.enable((TEthMacPorts)macPort_[i]);
}
else {
tx_flow_.disable((TEthMacPorts)macPort_[i]);
}
linkUp_[i] = linkUp;
}
}
ClockP_usleep(100000); // 100ms
}
}
bool free_rtos::Eth::Open()
{
int32_t status;
EnetAppUtils_print("%s: Init peripheral clocks\r\n", name_.c_str());
EnetAppUtils_enableClocks(enetType_, instId_);
EnetAppUtils_print("%s: Open enet driver\r\n", name_.c_str());
status = EnetApp_driverOpen(enetType_, instId_);
if (ENET_SOK != status) {
EnetAppUtils_print("%s: fail to open enet driver\r\n", name_.c_str());
return false;
}
EnetAppUtils_print("%s: Init handle info\r\n", name_.c_str());
EnetApp_acquireHandleInfo(enetType_, instId_, &handleInfo_);
EnetAppUtils_print("%s: Open peripherals\r\n", name_.c_str());
if (Enet_isIcssFamily(enetType_))
{
EnetAppUtils_print("%s: Register async IOCTL callback\r\n", name_.c_str());
Enet_registerEventCb(handleInfo_.hEnet,
ENET_EVT_ASYNC_CMD_RESP,
0U,
eth_asyncIoctlCb,
(void *)this);
}
else {
EnetAppUtils_print("Error: the %s subsystem doesn't relates to Icss family\r\n", name_.c_str());
return false;
}
EnetAppUtils_print("%s: Attach core id %u on peripherals\r\n", name_.c_str(), core_id_);
EnetApp_coreAttach(enetType_, instId_, core_id_, &attachInfo_);
EnetAppUtils_print("%s: Create link tracking tasks\r\n", name_.c_str());
if (!task_[e_taskLink].Create("LinkTask", LINK_TASK_PRIORITY, eth_taskLinkTracking, (void*)this, LINK_TASK_STACK_SIZE))
{
EnetAppUtils_print("%s: Failed to create link task\r\n", name_.c_str());
return false;
}
return true;
}