/* * 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 #include #include #include /*----------------------------------------------------------------------*/ /** * ����� ������������ sysconfig. * ������������ ����� ������� � ���������� � ����� /syscfg */ #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]; } core_id_ = EnetSoc_getCoreId(); host_ready_ = false; eth_stack_.init(sett.eth_stack_sett); return true; } /// Callback ���������� ������ ioctl 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_MacPort macPort; Enet_IoctlPrms prms; IcssgMacPort_SetPortStateInArgs setPortStateInArgs; int32_t status = ENET_SOK; while(1) { for (int i = 0; i < macPortNum_; ++i) { if(linkUp_[i] == true) { continue; } macPort = macPort_[i]; linkUp = false; ENET_IOCTL_SET_INOUT_ARGS(&prms, &macPort, &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), 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), linkUp ? "up" : "down"); if (linkUp) { EnetAppUtils_print("link_task: %s: Set port state to 'Forward'\r\n", name_.c_str()); setPortStateInArgs.macPort = macPort; 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; } /// ����� �������� ������ ����(����� SWITCH) if (!tx_flow_.open(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(i, ENET_DMA_RX_CH0 + i)) { EnetAppUtils_print("link_task: %s: Failed to open rx flow: %u\n", name_.c_str(), i); continue; } /// e_ethMac0 if (i == e_ethMac0) { if (!host_init()) { EnetAppUtils_print("link_task: %s: Failed to init host\r\n", name_.c_str()); continue; } } else if (i == e_ethMac1) { //rx_flow_[i].set_passive(); /// ���� � �������� ���������� �� - ���������, �� ������������ ������ } tx_flow_.enable((TEthMacPorts)i); } else { tx_flow_.disable((TEthMacPorts)i); } linkUp_[i] = linkUp; } } ClockP_usleep(1000000); // 100ms /// ������ 10�� ���������� ��������� ����� } } 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; }