sitara_depot/components/free_rtos/ethernet/eth.cpp

300 lines
9.0 KiB
C++
Raw Permalink 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.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());
EnetApp_driverInit();
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;
}