298 lines
9.0 KiB
C++
298 lines
9.0 KiB
C++
/*
|
||
* 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;
|
||
}
|