feat: First commit
Adds sitara_depot/free_rtos Original one is on server_gorbunov/SmartForce4.0/sitara_depot
This commit is contained in:
parent
52f8c89ec4
commit
ae3cac8a7d
@ -1,2 +1,3 @@
|
||||
# sitara_depot
|
||||
|
||||
Хранилище программных модулей для процессора Sitara AM64x
|
||||
|
||||
15
components/free_rtos/base/swap.h
Normal file
15
components/free_rtos/base/swap.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* swap.h
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_BASE_SWAP_H_
|
||||
#define FREE_RTOS_BASE_SWAP_H_
|
||||
|
||||
#define BASE_SWAP32(value) __builtin_bswap32(value)
|
||||
|
||||
#define BASE_SWAP16(value) (uint16_t)__builtin_bswap16(value)
|
||||
|
||||
#endif /* FREE_RTOS_BASE_SWAP_H_ */
|
||||
37
components/free_rtos/clock/clock.cpp
Normal file
37
components/free_rtos/clock/clock.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* clock.cpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "clock/clock.hpp"
|
||||
|
||||
bool free_rtos::Clock::init(uint32_t period_ms, Callback cbk, void * arg)
|
||||
{
|
||||
ClockP_Params clockParams;
|
||||
ClockP_Params_init(&clockParams);
|
||||
|
||||
prd_ms_ = period_ms;
|
||||
|
||||
clockParams.timeout = ClockP_usecToTicks(prd_ms_ * 1000);
|
||||
clockParams.period = clockParams.timeout;
|
||||
clockParams.callback = cbk;
|
||||
clockParams.args = arg;
|
||||
|
||||
int32_t status = ClockP_construct(&obj_, &clockParams);
|
||||
|
||||
return (SystemP_SUCCESS == status);
|
||||
}
|
||||
|
||||
|
||||
void free_rtos::Clock::start() {
|
||||
ClockP_start(&obj_);
|
||||
}
|
||||
|
||||
void free_rtos::Clock::stop() {
|
||||
ClockP_stop(&obj_);
|
||||
}
|
||||
|
||||
free_rtos::Clock::~Clock() {
|
||||
ClockP_destruct (&obj_);
|
||||
}
|
||||
39
components/free_rtos/clock/clock.hpp
Normal file
39
components/free_rtos/clock/clock.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* clock.hpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_CLOCK_CLOCK_HPP_
|
||||
#define FREE_RTOS_CLOCK_CLOCK_HPP_
|
||||
|
||||
#include <kernel/dpl/ClockP.h>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class Clock {
|
||||
public:
|
||||
using Callback = void(*)(ClockP_Object *,void *);
|
||||
|
||||
bool init(uint32_t period_ms, Callback cbk, void * arg);
|
||||
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
uint32_t getPeriod() {
|
||||
return prd_ms_;
|
||||
}
|
||||
|
||||
~Clock();
|
||||
private:
|
||||
ClockP_Object obj_;
|
||||
uint32_t prd_ms_; /// Ïåðèîä â ìñ
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_CLOCK_CLOCK_HPP_ */
|
||||
301
components/free_rtos/ethernet/eth.cpp
Normal file
301
components/free_rtos/ethernet/eth.cpp
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* eth.cpp
|
||||
*
|
||||
* Created on: 9 <EFBFBD><EFBFBD><EFBFBD>. 2023 <EFBFBD>.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet/eth.hpp"
|
||||
#include "ethernet/eth_vlan.h"
|
||||
#include "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>
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/**
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sysconfig.
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <build_name>/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 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD> 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(); /// <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
tx_flow_.enable((TEthMacPorts)i);
|
||||
}
|
||||
else {
|
||||
tx_flow_.disable((TEthMacPorts)i);
|
||||
}
|
||||
|
||||
linkUp_[i] = linkUp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ClockP_usleep(100000); // 100ms /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 10<31><30> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
}
|
||||
|
||||
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", e_linkTaskPriority, eth_taskLinkTracking, (void*)this, (10U * 1024U)))
|
||||
{
|
||||
EnetAppUtils_print("%s: Failed to create link task\r\n", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
139
components/free_rtos/ethernet/eth.hpp
Normal file
139
components/free_rtos/ethernet/eth.hpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* eth.hpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_HPP_
|
||||
#define FREE_RTOS_ETHERNET_ETH_HPP_
|
||||
|
||||
#include "ethernet/eth_rx_flow.hpp"
|
||||
#include "ethernet/eth_tx_flow.hpp"
|
||||
|
||||
#include "semaphore/semaphore.hpp"
|
||||
#include "ethernet/eth_frame.h"
|
||||
#include "task/task.hpp"
|
||||
|
||||
#include <networking/enet/core/include/core/enet_per.h>
|
||||
#include <networking/enet/utils/include/enet_apputils.h>
|
||||
#include <networking/enet/core/include/per/icssg.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "ethernet/eth_types.h"
|
||||
|
||||
#include "ethernet_ip/eth_stack.hpp"
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class Eth {
|
||||
public:
|
||||
typedef enum {
|
||||
e_ethInstSwitch = 1, /// Ïîääåðæèâàåòñÿ
|
||||
e_ethInstDualMac_1, /// Íå ïîääåðæèâàåòñÿ
|
||||
e_ethInstDualMac_2 /// Íå ïîääåðæèâàåòñÿ
|
||||
}TEthInstId;
|
||||
|
||||
struct Settings {
|
||||
uint32_t id; /// Èäåíòèôèêàòîð ïîðòà
|
||||
|
||||
/* Peripheral type */
|
||||
Enet_Type enetType;
|
||||
|
||||
/* Peripheral instance */
|
||||
TEthInstId instId;
|
||||
|
||||
/* Peripheral's MAC ports to use */
|
||||
Enet_MacPort macPort[e_ethMacTotal];
|
||||
|
||||
/* Number of MAC ports in macPorts array */
|
||||
uint32_t macPortNum;
|
||||
|
||||
/* Name of this port to be used for logging */
|
||||
std::string name;
|
||||
|
||||
uint32_t vlan_id;
|
||||
|
||||
EthStack::Settings eth_stack_sett;
|
||||
};
|
||||
|
||||
Eth();
|
||||
|
||||
bool Init(Settings& sett);
|
||||
|
||||
bool Open();
|
||||
|
||||
void ioctl_callback();
|
||||
|
||||
void link_task();
|
||||
|
||||
EthUdpServerIface * getUdpServerPtr() {return eth_stack_.getUdpServerPtr(); }
|
||||
|
||||
EthTxFlowIface * getTxFlowPtr() { return &tx_flow_; }
|
||||
|
||||
EthStackIface * getEthStackPtr() {return ð_stack_;}
|
||||
|
||||
private:
|
||||
enum TaskPriority {
|
||||
e_linkTaskPriority = 2
|
||||
};
|
||||
|
||||
bool host_init();
|
||||
|
||||
|
||||
private:
|
||||
enum SignalsId {
|
||||
e_signalIoctl, /// Çàâåðøåíèå ïåðåäà÷è ïî ioctl
|
||||
e_signalTotal
|
||||
};
|
||||
|
||||
enum TasksId {
|
||||
e_taskLink,
|
||||
e_taskTotal
|
||||
};
|
||||
|
||||
uint32_t id_; /// Èäåíòèôèêàòîð ïîðòà
|
||||
std::string name_; /// Èìÿ ïîðòà
|
||||
|
||||
uint32_t core_id_; /// Èäåíòèôèêàòîð ÿäðà
|
||||
|
||||
Enet_Type enetType_; /// Òèï ïîðòà
|
||||
|
||||
/// Èäåíòèôèêàòîð ïåðèôåðèè mac: 1 - äëÿ ðåæèìà SWITCH, 2 è 3 äëÿ ðåæèìà DUAL MAC ( äëÿ mac1 è mac2 ñîîòâåòñòâåííî)
|
||||
uint32_t instId_;
|
||||
|
||||
/// Èäåíòèôèêàòîðû mac ïîðòîâ
|
||||
Enet_MacPort macPort_[e_ethMacTotal];
|
||||
|
||||
/// Êîëè÷åñòâî MAC ïîðòîâ
|
||||
uint32_t macPortNum_;
|
||||
|
||||
/// Îñíîâíàÿ èíôîðìàöèÿ î ïîäêëþ÷åíèè äëÿ ïåðèôåðèéíîãî óñòðîéñòâà ????
|
||||
EnetPer_AttachCoreOutArgs attachInfo_;
|
||||
|
||||
/// Enet è Udma îáðàáîò÷èê èíôîðìàöèè äëÿ ïåðèôåðèéíîãî óñòðîéñòâà.
|
||||
EnetApp_HandleInfo handleInfo_;
|
||||
|
||||
EthTxFlow tx_flow_; ///
|
||||
EthRxFlow rx_flow_[e_ethMacTotal]; /// Äâà ïîòîêà ïðèåìà â ðåæèìå SWITCH
|
||||
|
||||
Semaphore sem_[e_signalTotal];
|
||||
|
||||
Task task_[e_taskTotal];
|
||||
|
||||
bool linkUp_[e_ethMacTotal];
|
||||
|
||||
bool host_ready_;
|
||||
|
||||
TEthFrameMacAddr hostMacAddr_; /// ñîáñòâåííûé ìàê àäðåñ
|
||||
|
||||
uint32_t vlan_id_;
|
||||
|
||||
EthStack eth_stack_; /// Ñòåê ëîãè÷åñêèõ ïðîòîêîëîâ
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_HPP_ */
|
||||
40
components/free_rtos/ethernet/eth_frame.h
Normal file
40
components/free_rtos/ethernet/eth_frame.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* eth_frame.h
|
||||
*
|
||||
* Created on: 7 <EFBFBD><EFBFBD><EFBFBD>. 2023 <EFBFBD>.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_FRAME_H_
|
||||
#define FREE_RTOS_ETHERNET_ETH_FRAME_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ETH_FRAME_MAC_ADDR_LEN_BYTES (6u)
|
||||
|
||||
#define ETH_FRAME_MAC_ADDR_MASK (0xFFFFFFFFFFFFul) /// 6 <20><><EFBFBD><EFBFBD>
|
||||
|
||||
#define ETH_FRAME_MAC_ADDR_BROADCAST (0xFFFFFFFFFFFFul) /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
#define ETH_FRAME_MIN_LEN (14u) /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
#define ETH_FRAME_MAX_LEN (1518u) /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
typedef union {
|
||||
uint64_t addr;
|
||||
uint8_t bytes[8];
|
||||
} __attribute__ ((packed)) TEthFrameMacAddr;
|
||||
|
||||
typedef struct {
|
||||
uint8_t mac_dest[ETH_FRAME_MAC_ADDR_LEN_BYTES];
|
||||
uint8_t mac_src[ETH_FRAME_MAC_ADDR_LEN_BYTES];
|
||||
uint16_t prot_id;
|
||||
} __attribute__ ((packed)) TEthFrameHeader;
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[ETH_FRAME_MAX_LEN]; //__attribute__ ((aligned(32)))
|
||||
uint32_t length;
|
||||
}TEthPkt;
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_FRAME_H_ */
|
||||
41
components/free_rtos/ethernet/eth_ioctl.c
Normal file
41
components/free_rtos/ethernet/eth_ioctl.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* eth_ioctl.c
|
||||
*
|
||||
* Created on: 10 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet/eth_ioctl.h"
|
||||
|
||||
#include <networking/enet/core/include/per/icssg.h>
|
||||
|
||||
int32_t eth_ioctl(Enet_Handle handle, uint32_t core_id, uint32_t cmd, Enet_IoctlPrms * param)
|
||||
{
|
||||
int32_t status = ENET_SOK;
|
||||
/**
|
||||
* Åñëè íóæíû äðóãèå êîìàíäû, òî äîáàâèòü ñþäà.
|
||||
*/
|
||||
switch(cmd)
|
||||
{
|
||||
case ENET_PER_IOCTL_IS_PORT_LINK_UP:
|
||||
{
|
||||
ENET_IOCTL(handle, core_id, ENET_PER_IOCTL_IS_PORT_LINK_UP, param, status);
|
||||
}
|
||||
break;
|
||||
case ICSSG_PER_IOCTL_SET_PORT_STATE:
|
||||
{
|
||||
ENET_IOCTL(handle, core_id, ICSSG_PER_IOCTL_SET_PORT_STATE, param, status);
|
||||
}
|
||||
break;
|
||||
case ICSSG_HOSTPORT_IOCTL_SET_MACADDR:
|
||||
{
|
||||
ENET_IOCTL(handle, core_id, ICSSG_HOSTPORT_IOCTL_SET_MACADDR, param, status);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = ENET_EFAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
24
components/free_rtos/ethernet/eth_ioctl.h
Normal file
24
components/free_rtos/ethernet/eth_ioctl.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* eth_ioctl.h
|
||||
*
|
||||
* Created on: 10 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_IOCTL_H_
|
||||
#define FREE_RTOS_ETHERNET_ETH_IOCTL_H_
|
||||
|
||||
#include <networking/enet/core/include/core/enet_base.h>
|
||||
#include <networking/enet/core/include/core/enet_ioctl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t eth_ioctl(Enet_Handle handle, uint32_t core_id, uint32_t cmd, Enet_IoctlPrms * param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_IOCTL_H_ */
|
||||
227
components/free_rtos/ethernet/eth_rx_flow.cpp
Normal file
227
components/free_rtos/ethernet/eth_rx_flow.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* eth_rx_flow.cpp
|
||||
*
|
||||
* Created on: 7 <EFBFBD><EFBFBD><EFBFBD>. 2023 <EFBFBD>.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet/eth_rx_flow.hpp"
|
||||
|
||||
#include <networking/enet/core/include/core/enet_soc.h>
|
||||
#include <networking/enet/core/include/core/enet_queue.h>
|
||||
#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>
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/**
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sysconfig.
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <build_name>/syscfg
|
||||
*/
|
||||
#include "ti_enet_config.h"
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
using namespace free_rtos;
|
||||
|
||||
#define RX_TASK_STACK_SIZE (10U * 1024U) /// 10<31><30>
|
||||
|
||||
/**
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
void free_rtos::rxIsrHandler(void *appData)
|
||||
{
|
||||
EthRxFlow * rx_flow = (EthRxFlow *)appData;
|
||||
if (rx_flow != nullptr) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
static void eth_initRxReadyPktQ(EnetDma_RxChHandle hRxCh, void * appPriv)
|
||||
{
|
||||
EnetDma_PktQ rxReadyQ;
|
||||
EnetDma_PktQ rxFreeQ;
|
||||
EnetDma_Pkt *pPktInfo;
|
||||
uint32_t i;
|
||||
int32_t status;
|
||||
|
||||
EnetQueue_initQ(&rxFreeQ);
|
||||
|
||||
for (i = 0U; i < (ENET_SYSCFG_TOTAL_NUM_RX_PKT/2); ++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(&rxFreeQ, &pPktInfo->node);
|
||||
}
|
||||
|
||||
/* Retrieve any packets which are ready */
|
||||
EnetQueue_initQ(&rxReadyQ);
|
||||
status = EnetDma_retrieveRxPktQ(hRxCh, &rxReadyQ);
|
||||
EnetAppUtils_assert(status == ENET_SOK);
|
||||
|
||||
/* There should not be any packet with DMA during init */
|
||||
EnetAppUtils_assert(EnetQueue_getQCount(&rxReadyQ) == 0U);
|
||||
|
||||
EnetAppUtils_validatePacketState(&rxFreeQ,
|
||||
ENET_PKTSTATE_APP_WITH_FREEQ,
|
||||
ENET_PKTSTATE_APP_WITH_DRIVER);
|
||||
|
||||
EnetDma_submitRxPktQ(hRxCh, &rxFreeQ);
|
||||
|
||||
/* 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(EnetQueue_getQCount(&rxFreeQ) == 0U);
|
||||
}
|
||||
|
||||
free_rtos::EthRxFlow::EthRxFlow(TEthFrameMacAddr& mac_addr, EthStackIface& eth_stack) :
|
||||
mac_addr_{mac_addr},
|
||||
eth_stack_{eth_stack},
|
||||
passive_mode_{false}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void free_rtos::EthRxFlow::rxProcessPktTask()
|
||||
{
|
||||
EnetDma_PktQ rxReadyQ; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
EnetDma_PktQ rxFreeQ; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
EnetDma_Pkt* rxPktInfo; /// <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int32_t status;
|
||||
|
||||
while(1)
|
||||
{
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
sem_[e_signalRxPkt].pend();
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
EnetQueue_initQ(&rxReadyQ);
|
||||
EnetQueue_initQ(&rxFreeQ);
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> rxReadyQ
|
||||
status = EnetDma_retrieveRxPktQ(dma_handle_, &rxReadyQ);
|
||||
EnetAppUtils_assert(status == ENET_SOK);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ);
|
||||
|
||||
while(rxPktInfo != nullptr)
|
||||
{
|
||||
/// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (!passive_mode_)
|
||||
{
|
||||
/// <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
for (int j = 0 ; j < rxPktInfo->sgList.numScatterSegments; ++j)
|
||||
{
|
||||
eth_stack_.rx_handler(rxPktInfo->sgList.list[j].bufPtr, rxPktInfo->sgList.list[j].segmentFilledLen);
|
||||
}
|
||||
}
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
EnetDma_checkPktState(&rxPktInfo->pktState,
|
||||
ENET_PKTSTATE_MODULE_APP,
|
||||
ENET_PKTSTATE_APP_WITH_DRIVER,
|
||||
ENET_PKTSTATE_APP_WITH_FREEQ);
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
EnetQueue_enq(&rxFreeQ, &rxPktInfo->node);
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ);
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
++rx_pkt_counter_;
|
||||
}
|
||||
|
||||
/**
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD> ENET_PKTSTATE_APP_WITH_FREEQ)
|
||||
* <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> ENET_PKTSTATE_APP_WITH_DRIVER. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> EnetDma_checkPktState.
|
||||
*/
|
||||
EnetAppUtils_validatePacketState(&rxFreeQ,
|
||||
ENET_PKTSTATE_APP_WITH_FREEQ,
|
||||
ENET_PKTSTATE_APP_WITH_DRIVER);
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
EnetDma_submitRxPktQ(dma_handle_, &rxFreeQ);
|
||||
}
|
||||
}
|
||||
|
||||
bool free_rtos::EthRxFlow::open(uint32_t id, int32_t enetDmaRxChId)
|
||||
{
|
||||
EnetApp_GetDmaHandleInArgs rxInArgs;
|
||||
EnetApp_GetRxDmaHandleOutArgs rxChInfo;
|
||||
|
||||
EnetAppUtils_print("rx_flow %u: opening flow...\r\n", id);
|
||||
|
||||
rx_pkt_counter_ = 0;
|
||||
|
||||
if (open_) {
|
||||
EnetAppUtils_print("rx_flow %u: rx flow is already open. Do nothing.\r\n", id_);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!rx_task.Create("rx_task", Task::TaskPriorityHiest - 2, rxTaskHandler, this, RX_TASK_STACK_SIZE))
|
||||
{
|
||||
EnetAppUtils_print("rx_flow %u: failed to create rx task.\r\n", id_);
|
||||
return false;
|
||||
}
|
||||
|
||||
id_ = id;
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
rxInArgs.notifyCb = rxIsrHandler; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
rxInArgs.cbArg = this; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
EnetApp_getRxDmaHandle(enetDmaRxChId, &rxInArgs, &rxChInfo);
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
EnetAppUtils_assert(rxChInfo.useGlobalEvt == true);
|
||||
EnetAppUtils_assert(rxChInfo.sizeThreshEn == 0U);
|
||||
EnetAppUtils_assert(rxChInfo.maxNumRxPkts >= (ENET_SYSCFG_TOTAL_NUM_RX_PKT/2U));
|
||||
EnetAppUtils_assert(rxChInfo.chIdx == id_);
|
||||
EnetAppUtils_assert(rxChInfo.useDefaultFlow == true);
|
||||
|
||||
if (dma_handle_ == nullptr)
|
||||
{
|
||||
EnetAppUtils_print("rx_flow %u: failed to open rx dma flow\r\n", id_);
|
||||
EnetAppUtils_assert(dma_handle_ != nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
eth_initRxReadyPktQ(dma_handle_, this);
|
||||
|
||||
open_ = true;
|
||||
|
||||
EnetAppUtils_print("rx_flow %u: rx flow open successfully\r\n", id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
73
components/free_rtos/ethernet/eth_rx_flow.hpp
Normal file
73
components/free_rtos/ethernet/eth_rx_flow.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* eth_rx_dma.hpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_RX_DMA_HPP_
|
||||
#define FREE_RTOS_ETHERNET_ETH_RX_DMA_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <networking/enet/core/include/dma/udma/enet_udma.h>
|
||||
|
||||
#include "handler_store/handler_store.hpp"
|
||||
#include "semaphore/semaphore.hpp"
|
||||
#include "task/task.hpp"
|
||||
|
||||
#include "ethernet/eth_frame.h"
|
||||
#include "ethernet_ip/eth_stack_iface.hpp"
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthRxFlow {
|
||||
public:
|
||||
EthRxFlow(TEthFrameMacAddr& mac_addr, EthStackIface& eth_stack);
|
||||
|
||||
bool open(uint32_t id, int32_t enetDmaRxChId);
|
||||
|
||||
bool is_open() {return open_;}
|
||||
|
||||
void set_passive() { passive_mode_ = true; }
|
||||
|
||||
private:
|
||||
|
||||
friend void rxIsrHandler(void *appData); /// Îáðàáîò÷èê ïðåðûâàíèÿ ïî ïðèåìó
|
||||
|
||||
friend void rxTaskHandler(void *appData); ///Çàäà÷à îáðàáîòêè ïðèíÿòûõ ïàêåòîâ
|
||||
|
||||
void rxProcessPktTask(); ///Ôóíêöèÿ îáðàáîòêè ïðèíÿòûõ ïàêåòîâ
|
||||
|
||||
private:
|
||||
enum SignalsId {
|
||||
e_signalRxPkt, /// Ïðèåì ïàêåòà
|
||||
e_signalTotal
|
||||
};
|
||||
|
||||
uint32_t id_; /// Èäåíòèôèêàòîð êàíàëà
|
||||
bool open_; /// Ôëàã òîãî, ÷òî dma êàíàë óæå îòêðûò
|
||||
|
||||
Semaphore sem_[e_signalTotal]; /// Ñåìàôîðû ñîáûòèé
|
||||
|
||||
Task rx_task; /// Çàäà÷à ïðèåìà
|
||||
|
||||
TEthFrameMacAddr& mac_addr_; /// mac àäðåñ
|
||||
|
||||
uint32_t rx_pkt_counter_;
|
||||
|
||||
EthStackIface& eth_stack_;
|
||||
|
||||
///------------------------------------
|
||||
uint32_t rx_start_flow_idx_;
|
||||
uint32_t rx_flow_idx_;
|
||||
EnetDma_RxChHandle dma_handle_;
|
||||
|
||||
bool passive_mode_; /// Ïàññèâíûé ðåæèì, ïàêåòû ïðèíèìàþòñÿ, íî íå ïåðåäàþòñÿ â ñòåê îáðàáîòêè
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_RX_DMA_HPP_ */
|
||||
160
components/free_rtos/ethernet/eth_ti_enet_inst.c
Normal file
160
components/free_rtos/ethernet/eth_ti_enet_inst.c
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* app_enet_open_close.c
|
||||
*
|
||||
* Created on: 1 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
* Ôàéë ðåàëèçóåò ôóíêöèè îáúÿâëåííûå â ñãåíåðåííîì ôàéëå
|
||||
* ti_enet_open_close.h è âûçûâàåìûå â ñãåíåðåííîì ôàéëå ti_enet_open_close.ñ
|
||||
*/
|
||||
#include <utils/include/enet_board.h>
|
||||
#include <networking/enet/core/include/per/icssg.h>
|
||||
#include <networking/enet/utils/include/enet_apputils.h>
|
||||
|
||||
#define ETH_TYPES_MAC_PORT_MAX (2u) /// Êîëè÷åñòâî mac-ïîðòîâ
|
||||
|
||||
/// Ñãåíåðåííûå ôàéëû
|
||||
#include <ti_board_config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
static void eth_macMode2MacMii(emac_mode macMode, EnetMacPort_Interface *mii);
|
||||
|
||||
static int32_t eth_getSubsPortIdx(Enet_Type enetType, uint32_t instId, uint32_t *subsportIdx);
|
||||
|
||||
/*
|
||||
* Îáúÿâëåíà è èñïîëüçóåòñÿ â ñãåíåðåííîì ôàéëå ti_enet_open_close.h
|
||||
*/
|
||||
void EnetApp_initLinkArgs(Enet_Type enetType,
|
||||
uint32_t instId,
|
||||
EnetPer_PortLinkCfg *portLinkCfg,
|
||||
Enet_MacPort macPort)
|
||||
{
|
||||
EnetBoard_EthPort ethPort;
|
||||
const EnetBoard_PhyCfg *boardPhyCfg;
|
||||
IcssgMacPort_Cfg *icssgMacCfg;
|
||||
EnetMacPort_LinkCfg *linkCfg = &portLinkCfg->linkCfg;
|
||||
EnetMacPort_Interface *mii = &portLinkCfg->mii;
|
||||
EnetPhy_Cfg *phyCfg = &portLinkCfg->phyCfg;
|
||||
int32_t status = ENET_SOK;
|
||||
|
||||
EnetAppUtils_print("Open mac port %u\r\n", ENET_MACPORT_ID(macPort));
|
||||
|
||||
/* Setup board for requested Ethernet port */
|
||||
ethPort.enetType = enetType;
|
||||
ethPort.instId = instId;
|
||||
ethPort.macPort = macPort;
|
||||
ethPort.boardId = ENETBOARD_AM64X_AM243X_EVM;
|
||||
eth_macMode2MacMii(RGMII, ðPort.mii);
|
||||
|
||||
status = EnetBoard_setupPorts(ðPort, 1U);
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("Failed to setup MAC port %u\r\n", ENET_MACPORT_ID(macPort));
|
||||
EnetAppUtils_assert(false);
|
||||
}
|
||||
|
||||
icssgMacCfg = portLinkCfg->macCfg;
|
||||
IcssgMacPort_initCfg(icssgMacCfg);
|
||||
icssgMacCfg->specialFramePrio = 1U;
|
||||
|
||||
/* Set port link params */
|
||||
portLinkCfg->macPort = macPort;
|
||||
|
||||
mii->layerType = ethPort.mii.layerType;
|
||||
mii->sublayerType = ethPort.mii.sublayerType;
|
||||
mii->variantType = ENET_MAC_VARIANT_FORCED;
|
||||
|
||||
linkCfg->speed = ENET_SPEED_AUTO;
|
||||
linkCfg->duplexity = ENET_DUPLEX_AUTO;
|
||||
|
||||
boardPhyCfg = EnetBoard_getPhyCfg(ðPort);
|
||||
if (boardPhyCfg != NULL)
|
||||
{
|
||||
EnetPhy_initCfg(phyCfg);
|
||||
if ((ENET_ICSSG_DUALMAC == enetType) && (2U == instId))
|
||||
{
|
||||
phyCfg->phyAddr = CONFIG_ENET_ICSS0_PHY1_ADDR;
|
||||
}
|
||||
else if ((ENET_ICSSG_DUALMAC == enetType) && (3U == instId))
|
||||
{
|
||||
phyCfg->phyAddr = CONFIG_ENET_ICSS0_PHY2_ADDR;
|
||||
}
|
||||
else if ((ENET_ICSSG_SWITCH == enetType) && (1U == instId))
|
||||
{
|
||||
if (macPort == ENET_MAC_PORT_1)
|
||||
{
|
||||
phyCfg->phyAddr = CONFIG_ENET_ICSS0_PHY1_ADDR;
|
||||
}
|
||||
else
|
||||
{
|
||||
phyCfg->phyAddr = CONFIG_ENET_ICSS0_PHY2_ADDR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnetAppUtils_assert(false);
|
||||
}
|
||||
|
||||
phyCfg->isStrapped = boardPhyCfg->isStrapped;
|
||||
phyCfg->loopbackEn = false;
|
||||
phyCfg->skipExtendedCfg = boardPhyCfg->skipExtendedCfg;
|
||||
phyCfg->extendedCfgSize = boardPhyCfg->extendedCfgSize;
|
||||
memcpy(phyCfg->extendedCfg, boardPhyCfg->extendedCfg, phyCfg->extendedCfgSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnetAppUtils_print("No PHY configuration found for mac %u\r\n", ENET_MACPORT_ID(macPort));
|
||||
EnetAppUtils_assert(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Îáúÿâëåíà è èñïîëüçóåòñÿ â ñãåíåðåííîì ôàéëå ti_enet_open_close.h
|
||||
*/
|
||||
void EnetApp_updateIcssgInitCfg(Enet_Type enetType, uint32_t instId, Icssg_Cfg *icssgCfg)
|
||||
{
|
||||
EnetRm_ResCfg *resCfg;
|
||||
uint32_t i;
|
||||
|
||||
/* Prepare init configuration for all peripherals */
|
||||
EnetAppUtils_print("\nInit configs EnetType:%u, InstId :%u\r\n", enetType, instId);
|
||||
EnetAppUtils_print("----------------------------------------------\r\n");
|
||||
|
||||
resCfg = &icssgCfg->resCfg;
|
||||
|
||||
/* We use software MAC address pool from apputils, but it will give same MAC address.
|
||||
* Add port index to make them unique */
|
||||
for (i = 0U; i < ETH_TYPES_MAC_PORT_MAX; ++i)
|
||||
{
|
||||
resCfg->macList.macAddress[i][ENET_MAC_ADDR_LEN - 1] += i;
|
||||
}
|
||||
|
||||
resCfg->macList.numMacAddress = ETH_TYPES_MAC_PORT_MAX;
|
||||
}
|
||||
|
||||
static void eth_macMode2MacMii(emac_mode macMode,
|
||||
EnetMacPort_Interface *mii)
|
||||
{
|
||||
switch (macMode)
|
||||
{
|
||||
case RMII:
|
||||
mii->layerType = ENET_MAC_LAYER_MII;
|
||||
mii->sublayerType = ENET_MAC_SUBLAYER_REDUCED;
|
||||
mii->variantType = ENET_MAC_VARIANT_NONE;
|
||||
break;
|
||||
|
||||
case RGMII:
|
||||
mii->layerType = ENET_MAC_LAYER_GMII;
|
||||
mii->sublayerType = ENET_MAC_SUBLAYER_REDUCED;
|
||||
mii->variantType = ENET_MAC_VARIANT_FORCED;
|
||||
break;
|
||||
default:
|
||||
EnetAppUtils_print("Invalid MAC mode: %u\r\n", macMode);
|
||||
EnetAppUtils_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
227
components/free_rtos/ethernet/eth_tx_flow.cpp
Normal file
227
components/free_rtos/ethernet/eth_tx_flow.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* eth_tx_flow.cpp
|
||||
*
|
||||
* Created on: 7 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet/eth_tx_flow.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <networking/enet/core/include/core/enet_soc.h>
|
||||
#include <networking/enet/core/include/core/enet_queue.h>
|
||||
#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>
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/**
|
||||
* Ôàéëû ãåíåðèðóåìûå sysconfig.
|
||||
* Ãåíåðèðóþòñÿ ïåðåä ñáîðêîé è ïîìåùàþòñÿ â ïàïêó <build_name>/syscfg
|
||||
*/
|
||||
#include "ti_enet_config.h"
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Âûäåëÿåò ïàìÿòü ïîä ñâîäîáíûå ïàêåòû è êëàäåò èõ â î÷åðåäü p_packet_queue
|
||||
*/
|
||||
static void eth_initTxFreePktQ(void * appPriv, EnetDma_PktQ * p_packet_queue)
|
||||
{
|
||||
EnetDma_Pkt *pPktInfo;
|
||||
uint32_t i;
|
||||
|
||||
/// Ìàêñèìàëüíîå êîëè÷åñòâî ïàêåòîâ
|
||||
int i_max = (ENET_SYSCFG_TOTAL_NUM_TX_PKT/2);
|
||||
|
||||
/* Initialize TX EthPkts and queue them to txFreePktInfoQ */
|
||||
for (i = 0U; i < i_max; 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);
|
||||
/// Êëàäåì ïàêåò â î÷åðåäü p_packet_queue
|
||||
EnetQueue_enq(p_packet_queue, &pPktInfo->node);
|
||||
}
|
||||
|
||||
EnetAppUtils_print("initQs() txFreePktInfoQ initialized with %d pkts\r\n",
|
||||
EnetQueue_getQCount(p_packet_queue));
|
||||
}
|
||||
|
||||
static uint32_t eth_retrieveFreeTxPkts(EnetDma_TxChHandle * p_handle, EnetDma_PktQ * p_queque)
|
||||
{
|
||||
EnetDma_PktQ txFreeQ;
|
||||
EnetDma_Pkt *pktInfo;
|
||||
uint32_t txFreeQCnt = 0U;
|
||||
int32_t status;
|
||||
|
||||
EnetQueue_initQ(&txFreeQ);
|
||||
|
||||
/// Èçâëåêàåì ïàêåòû êîòîðûå áûëè óñïåøíî ïåðåäàíû èç î÷åðåäè çàâåðøåíèÿ ïåðåäà÷è
|
||||
status = EnetDma_retrieveTxPktQ(*p_handle, &txFreeQ);
|
||||
if (status == ENET_SOK)
|
||||
{
|
||||
/// Êîëè÷åñòâî ïàêåòîâ â î÷åðåäè
|
||||
txFreeQCnt = EnetQueue_getQCount(&txFreeQ);
|
||||
|
||||
pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ);
|
||||
while (NULL != pktInfo)
|
||||
{
|
||||
EnetDma_checkPktState(&pktInfo->pktState,
|
||||
ENET_PKTSTATE_MODULE_APP,
|
||||
ENET_PKTSTATE_APP_WITH_DRIVER,
|
||||
ENET_PKTSTATE_APP_WITH_FREEQ);
|
||||
|
||||
/// Ïîëîæèòü ïàêåò â î÷åðåäü ñâîáîäíûõ ïàêåòîâ txFreePktInfoQ
|
||||
EnetQueue_enq(p_queque, &pktInfo->node);
|
||||
pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ); /// Âçÿòü ñëåäóþùèé ñâîáîäíûé ïàêåò
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnetAppUtils_print("retrieveFreeTxPkts() failed to retrieve pkts: %d\r\n", status);
|
||||
}
|
||||
|
||||
return txFreeQCnt; /// Êîëè÷åñòâî ñâîáîäíûõ ïàêåòîâ
|
||||
}
|
||||
|
||||
free_rtos::EthTxFlow::EthTxFlow() :
|
||||
id_{0},
|
||||
open_{false},
|
||||
tx_ch_num_{0}
|
||||
{
|
||||
EnetQueue_initQ(&tx_free_pktq_);
|
||||
}
|
||||
|
||||
bool free_rtos::EthTxFlow::open(uint32_t id, int32_t enetDmaTxChId)
|
||||
{
|
||||
if (id >= e_ethMacTotal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnetApp_GetDmaHandleInArgs txInArgs;
|
||||
EnetApp_GetTxDmaHandleOutArgs txChInfo;
|
||||
|
||||
EnetAppUtils_print("tx_flow %u: opening flow...\r\n", id);
|
||||
|
||||
port_data_[id].tx_pkt_counter = 0;
|
||||
|
||||
if (open_) {
|
||||
EnetAppUtils_print("tx_flow %u: tx flow is already open. Do nothing.\r\n", id_);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Open the TX channel */
|
||||
txInArgs.notifyCb = nullptr;
|
||||
txInArgs.cbArg = nullptr;
|
||||
|
||||
EnetApp_getTxDmaHandle(enetDmaTxChId, &txInArgs, &txChInfo);
|
||||
|
||||
tx_ch_num_ = txChInfo.txChNum;
|
||||
dma_handle_ = txChInfo.hTxCh;
|
||||
|
||||
EnetAppUtils_assert(txChInfo.useGlobalEvt == true);
|
||||
EnetAppUtils_assert(txChInfo.maxNumTxPkts >= (ENET_SYSCFG_TOTAL_NUM_TX_PKT/2U));
|
||||
|
||||
if (dma_handle_ == nullptr)
|
||||
{
|
||||
EnetAppUtils_print("tx_flow %u: failed to open tx dma flow\r\n", id_);
|
||||
EnetAppUtils_assert(dma_handle_ != nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
eth_initTxFreePktQ(this, &tx_free_pktq_);
|
||||
|
||||
open_= true;
|
||||
|
||||
EnetAppUtils_print("tx_flow %u: tx flow open successfully\r\n", id_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void free_rtos::EthTxFlow::enable(TEthMacPorts port_id) {
|
||||
if (port_id >= e_ethMacTotal) {
|
||||
return;
|
||||
}
|
||||
|
||||
port_data_[port_id].tx_enable = true;
|
||||
}
|
||||
|
||||
void free_rtos::EthTxFlow::disable(TEthMacPorts port_id) {
|
||||
if (port_id >= e_ethMacTotal) {
|
||||
return;
|
||||
}
|
||||
|
||||
port_data_[port_id].tx_enable = false;
|
||||
}
|
||||
|
||||
bool free_rtos::EthTxFlow::send(TEthMacPorts port_id, uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
if (port_id >= e_ethMacTotal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!port_data_[port_id].tx_enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnetDma_PktQ txSubmitQ;
|
||||
EnetDma_Pkt *txPktInfo;
|
||||
int32_t status;
|
||||
|
||||
/*
|
||||
* Îáíàðóæèâàåò ñâîáîäíûå ïàêåòû â äðàéâåðå enet è êëàäåò èõ â î÷åðåäü ñâîáîäíûõ ïàêåòîâ txFreePktInfoQ
|
||||
*/
|
||||
eth_retrieveFreeTxPkts(&dma_handle_, &tx_free_pktq_);
|
||||
|
||||
/// Èíèöèàëèçèðóåì ïîëÿ txSubmitQ
|
||||
EnetQueue_initQ(&txSubmitQ);
|
||||
|
||||
/* Çàáðàòü èç î÷åðåäè îäèí ñâîáîäíûé ïàêåò TX Eth */
|
||||
txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&tx_free_pktq_);
|
||||
if (txPktInfo != NULL)
|
||||
{
|
||||
///Êîïèðóåì äàííûå ïàêåòà â áóôåð
|
||||
memcpy(txPktInfo->sgList.list[0].bufPtr, p_data, len);
|
||||
|
||||
txPktInfo->sgList.list[0].segmentFilledLen = len;
|
||||
txPktInfo->sgList.numScatterSegments = 1;
|
||||
txPktInfo->chkSumInfo = 0U;
|
||||
txPktInfo->appPriv = nullptr;
|
||||
txPktInfo->tsInfo.txPktSeqId = 0;
|
||||
txPktInfo->txPktTc = 0; /// Traffic class íóæåí äëÿ IPv6
|
||||
txPktInfo->tsInfo.enableHostTxTs = false;
|
||||
txPktInfo->txPortNum = (Enet_MacPort)port_id;
|
||||
|
||||
EnetDma_checkPktState(&txPktInfo->pktState,
|
||||
ENET_PKTSTATE_MODULE_APP,
|
||||
ENET_PKTSTATE_APP_WITH_FREEQ,
|
||||
ENET_PKTSTATE_APP_WITH_DRIVER);
|
||||
|
||||
/// Êëàäåì ïàêåò txPktInfo â î÷åðåäü txSubmitQ
|
||||
EnetQueue_enq(&txSubmitQ, &txPktInfo->node);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnetAppUtils_print("tx_flow %u: Drop due to TX pkt not available\r\n", id_);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Êëàäåì î÷åðåäü â î÷åðåäü DMA
|
||||
status = EnetDma_submitTxPktQ(dma_handle_, &txSubmitQ);
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("tx_flow %u: Failed to submit TX pkt queue: %d\r\n", id_, status);
|
||||
return false;
|
||||
}
|
||||
|
||||
++port_data_[port_id].tx_pkt_counter; /// Ñ÷åò÷èê ïåðåäàííûõ ïàêåòîâ
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
52
components/free_rtos/ethernet/eth_tx_flow.hpp
Normal file
52
components/free_rtos/ethernet/eth_tx_flow.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* eth_tx_flow.hpp
|
||||
*
|
||||
* Created on: 7 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_TX_FLOW_HPP_
|
||||
#define FREE_RTOS_ETHERNET_ETH_TX_FLOW_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <networking/enet/core/include/core/enet_dma.h>
|
||||
|
||||
#include "ethernet/eth_tx_flow_iface.hpp"
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthTxFlow : public EthTxFlowIface {
|
||||
public:
|
||||
EthTxFlow();
|
||||
|
||||
bool open(uint32_t id, int32_t enetDmaTxChId);
|
||||
|
||||
bool is_open() {return open_;}
|
||||
|
||||
void enable(TEthMacPorts port_id);
|
||||
|
||||
void disable(TEthMacPorts port_id);
|
||||
|
||||
virtual bool send(TEthMacPorts port_id, uint8_t * p_data, uint32_t len) override;
|
||||
|
||||
private:
|
||||
struct PortData {
|
||||
bool tx_enable;
|
||||
uint32_t tx_pkt_counter;
|
||||
};
|
||||
|
||||
uint32_t id_;
|
||||
bool open_;
|
||||
|
||||
//-------------------------------------------------
|
||||
uint32_t tx_ch_num_;
|
||||
EnetDma_TxChHandle dma_handle_; /// Ïåðåäàþùèé êàíàë DMA
|
||||
EnetDma_PktQ tx_free_pktq_; /// Î÷åðåäü ñâîáîäíûõ ïàêåòîâ
|
||||
|
||||
PortData port_data_[e_ethMacTotal];
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_TX_FLOW_HPP_ */
|
||||
22
components/free_rtos/ethernet/eth_tx_flow_iface.hpp
Normal file
22
components/free_rtos/ethernet/eth_tx_flow_iface.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* eth_tx_iface.hpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_TX_FLOW_IFACE_HPP_
|
||||
#define FREE_RTOS_ETHERNET_ETH_TX_FLOW_IFACE_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include "ethernet/eth_types.h"
|
||||
|
||||
class EthTxFlowIface {
|
||||
public:
|
||||
virtual bool send(TEthMacPorts port_id, uint8_t * p_data, uint32_t len) = 0;
|
||||
virtual ~EthTxFlowIface(){}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_TX_FLOW_IFACE_HPP_ */
|
||||
17
components/free_rtos/ethernet/eth_types.h
Normal file
17
components/free_rtos/ethernet/eth_types.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* eth_types.hpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_TYPES_HPP_
|
||||
#define FREE_RTOS_ETHERNET_ETH_TYPES_HPP_
|
||||
|
||||
typedef enum {
|
||||
e_ethMac0,
|
||||
e_ethMac1,
|
||||
e_ethMacTotal
|
||||
}TEthMacPorts;
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_TYPES_HPP_ */
|
||||
300
components/free_rtos/ethernet/eth_vlan.c
Normal file
300
components/free_rtos/ethernet/eth_vlan.c
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* eth_vlan.c
|
||||
*
|
||||
* Created on: 9 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet/eth_vlan.h"
|
||||
|
||||
#include <networking/enet/utils/include/enet_apputils.h>
|
||||
#include <networking/enet/core/include/core/enet_ioctl.h>
|
||||
|
||||
//using namespace free_rtos;
|
||||
|
||||
/* Bit#0 Indicates host ownership (indicates Host egress) */
|
||||
#define FDB_ENTRY_HOST_BIT (0)
|
||||
|
||||
/* Bit#1 Indicates that MAC ID is connected to Physical Port 1 */
|
||||
#define FDB_ENTRY_PORT1_BIT (1)
|
||||
|
||||
/* Bit#2 Indicates that MAC ID is connected to Physical Port 2 */
|
||||
#define FDB_ENTRY_PORT2_BIT (2)
|
||||
|
||||
/* Bit#3 This is set to 1 for all learnt entries. 0 for static entries. */
|
||||
#define FDB_ENTRY_LEARNT_ENTRY_BIT (3)
|
||||
|
||||
/* Bit#4 If set for SA then packet is dropped (can be used to implement a blacklist).
|
||||
* If set for DA then packet is determined to be a special packet */
|
||||
#define FDB_ENTRY_BLOCK_BIT (4)
|
||||
|
||||
/* Bit#5 If set for DA then the SA from the packet is not learnt */
|
||||
|
||||
/* Bit#6 if set, it means packet has been seen recently with source address +
|
||||
* FID matching MAC address/FID of entry. */
|
||||
#define FDB_ENTRY_TOUCH_BIT (6)
|
||||
|
||||
/* Bit#7 set if entry is valid */
|
||||
#define FDB_ENTRY_VALID_BIT (7)
|
||||
|
||||
int32_t eth_vlan_setPriorityRegMapping(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
Enet_MacPort macPort,
|
||||
uint32_t *prioRegenMap)
|
||||
{
|
||||
EnetMacPort_SetPriorityRegenMapInArgs regenMap;
|
||||
Enet_IoctlPrms prms;
|
||||
int32_t status = ENET_SOK;
|
||||
int32_t i;
|
||||
|
||||
regenMap.macPort = macPort;
|
||||
|
||||
for (i = 0; i < ENET_PRI_NUM; i++)
|
||||
{
|
||||
regenMap.priorityRegenMap.priorityMap[i] = prioRegenMap[i];
|
||||
}
|
||||
|
||||
ENET_IOCTL_SET_IN_ARGS(&prms, ®enMap);
|
||||
|
||||
ENET_IOCTL(handle, core_id, ENET_MACPORT_IOCTL_SET_PRI_REGEN_MAP, &prms, status);
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("ERROR: IOCTL command for priority regeneration for PORT = %u\r\n", macPort);
|
||||
status = ENET_EFAIL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t eth_vlan_setPriorityMapping(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
Enet_MacPort macPort,
|
||||
uint32_t *prioMap)
|
||||
{
|
||||
EnetMacPort_SetEgressPriorityMapInArgs priMap;
|
||||
Enet_IoctlPrms prms;
|
||||
int32_t status = ENET_SOK;
|
||||
int32_t i;
|
||||
|
||||
priMap.macPort = macPort;
|
||||
|
||||
for (i = 0; i < ENET_PRI_NUM; i++)
|
||||
{
|
||||
priMap.priorityMap.priorityMap[i] = prioMap[i];
|
||||
}
|
||||
|
||||
ENET_IOCTL_SET_IN_ARGS(&prms, &priMap);
|
||||
ENET_IOCTL(handle, core_id, ENET_MACPORT_IOCTL_SET_EGRESS_QOS_PRI_MAP, &prms, status);
|
||||
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("ERROR: IOCTL command for priority mapping for PORT = %u\r\n", macPort);
|
||||
status = ENET_EFAIL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t eth_vlan_addDefaultHostVid(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
uint8_t pcp,
|
||||
uint16_t vlan_id)
|
||||
{
|
||||
Enet_IoctlPrms prms;
|
||||
EnetPort_VlanCfg vlanDefaultEntry;
|
||||
int32_t status = ENET_SOK;
|
||||
|
||||
vlanDefaultEntry.portVID = vlan_id;
|
||||
vlanDefaultEntry.portPri = pcp;
|
||||
|
||||
ENET_IOCTL_SET_IN_ARGS(&prms, &vlanDefaultEntry);
|
||||
ENET_IOCTL(handle, core_id, ICSSG_PER_IOCTL_VLAN_SET_HOSTPORT_DFLT_VID, &prms, status);
|
||||
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("Failed to set default VID");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t eth_vlan_addDefaultPortVid(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
Enet_MacPort macPort,
|
||||
uint8_t pcp,
|
||||
uint16_t vlanId)
|
||||
{
|
||||
int32_t status = ENET_SOK;
|
||||
Enet_IoctlPrms prms;
|
||||
Icssg_MacPortDfltVlanCfgInArgs vlanDefaultEntry;
|
||||
|
||||
vlanDefaultEntry.macPort = macPort;
|
||||
vlanDefaultEntry.vlanCfg.portVID = vlanId;
|
||||
vlanDefaultEntry.vlanCfg.portPri = pcp;
|
||||
|
||||
ENET_IOCTL_SET_IN_ARGS(&prms, &vlanDefaultEntry);
|
||||
ENET_IOCTL(handle, core_id, ICSSG_PER_IOCTL_VLAN_SET_MACPORT_DFLT_VID, &prms, status);
|
||||
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("Failed to set default VID");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t eth_vlan_init(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
uint16_t vlanId,
|
||||
Enet_Type enetType)
|
||||
{
|
||||
int32_t status = ENET_SOK;
|
||||
Enet_IoctlPrms prms;
|
||||
uint32_t i;
|
||||
uint32_t prioRegenMap[ENET_PRI_NUM];
|
||||
uint32_t prioMap[ENET_PRI_NUM];
|
||||
Icssg_VlanFidEntry vlanEntry;
|
||||
Icssg_VlanFidParams vlanParams = {
|
||||
.fid = 0,
|
||||
.hostMember = 1,
|
||||
.p1Member = 1,
|
||||
.p2Member = 1,
|
||||
.hostTagged = 0,
|
||||
.p1Tagged = 0,
|
||||
.p2Tagged = 0,
|
||||
.streamVid = 0,
|
||||
.floodToHost = 0
|
||||
};
|
||||
Icssg_VlanFidParams vlanParamsForPrioTag = {
|
||||
.fid = 0,
|
||||
.hostMember = 1,
|
||||
.p1Member = 1,
|
||||
.p2Member = 1,
|
||||
.hostTagged = 0,
|
||||
.p1Tagged = 1,
|
||||
.p2Tagged = 1,
|
||||
.streamVid = 0,
|
||||
.floodToHost = 0
|
||||
};
|
||||
|
||||
vlanParams.fid = vlanId;
|
||||
|
||||
for (i = 0; i < ENET_PRI_NUM; i++)
|
||||
{
|
||||
prioRegenMap[i] = (uint32_t)(ENET_PRI_NUM-1-i);
|
||||
prioMap[i] = 0U;
|
||||
}
|
||||
|
||||
/* Óñòàíîâèòå êîìàíäó IOCTL, ÷òîáû ñäåëàòü PORT1 ãðàíè÷íûì ïîðòîì, à PORT2 ïðèíèìàòü âñå òèïû ïàêåòîâ. */
|
||||
eth_vlan_setPriorityRegMapping(handle, core_id, ENET_MAC_PORT_1, prioRegenMap);
|
||||
eth_vlan_setPriorityMapping(handle, core_id, ENET_MAC_PORT_1, prioMap);
|
||||
|
||||
if (enetType == ENET_ICSSG_SWITCH)
|
||||
{
|
||||
eth_vlan_setPriorityRegMapping(handle, core_id, ENET_MAC_PORT_2, prioRegenMap);
|
||||
eth_vlan_setPriorityMapping(handle, core_id, ENET_MAC_PORT_2, prioMap);
|
||||
}
|
||||
|
||||
/* Make an entry for common vlan id
|
||||
* Update table for default entry */
|
||||
vlanEntry.vlanFidParams = vlanParams;
|
||||
vlanEntry.vlanId = (uint16_t)vlanId;
|
||||
|
||||
ENET_IOCTL_SET_IN_ARGS(&prms, &vlanEntry);
|
||||
ENET_IOCTL(handle, core_id, ICSSG_PER_IOCTL_VLAN_SET_ENTRY, &prms, status);
|
||||
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("FID VLAN entry for HOST is FAILED = %u : FAILED\r\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* -----------------Make an entry for Priority tag----------------- */
|
||||
|
||||
vlanEntry.vlanFidParams = vlanParamsForPrioTag;
|
||||
vlanEntry.vlanId = (uint16_t)0;
|
||||
|
||||
ENET_IOCTL_SET_IN_ARGS(&prms, &vlanEntry);
|
||||
ENET_IOCTL(handle, core_id, ICSSG_PER_IOCTL_VLAN_SET_ENTRY, &prms, status);
|
||||
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("FID VLAN entry for VID = 0: FAILED = %u : FAILED\r\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* -----------------Make a default entry for Host port----------------- */
|
||||
status = eth_vlan_addDefaultHostVid(handle, core_id, 0, vlanId);
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("\n ERROR: In updating default VLAN for Host : %d\r\n", status);
|
||||
}
|
||||
|
||||
/* -----------------Make a default entry for P1 port----------------- */
|
||||
status = eth_vlan_addDefaultPortVid(handle, core_id, ENET_MAC_PORT_1, 1, vlanId);
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("\n ERROR: In updating default VLAN for P1 \r\n\r");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (enetType == ENET_ICSSG_SWITCH)
|
||||
{
|
||||
/* -----------------Make a default entry for P2 port----------------- */
|
||||
status = eth_vlan_addDefaultPortVid(handle, core_id, ENET_MAC_PORT_2, 2, vlanId);
|
||||
if (status != ENET_SOK)
|
||||
{
|
||||
EnetAppUtils_print("\n ERROR: In updating default VLAN for P2 \r\n\r");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*int32_t eth_vlan_addMacFdbEntry(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
Semaphore& ioctl_sem,
|
||||
Icssg_MacAddr mac,
|
||||
int16_t vlanId,
|
||||
uint8_t fdbEntryPort)
|
||||
{
|
||||
int32_t status = ENET_EFAIL;
|
||||
int32_t semStatus;
|
||||
Enet_IoctlPrms prms;
|
||||
Icssg_FdbEntry fdbEntry;
|
||||
int i = 0;
|
||||
|
||||
// Now make an entry in FDB for the HOST MAC address using Asynchronous IOCTL
|
||||
for (i = 0; i < ENET_MAC_ADDR_LEN; i++)
|
||||
{
|
||||
fdbEntry.macAddr[i] = mac.macAddr[i];
|
||||
}
|
||||
|
||||
fdbEntry.vlanId = vlanId;
|
||||
fdbEntry.fdbEntry[0] = fdbEntryPort;
|
||||
fdbEntry.fdbEntry[1] = fdbEntryPort;
|
||||
|
||||
ENET_IOCTL_SET_IN_ARGS(&prms, &fdbEntry);
|
||||
ENET_IOCTL(handle, core_id, ICSSG_FDB_IOCTL_ADD_ENTRY, &prms, status);
|
||||
|
||||
if (status == ENET_SINPROGRESS)
|
||||
{
|
||||
EnetAppUtils_print("Success: IOCTL command sent for making MAC entry in FDB \r\n");
|
||||
|
||||
// Wait for asyc ioctl to complete
|
||||
do
|
||||
{
|
||||
Enet_poll(handle, ENET_EVT_ASYNC_CMD_RESP, NULL, 0U);
|
||||
semStatus = ioctl_sem.pend(1U);
|
||||
} while (semStatus != SystemP_SUCCESS);
|
||||
|
||||
status = ENET_SOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnetAppUtils_print("ERROR: IOCTL command sent for making MAC entry in FDB failed as vlanId out of range \r\n");
|
||||
EnetAppUtils_print("ERROR: IOCTL command sent for making MAC entry in FDB \r\n");
|
||||
}
|
||||
|
||||
return status;
|
||||
}*/
|
||||
62
components/free_rtos/ethernet/eth_vlan.h
Normal file
62
components/free_rtos/ethernet/eth_vlan.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* eth_vlan.hpp
|
||||
*
|
||||
* Created on: 9 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_VLAN_HPP_
|
||||
#define FREE_RTOS_ETHERNET_ETH_VLAN_HPP_
|
||||
|
||||
//#include "semaphore/semaphore.hpp"
|
||||
|
||||
#include <networking/enet/core/include/core/enet_base.h>
|
||||
//#include <networking/enet/core/include/per/icssg.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//namespace free_rtos {
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t eth_vlan_setPriorityRegMapping(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
Enet_MacPort macPort,
|
||||
uint32_t *prioRegenMap);
|
||||
|
||||
int32_t eth_vlan_setPriorityMapping(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
Enet_MacPort macPort,
|
||||
uint32_t *prioMap);
|
||||
|
||||
int32_t eth_vlan_addDefaultHostVid(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
uint8_t pcp,
|
||||
uint16_t vlan_id);
|
||||
|
||||
int32_t eth_vlan_addDefaultPortVid(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
Enet_MacPort macPort,
|
||||
uint8_t pcp,
|
||||
uint16_t vlanId);
|
||||
|
||||
int32_t eth_vlan_init(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
uint16_t vlanId,
|
||||
Enet_Type enetType);
|
||||
|
||||
/*int32_t eth_vlan_addMacFdbEntry(Enet_Handle handle,
|
||||
uint32_t core_id,
|
||||
Semaphore& ioctl_sem,
|
||||
Icssg_MacAddr mac,
|
||||
int16_t vlanId,
|
||||
uint8_t fdbEntryPort);
|
||||
|
||||
}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_VLAN_HPP_ */
|
||||
211
components/free_rtos/ethernet_industry/eth_ecat.cpp
Normal file
211
components/free_rtos/ethernet_industry/eth_ecat.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* eth_ecat.cpp
|
||||
*
|
||||
* Created on: 16 <EFBFBD><EFBFBD><EFBFBD>. 2023 <EFBFBD>.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#include "ethernet_industry/eth_ecat.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <kernel/dpl/ClockP.h>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
EthEcat::EthEcat(Eth& eth)
|
||||
: p_pkt_{&pkt_[e_pktFirst]}
|
||||
, p_pkt_next_{&pkt_[e_pktSecond]}
|
||||
, eth_{eth}
|
||||
, tx_flow_{*eth.getTxFlowPtr()}
|
||||
, telegram_{eth}
|
||||
, eeprom_{telegram_} { }
|
||||
|
||||
void EthEcat::Init(TEthMacPorts port_id) {
|
||||
port_id_ = port_id;
|
||||
telegram_.init(port_id);
|
||||
}
|
||||
|
||||
int32_t EthEcat::Process(uint8_t * p_data, uint32_t len) {
|
||||
p_pkt_next_->length = len + sizeof(TEthFrameHeader);
|
||||
|
||||
memcpy(p_pkt_next_->data, p_data - sizeof(TEthFrameHeader), p_pkt_next_->length);
|
||||
|
||||
++stat_.rx_pkt;
|
||||
|
||||
rx_sem_.post();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> EthEcat::receive_datagram() {
|
||||
rx_sem_.pend();
|
||||
|
||||
return std::vector<uint8_t>(p_pkt_next_->data + sizeof(TEthFrameHeader), p_pkt_next_->data + p_pkt_next_->length);
|
||||
}
|
||||
|
||||
void EthEcat::send_datagram(const std::vector<uint8_t>& datagram) {
|
||||
TEthFrameHeader *p_eth_hdr = reinterpret_cast<TEthFrameHeader*>(p_pkt_->data);
|
||||
uint8_t *p_eth_data = reinterpret_cast<uint8_t*>(p_pkt_->data + sizeof(TEthFrameHeader));
|
||||
|
||||
uint8_t mac_dest[ETH_FRAME_MAC_ADDR_LEN_BYTES] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
uint8_t mac_src[ETH_FRAME_MAC_ADDR_LEN_BYTES] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
|
||||
|
||||
memcpy(p_eth_hdr->mac_dest, mac_dest, sizeof(mac_dest));
|
||||
memcpy(p_eth_hdr->mac_src, mac_src, sizeof(mac_src));
|
||||
p_eth_hdr->prot_id = ETH_PROT_ECAT_LE;
|
||||
|
||||
memcpy(p_eth_data, datagram.data(), datagram.size());
|
||||
|
||||
p_pkt_->length = sizeof(TEthFrameHeader) + datagram.size();
|
||||
|
||||
bool stat = tx_flow_.send(port_id_, p_pkt_->data, p_pkt_->length);
|
||||
|
||||
if (stat)
|
||||
{
|
||||
++stat_.tx_pkt;
|
||||
}
|
||||
}
|
||||
|
||||
void EthEcat::set_slaves_to_default() {
|
||||
/* deact loop manual */
|
||||
uint8_t a_data_out{0x00};
|
||||
datagram::EcatDatagram<command::BWR, uint8_t> a{ {{0x0000, ECT_REG_DLPORT}}, a_data_out };
|
||||
|
||||
/* set IRQ mask */
|
||||
uint16_t b_data_out{0x0C04};
|
||||
datagram::EcatDatagram<command::BWR, uint16_t> b{ {{0x0000, ECT_REG_IRQMASK}}, b_data_out };
|
||||
|
||||
/* reset CRC counters */
|
||||
std::array<uint8_t, 8> c_data_out;
|
||||
datagram::EcatDatagram<command::BWR, std::array<uint8_t, 8>> c{ {{0x0000, ECT_REG_RXERR}}, c_data_out };
|
||||
|
||||
/* reset FMMU's */
|
||||
std::array<uint8_t, 16*3> d_data_out;
|
||||
std::array<uint8_t, 16*3> d_data_in;
|
||||
datagram::EcatDatagram<command::BWR, std::array<uint8_t, 16*3>> d{ {{0x0000, ECT_REG_FMMU0}}, d_data_out };
|
||||
|
||||
/* reset SyncM */
|
||||
std::array<uint8_t, 8*4> e_data_out;
|
||||
datagram::EcatDatagram<command::BWR, std::array<uint8_t, 8*4>> e{ {{0x0000, ECT_REG_SM0}}, e_data_out };
|
||||
|
||||
/* reset activation register */
|
||||
uint8_t f_data_out{0x00};
|
||||
datagram::EcatDatagram<command::BWR, uint8_t> f{ {{0x0000, ECT_REG_DCSYNCACT}}, f_data_out };
|
||||
|
||||
/* reset system time+ofs */
|
||||
std::array<uint8_t, 4> g_data_out;
|
||||
datagram::EcatDatagram<command::BWR, std::array<uint8_t, 4>> g{ {{0x0000, ECT_REG_DCSYSTIME}}, g_data_out };
|
||||
|
||||
/* DC speedstart */
|
||||
uint16_t h_data_out{0x1000};
|
||||
datagram::EcatDatagram<command::BWR, uint16_t> h{ {{0x0000, ECT_REG_DCSPEEDCNT}}, h_data_out };
|
||||
|
||||
/* DC filt expr */
|
||||
uint16_t i_data_out{0x0C00};
|
||||
datagram::EcatDatagram<command::BWR, uint16_t> i{ {{0x0000, ECT_REG_DCTIMEFILT}}, i_data_out };
|
||||
|
||||
/* Ignore Alias register */
|
||||
uint8_t j_data_out{0x00};
|
||||
datagram::EcatDatagram<command::BWR, uint8_t> j{ {{0x0000, ECT_REG_DLALIAS}}, j_data_out };
|
||||
|
||||
/* Reset all slaves to Init */
|
||||
uint8_t k_data_out{0x00};
|
||||
datagram::EcatDatagram<command::BWR, uint8_t> k{ {{0x0000, ECT_REG_ALCTL}}, k_data_out };
|
||||
|
||||
/* force Eeprom from PDI */
|
||||
uint8_t l_data_out{0x02};
|
||||
datagram::EcatDatagram<command::BWR, uint8_t> l{ {{0x0000, ECT_REG_EEPCFG}}, l_data_out };
|
||||
|
||||
/* set Eeprom to master */
|
||||
uint8_t m_data_out{0x00};
|
||||
datagram::EcatDatagram<command::BWR, uint8_t> m{ {{0x0000, ECT_REG_EEPCFG}}, m_data_out };
|
||||
|
||||
a + b + c + d + e + f + g + h + i + j + k + l + m;
|
||||
telegram_.transfer(a);
|
||||
|
||||
DebugP_log("a.get_wkc() = %d\r\n", a.get_wkc());
|
||||
DebugP_log("b.get_wkc() = %d\r\n", b.get_wkc());
|
||||
DebugP_log("c.get_wkc() = %d\r\n", c.get_wkc());
|
||||
DebugP_log("d.get_wkc() = %d\r\n", d.get_wkc());
|
||||
DebugP_log("e.get_wkc() = %d\r\n", e.get_wkc());
|
||||
DebugP_log("f.get_wkc() = %d\r\n", f.get_wkc());
|
||||
DebugP_log("g.get_wkc() = %d\r\n", g.get_wkc());
|
||||
DebugP_log("h.get_wkc() = %d\r\n", h.get_wkc());
|
||||
DebugP_log("i.get_wkc() = %d\r\n", i.get_wkc());
|
||||
DebugP_log("j.get_wkc() = %d\r\n", j.get_wkc());
|
||||
DebugP_log("k.get_wkc() = %d\r\n", k.get_wkc());
|
||||
DebugP_log("l.get_wkc() = %d\r\n", l.get_wkc());
|
||||
DebugP_log("m.get_wkc() = %d\r\n", m.get_wkc());
|
||||
}
|
||||
|
||||
uint16_t EthEcat::slaves_detecting() {
|
||||
uint16_t data_out{0x0000};
|
||||
datagram::EcatDatagram<command::BRD, uint16_t> datagram{ {{0x0000, ECT_REG_TYPE}}, data_out };
|
||||
|
||||
telegram_.transfer(datagram);
|
||||
|
||||
return datagram.get_wkc();
|
||||
}
|
||||
|
||||
void EthEcat::set_addresses_of_slaves(uint16_t address_base) {
|
||||
std::array<datagram::EcatDatagram<command::APWR, address::Node>, max_number_of_slaves> datagrams;
|
||||
|
||||
for(uint16_t i = 0; i < number_of_slaves_; i++) {
|
||||
slaves_[i].set_slave_address<command::FP>(static_cast<address::Node>(address_base + i));
|
||||
slaves_[i].set_slave_address<command::AP>(static_cast<address::Position>(-i));
|
||||
|
||||
datagrams[i] = { {{address::Position{static_cast<int16_t>(-i)}, ECT_REG_STADR}}, slaves_[i].get_slave_address<command::FP>() };
|
||||
}
|
||||
|
||||
for(uint16_t i = 1; i < number_of_slaves_; i++) {
|
||||
datagrams[i - 1] + datagrams[i];
|
||||
}
|
||||
|
||||
telegram_.transfer(datagrams[0]);
|
||||
}
|
||||
|
||||
void EthEcat::get_addresses_of_slaves() {
|
||||
std::array<datagram::EcatDatagram<command::APRD, address::Node>, max_number_of_slaves> datagrams;
|
||||
|
||||
for(uint16_t i = 0; i < number_of_slaves_; i++) {
|
||||
slaves_[i].set_slave_address<command::AP>(static_cast<address::Position>(-i));
|
||||
|
||||
datagrams[i] = { {{address::Position{static_cast<int16_t>(-i)}, ECT_REG_STADR}}, slaves_[i].get_slave_address<command::FP>() };
|
||||
}
|
||||
|
||||
for(uint16_t i = 1; i < number_of_slaves_; i++) {
|
||||
datagrams[i - 1] + datagrams[i];
|
||||
}
|
||||
|
||||
telegram_.transfer(datagrams[0]);
|
||||
|
||||
for(uint16_t i = 0; i < number_of_slaves_; i++) {
|
||||
DebugP_log("Slave %d address = %d\r\n", i, slaves_[i].get_slave_address<command::FP>());
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t EthEcat::config_init() {
|
||||
DebugP_log("Initializing slaves...\r\n");
|
||||
|
||||
set_slaves_to_default();
|
||||
number_of_slaves_ = slaves_detecting();
|
||||
DebugP_log("number_of_slaves = %d\r\n", number_of_slaves_);
|
||||
|
||||
set_addresses_of_slaves(0x1000);
|
||||
get_addresses_of_slaves();
|
||||
|
||||
address::Node node = 4096;
|
||||
|
||||
BufferProperties mbx_write_adr_len;
|
||||
eeprom_.read<command::FP>(node, ECT_SII_RXMBXADR, mbx_write_adr_len);
|
||||
|
||||
BufferProperties mbx_read_adr_len;
|
||||
eeprom_.read<command::FP>(node, ECT_SII_TXMBXADR, mbx_read_adr_len);
|
||||
|
||||
DebugP_log("response = 0x%04x\r\n", mbx_write_adr_len);
|
||||
DebugP_log("response = 0x%04x\r\n", mbx_read_adr_len);
|
||||
|
||||
return number_of_slaves_;
|
||||
}
|
||||
|
||||
}
|
||||
141
components/free_rtos/ethernet_industry/eth_ecat.hpp
Normal file
141
components/free_rtos/ethernet_industry/eth_ecat.hpp
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* eth_ecat.hpp
|
||||
*
|
||||
* Created on: 16 <EFBFBD><EFBFBD><EFBFBD>. 2023 <EFBFBD>.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_HPP_
|
||||
#define FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_HPP_
|
||||
|
||||
#include <ethernet_industry/eth_ecat_datagram.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
#include "handler_store/handler.hpp"
|
||||
#include "ethernet/eth_frame.h"
|
||||
#include "mutex/mutex.hpp"
|
||||
#include "semaphore/semaphore.hpp"
|
||||
#include "ethernet/eth.hpp"
|
||||
#include "ethernet_industry/ethercattype.hpp"
|
||||
#include "ethernet_industry/eth_ecat_types.h"
|
||||
#include "ethernet_industry/eth_ecat_command.hpp"
|
||||
#include "ethernet_industry/eth_ecat_eeprom.hpp"
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
struct BufferProperties {
|
||||
uint16_t address;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
class EcatSlave {
|
||||
public:
|
||||
EcatSlave() {
|
||||
|
||||
}
|
||||
|
||||
template<typename TypeT>
|
||||
void set_slave_address(typename TypeT::TSlaveAddress&& slave_address) {
|
||||
std::get<static_cast<size_t>(TypeT::type)>(slave_addresses_) = slave_address;
|
||||
}
|
||||
|
||||
template<typename TypeT>
|
||||
typename TypeT::TSlaveAddress& get_slave_address() {
|
||||
return std::get<static_cast<size_t>(TypeT::type)>(slave_addresses_);
|
||||
}
|
||||
|
||||
private:
|
||||
address::SlaveTypes slave_addresses_;
|
||||
|
||||
BufferProperties mbx_write_;
|
||||
BufferProperties mbx_read_;
|
||||
|
||||
BufferProperties pdo_output_;
|
||||
BufferProperties mbx_input_;
|
||||
};
|
||||
|
||||
class EthEcat : public Handler {
|
||||
public:
|
||||
struct Statistic {
|
||||
uint32_t rx_pkt;
|
||||
uint32_t tx_pkt;
|
||||
};
|
||||
|
||||
EthEcat(Eth& eth);
|
||||
|
||||
void Init(TEthMacPorts port_id);
|
||||
|
||||
std::vector<uint8_t> receive_datagram();
|
||||
void send_datagram(const std::vector<std::uint8_t>& datagram);
|
||||
|
||||
void set_slaves_to_default();
|
||||
uint16_t slaves_detecting();
|
||||
void set_addresses_of_slaves(uint16_t address_base);
|
||||
void get_addresses_of_slaves();
|
||||
|
||||
/*
|
||||
* Тип адресации slave_address зависит от типа команды CommandT
|
||||
* Может иметь тип Position, Broadcast, Node
|
||||
* Logical не поддерживается
|
||||
*/
|
||||
template<typename TypeT, typename DirT, typename EcatDgDataT>
|
||||
void simple_send_datagram(typename TypeT::TSlaveAddress& slave_address, uint16_t offset, EcatDgDataT& data) {
|
||||
using TCommand = command::EcatCommand<TypeT, DirT>;
|
||||
datagram::EcatDatagram<TCommand, EcatDgDataT> datagram{ {{slave_address, offset}}, data };
|
||||
|
||||
telegram_.transfer(datagram);
|
||||
}
|
||||
|
||||
datagram::EcatTelegram& get_telegram() {
|
||||
return telegram_;
|
||||
}
|
||||
|
||||
eeprom::EEPROM& get_eeprom() {
|
||||
return eeprom_;
|
||||
}
|
||||
|
||||
uint16_t config_init();
|
||||
|
||||
bool is_ready() { return ready_; }
|
||||
|
||||
Statistic getStat() { return stat_;}
|
||||
|
||||
virtual int32_t Process(uint8_t * p_data, uint32_t len) override; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ecat
|
||||
private:
|
||||
enum {
|
||||
e_pktFirst,
|
||||
e_pktSecond,
|
||||
e_pktTotal
|
||||
};
|
||||
|
||||
static constexpr uint16_t max_number_of_slaves = 32;
|
||||
|
||||
TEthPkt * p_pkt_;
|
||||
TEthPkt * p_pkt_next_;
|
||||
|
||||
TEthPkt pkt_[e_pktTotal];
|
||||
|
||||
Mutex mut_;
|
||||
|
||||
free_rtos::Semaphore rx_sem_;
|
||||
|
||||
Eth& eth_;
|
||||
EthTxFlowIface& tx_flow_;
|
||||
|
||||
datagram::EcatTelegram telegram_;
|
||||
eeprom::EEPROM eeprom_;
|
||||
|
||||
TEthMacPorts port_id_; /// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
bool ready_;
|
||||
|
||||
Statistic stat_;
|
||||
|
||||
std::array<EcatSlave, max_number_of_slaves> slaves_;
|
||||
|
||||
uint16_t number_of_slaves_ = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_HPP_ */
|
||||
230
components/free_rtos/ethernet_industry/eth_ecat_command.hpp
Normal file
230
components/free_rtos/ethernet_industry/eth_ecat_command.hpp
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* eth_ecat_commands.hpp
|
||||
*
|
||||
* Created on: May 2, 2023
|
||||
* Author: algin
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_COMMAND_HPP_
|
||||
#define FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_COMMAND_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include "ethernet_industry/ethercattype.hpp"
|
||||
#include "ethernet_industry/eth_ecat_types.h"
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
namespace address {
|
||||
|
||||
// Slave addressing types
|
||||
using Position = int16_t;
|
||||
using Broadcast = uint16_t;
|
||||
using Node = uint16_t;
|
||||
using Logical = uint32_t;
|
||||
|
||||
/*
|
||||
struct Position {
|
||||
Position(int16_t val): val_{val} { }
|
||||
Position() { }
|
||||
|
||||
int16_t val_;
|
||||
};
|
||||
|
||||
struct Broadcast {
|
||||
Broadcast(uint16_t val): val_{val} { }
|
||||
Broadcast() { }
|
||||
|
||||
uint16_t val_;
|
||||
};
|
||||
|
||||
struct Node {
|
||||
Node(uint16_t val): val_{val} { }
|
||||
Node() { }
|
||||
|
||||
uint16_t val_;
|
||||
};
|
||||
|
||||
struct Logical {
|
||||
Logical(uint32_t val): val_{val} { }
|
||||
Logical() { }
|
||||
|
||||
uint32_t val_;
|
||||
};
|
||||
*/
|
||||
using SlaveTypes = std::tuple<Position, Broadcast, Node, Logical>;
|
||||
|
||||
// Register offset
|
||||
using Offset = uint16_t;
|
||||
|
||||
using PositionAddress = std::tuple<Position, Offset>;
|
||||
using BroadcastAddress = std::tuple<Broadcast, Offset>;
|
||||
using NodeAddress = std::tuple<Node, Offset>;
|
||||
using LogicalAddress = std::tuple<Logical>;
|
||||
|
||||
using Types = std::tuple<PositionAddress, BroadcastAddress, NodeAddress, LogicalAddress>;
|
||||
|
||||
} // namespace address
|
||||
|
||||
namespace command {
|
||||
|
||||
enum class DIR_INDEX : uint16_t {
|
||||
RD = 0,
|
||||
WR,
|
||||
RW,
|
||||
RMW,
|
||||
NO = RMW
|
||||
};
|
||||
|
||||
enum class TYPE_INDEX : uint16_t {
|
||||
AP = 0,
|
||||
B,
|
||||
FP,
|
||||
L
|
||||
};
|
||||
|
||||
|
||||
struct DirBase {
|
||||
|
||||
};
|
||||
|
||||
template<DIR_INDEX dir_index>
|
||||
struct Dir : public DirBase {
|
||||
static constexpr DIR_INDEX dir = dir_index;
|
||||
};
|
||||
|
||||
using RD = Dir<DIR_INDEX::RD>;
|
||||
using WR = Dir<DIR_INDEX::WR>;
|
||||
using RW = Dir<DIR_INDEX::RW>;
|
||||
using RMW = Dir<DIR_INDEX::RMW>;
|
||||
using NO = Dir<DIR_INDEX::NO>;
|
||||
|
||||
struct TypeBase {
|
||||
|
||||
};
|
||||
|
||||
template<TYPE_INDEX type_index>
|
||||
struct Type : public TypeBase {
|
||||
using TAddress = typename std::tuple_element<static_cast<size_t>(type_index), address::Types>::type;
|
||||
using TSlaveAddress = typename std::tuple_element<0, TAddress>::type;
|
||||
|
||||
static constexpr TYPE_INDEX type = type_index;
|
||||
|
||||
static constexpr ec_cmdtype get_cmd(DIR_INDEX dir) {
|
||||
std::array<std::array<ec_cmdtype, 4>, 4> commands = {{
|
||||
{{EC_CMD_APRD, EC_CMD_APWR, EC_CMD_APRW, EC_CMD_ARMW}},
|
||||
{{EC_CMD_BRD, EC_CMD_BWR, EC_CMD_BRW, EC_CMD_NOP}},
|
||||
{{EC_CMD_FPRD, EC_CMD_FPWR, EC_CMD_FPRW, EC_CMD_FRMW}},
|
||||
{{EC_CMD_LRD, EC_CMD_LWR, EC_CMD_LRW, EC_CMD_NOP}}
|
||||
}};
|
||||
|
||||
return commands[static_cast<uint16_t>(type)][static_cast<uint16_t>(dir)];
|
||||
}
|
||||
};
|
||||
|
||||
using AP = Type<TYPE_INDEX::AP>;
|
||||
using B = Type<TYPE_INDEX::B>;
|
||||
using FP = Type<TYPE_INDEX::FP>;
|
||||
using L = Type<TYPE_INDEX::L>;
|
||||
|
||||
class EcatCommandBase {
|
||||
public:
|
||||
EcatCommandBase(ec_cmdtype cmd)
|
||||
: cmd_{cmd} { }
|
||||
|
||||
EcatCommandBase()
|
||||
: cmd_{ec_cmdtype::EC_CMD_NOP} { }
|
||||
|
||||
uint8_t get_cmd() {
|
||||
return cmd_;
|
||||
}
|
||||
|
||||
private:
|
||||
ec_cmdtype cmd_;
|
||||
};
|
||||
|
||||
template<typename TypeT, typename DirT>
|
||||
class EcatCommand : public EcatCommandBase {
|
||||
static_assert(std::is_base_of<TypeBase, TypeT>::value == true, "TypeT should be derived from CMD::TypeBase");
|
||||
static_assert(std::is_base_of<DirBase, DirT>::value == true, "DirT should be derived from CMD::DirBase");
|
||||
|
||||
public:
|
||||
EcatCommand(typename TypeT::TAddress fields)
|
||||
: EcatCommandBase{TypeT::get_cmd(DirT::dir)}
|
||||
, address_{fields} { }
|
||||
|
||||
EcatCommand() { }
|
||||
|
||||
uint32_t get_address() {
|
||||
return address_.dword_;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename FieldsT>
|
||||
union Address
|
||||
{
|
||||
Address(FieldsT fields)
|
||||
: fields_{fields} { }
|
||||
|
||||
Address() { }
|
||||
|
||||
Address& operator=(const Address& other) {
|
||||
fields_ = other.fields_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FieldsT fields_;
|
||||
uint32_t dword_;
|
||||
};
|
||||
|
||||
Address<typename TypeT::TAddress> address_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Position addressing
|
||||
* arg0: Each slave increments Position. Slave is addressed if Position = 0.
|
||||
* arg1: Local register or memory address of the ESC
|
||||
*/
|
||||
using APRD = EcatCommand<AP, RD>;
|
||||
using APWR = EcatCommand<AP, WR>;
|
||||
using APRW = EcatCommand<AP, RW>;
|
||||
using ARMW = EcatCommand<AP, RMW>;
|
||||
|
||||
/*
|
||||
* Broadcast addressing
|
||||
* arg0: Each slave increments Position (not used for addressing)
|
||||
* arg1: Local register or memory address of the ESC
|
||||
*/
|
||||
using NOP = EcatCommand<B, NO>;
|
||||
using BRD = EcatCommand<B, RD>;
|
||||
using BRW = EcatCommand<B, RW>;
|
||||
using BWR = EcatCommand<B, WR>;
|
||||
|
||||
// Node addressing shortcuts
|
||||
|
||||
/*
|
||||
* arg0: Slave is addressed if Address matches Configured Station Address or Configured Station Alias (if enabled).
|
||||
* arg1: Local register or memory address of the ESC
|
||||
*/
|
||||
using FPRD = EcatCommand<FP, RD>;
|
||||
using FPRW = EcatCommand<FP, RW>;
|
||||
using FPWR = EcatCommand<FP, WR>;
|
||||
using FPMW = EcatCommand<FP, RMW>;
|
||||
|
||||
/*
|
||||
* Logical addressing
|
||||
* arg0: Logical Address (configured by FMMUs) Slave is addressed if FMMU configuration matches Address.
|
||||
*/
|
||||
using LRD = EcatCommand<L, RD>;
|
||||
using LRW = EcatCommand<L, RW>;
|
||||
using LWR = EcatCommand<L, WR>;
|
||||
|
||||
} // namespace command
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_COMMAND_HPP_ */
|
||||
70
components/free_rtos/ethernet_industry/eth_ecat_datagram.cpp
Normal file
70
components/free_rtos/ethernet_industry/eth_ecat_datagram.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* eth_ecat_datagram.cpp
|
||||
*
|
||||
* Created on: May 2, 2023
|
||||
* Author: algin
|
||||
*/
|
||||
|
||||
#include <ethernet_industry/eth_ecat_datagram.hpp>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
namespace datagram {
|
||||
|
||||
int32_t EcatTelegram::Process(uint8_t *p_data, uint32_t len) {
|
||||
buffer_in_.length = len + sizeof(TEthFrameHeader);
|
||||
|
||||
memcpy(buffer_in_.data, p_data - sizeof(TEthFrameHeader), buffer_in_.length);
|
||||
|
||||
rx_sem_.post();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EcatTelegram::pack(IEcatDatagram& first) {
|
||||
TEthFrameHeader *p_eth_hdr = new(buffer_out_.data) TEthFrameHeader{ {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
|
||||
ETH_PROT_ECAT_LE};
|
||||
TEcatFrameHeader *p_hdr = new(buffer_out_.data + sizeof(TEthFrameHeader)) TEcatFrameHeader{ .bits.length = 0,
|
||||
.bits.type = static_cast<uint16_t>(ec_network::PROTOCOL_TYPE)};
|
||||
uint8_t *p_datagram_first = buffer_out_.data + sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader);
|
||||
uint8_t *p_datagram_last = p_datagram_first;
|
||||
IEcatDatagram *next = &first;
|
||||
|
||||
while(next != nullptr) {
|
||||
p_datagram_last = next->pack(p_datagram_last);
|
||||
next = next->get_next();
|
||||
}
|
||||
|
||||
p_hdr->bits.length = p_datagram_last - p_datagram_first;
|
||||
buffer_out_.length = sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader) + p_hdr->bits.length;
|
||||
}
|
||||
|
||||
void EcatTelegram::unpack(IEcatDatagram& first) {
|
||||
TEthFrameHeader *p_eth_hdr = reinterpret_cast<TEthFrameHeader*>(buffer_in_.data);
|
||||
TEcatFrameHeader *p_hdr = reinterpret_cast<TEcatFrameHeader*>(buffer_in_.data + sizeof(TEthFrameHeader));
|
||||
uint8_t *p_datagram_first = buffer_in_.data + sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader);
|
||||
uint8_t *p_datagram_last = p_datagram_first;
|
||||
IEcatDatagram *next = &first;
|
||||
|
||||
while(next != nullptr) {
|
||||
p_datagram_last = next->unpack(p_datagram_last);
|
||||
next = next->get_next();
|
||||
}
|
||||
}
|
||||
|
||||
void EcatTelegram::transfer(IEcatDatagram& first) {
|
||||
pack(first);
|
||||
bool stat = tx_flow_.send(port_id_, buffer_out_.data, buffer_out_.length);
|
||||
|
||||
if(stat == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
rx_sem_.pend();
|
||||
unpack(first);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
205
components/free_rtos/ethernet_industry/eth_ecat_datagram.hpp
Normal file
205
components/free_rtos/ethernet_industry/eth_ecat_datagram.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* eth_ecat_datagram.hpp
|
||||
*
|
||||
* Created on: May 2, 2023
|
||||
* Author: algin
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_DATAGRAM_HPP_
|
||||
#define FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_DATAGRAM_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "ethernet/eth.hpp"
|
||||
#include "ethernet_industry/ethercattype.hpp"
|
||||
#include "ethernet_industry/eth_ecat_types.h"
|
||||
#include "ethernet_industry/eth_ecat_command.hpp"
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
namespace datagram {
|
||||
|
||||
using TEcatWkc = uint16_t;
|
||||
|
||||
template<typename EcatDgDataT>
|
||||
struct EcatDg {
|
||||
public:
|
||||
EcatDg(uint8_t cmd, uint32_t address, EcatDgDataT& data, ec_moredatagrams more = ec_moredatagrams::EC_MOREDATAGRAMS_LAST, uint8_t idx = 0, uint16_t irq = 0)
|
||||
: header_{
|
||||
cmd,
|
||||
idx,
|
||||
address,
|
||||
{.bits = {
|
||||
.len = sizeof(EcatDgDataT),
|
||||
.c = static_cast<uint16_t>(ec_circframe::EC_CIRCFRAME_NOT),
|
||||
.m = static_cast<uint16_t>(more)}},
|
||||
irq}
|
||||
, data_{data}
|
||||
, wkc_{0} { }
|
||||
|
||||
EcatDg(uint8_t cmd, uint32_t address, ec_moredatagrams more = ec_moredatagrams::EC_MOREDATAGRAMS_LAST, uint8_t idx = 0, uint16_t irq = 0)
|
||||
: header_{
|
||||
cmd,
|
||||
idx,
|
||||
address,
|
||||
{.bits = {
|
||||
.len = sizeof(EcatDgDataT),
|
||||
.c = static_cast<uint16_t>(ec_circframe::EC_CIRCFRAME_NOT),
|
||||
.m = static_cast<uint16_t>(more)}},
|
||||
irq}
|
||||
, wkc_{0} { }
|
||||
|
||||
EcatDg() { }
|
||||
|
||||
TEcatDgHeader& get_header() {
|
||||
return header_;
|
||||
}
|
||||
|
||||
EcatDgDataT& get_data() {
|
||||
return data_;
|
||||
}
|
||||
|
||||
TEcatWkc get_wkc() {
|
||||
return wkc_;
|
||||
}
|
||||
|
||||
private:
|
||||
TEcatDgHeader header_;
|
||||
EcatDgDataT data_;
|
||||
TEcatWkc wkc_;
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
class IEcatDatagram {
|
||||
public:
|
||||
IEcatDatagram(ec_moredatagrams more, TEcatWkc wkc)
|
||||
: more_{more}
|
||||
, wkc_{wkc}
|
||||
{ }
|
||||
|
||||
IEcatDatagram() { }
|
||||
|
||||
IEcatDatagram& operator+(IEcatDatagram &next) {
|
||||
more_ = ec_moredatagrams::EC_MOREDATAGRAMS_MORE;
|
||||
next_ = &next;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
IEcatDatagram* get_next() {
|
||||
return next_;
|
||||
}
|
||||
|
||||
IEcatDatagram& set_next(IEcatDatagram &next) {
|
||||
|
||||
return operator+(next);
|
||||
}
|
||||
|
||||
virtual uint8_t* pack(uint8_t *raw) = 0;
|
||||
virtual uint8_t* unpack(uint8_t *raw) = 0;
|
||||
|
||||
TEcatWkc get_wkc() {
|
||||
return wkc_;
|
||||
}
|
||||
|
||||
protected:
|
||||
ec_moredatagrams more_;
|
||||
TEcatWkc wkc_;
|
||||
|
||||
private:
|
||||
IEcatDatagram *next_{nullptr};
|
||||
};
|
||||
|
||||
template<typename CommandT, typename EcatDgDataT>
|
||||
class EcatDatagram : public IEcatDatagram {
|
||||
static_assert(std::is_base_of<command::EcatCommandBase, CommandT>::value == true, "CommandT should be derived from ECatCommandBase");
|
||||
|
||||
public:
|
||||
EcatDatagram(CommandT command, EcatDgDataT &data_out, EcatDgDataT &data_in)
|
||||
: IEcatDatagram{ec_moredatagrams::EC_MOREDATAGRAMS_LAST, 0x0000}
|
||||
, command_{command}
|
||||
, data_out_{&data_out}
|
||||
, data_in_{&data_in} { }
|
||||
|
||||
EcatDatagram(CommandT command, EcatDgDataT &data)
|
||||
: IEcatDatagram{ec_moredatagrams::EC_MOREDATAGRAMS_LAST, 0x0000}
|
||||
, command_{command}
|
||||
, data_out_{&data}
|
||||
, data_in_{&data} { }
|
||||
|
||||
EcatDatagram(CommandT command)
|
||||
: IEcatDatagram{ec_moredatagrams::EC_MOREDATAGRAMS_LAST, 0x0000}
|
||||
, command_{command} { }
|
||||
|
||||
EcatDatagram() { }
|
||||
|
||||
virtual uint8_t* pack(uint8_t *raw) override {
|
||||
EcatDg<EcatDgDataT> *p_dg;
|
||||
|
||||
if(data_out_ != nullptr) {
|
||||
p_dg = new(raw) EcatDg<EcatDgDataT> {command_.get_cmd(), command_.get_address(), *data_out_, more_};
|
||||
}else{
|
||||
p_dg = new(raw) EcatDg<EcatDgDataT> {command_.get_cmd(), command_.get_address(), more_};
|
||||
}
|
||||
|
||||
(void)p_dg;
|
||||
|
||||
return (raw + sizeof(EcatDg<EcatDgDataT>));
|
||||
}
|
||||
|
||||
virtual uint8_t* unpack(uint8_t *raw) override {
|
||||
EcatDg<EcatDgDataT> *p_dg = reinterpret_cast<EcatDg<EcatDgDataT>*>(raw);
|
||||
|
||||
if(data_in_ != nullptr) {
|
||||
*data_in_ = p_dg->get_data();
|
||||
}
|
||||
|
||||
wkc_ = p_dg->get_wkc();
|
||||
|
||||
return (raw + sizeof(EcatDg<EcatDgDataT>));
|
||||
}
|
||||
|
||||
private:
|
||||
CommandT command_;
|
||||
EcatDgDataT *data_out_{nullptr};
|
||||
EcatDgDataT *data_in_{nullptr};
|
||||
};
|
||||
|
||||
class EcatTelegram : public Handler {
|
||||
public:
|
||||
EcatTelegram(Eth& eth)
|
||||
: eth_{eth}
|
||||
, tx_flow_{*eth.getTxFlowPtr()} {
|
||||
eth_.getEthStackPtr()->Register(ETH_PROT_ECAT_LE, this);
|
||||
}
|
||||
|
||||
virtual int32_t Process(uint8_t *p_data, uint32_t len) override;
|
||||
|
||||
void init(TEthMacPorts port_id) {
|
||||
port_id_ = port_id;
|
||||
}
|
||||
|
||||
void transfer(IEcatDatagram& first);
|
||||
|
||||
private:
|
||||
Eth& eth_;
|
||||
EthTxFlowIface& tx_flow_;
|
||||
TEthMacPorts port_id_;
|
||||
|
||||
free_rtos::Semaphore rx_sem_;
|
||||
|
||||
TEthPkt buffer_out_;
|
||||
TEthPkt buffer_in_;
|
||||
|
||||
void pack(IEcatDatagram& first);
|
||||
void unpack(IEcatDatagram& first);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_DATAGRAM_HPP_ */
|
||||
82
components/free_rtos/ethernet_industry/eth_ecat_eeprom.hpp
Normal file
82
components/free_rtos/ethernet_industry/eth_ecat_eeprom.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* eth_ecat_eeprom.hpp
|
||||
*
|
||||
* Created on: May 2, 2023
|
||||
* Author: algin
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_EEPROM_HPP_
|
||||
#define FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_EEPROM_HPP_
|
||||
|
||||
#include <ethernet_industry/eth_ecat_datagram.hpp>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
namespace eeprom {
|
||||
|
||||
class EEPROM {
|
||||
public:
|
||||
EEPROM(datagram::EcatTelegram& telegram)
|
||||
: telegram_{telegram} { }
|
||||
|
||||
template<typename TypeT>
|
||||
void wait_busy(typename TypeT::TSlaveAddress& slave_address) {
|
||||
using TCommand = command::EcatCommand<TypeT, command::RD>;
|
||||
volatile uint16_t stat;
|
||||
datagram::EcatDatagram<TCommand, volatile uint16_t> datagram{ {{slave_address, ECT_REG_EEPSTAT}}, stat };
|
||||
|
||||
do {
|
||||
telegram_.transfer(datagram);
|
||||
}while((stat & EC_ESTAT_BUSY) != 0);
|
||||
}
|
||||
|
||||
template<typename TypeT, typename DirT>
|
||||
void control_register(typename TypeT::TSlaveAddress& slave_address, ec_ecmdtype eeprom_cmd, uint16_t eeprom_address) {
|
||||
using TCommand = command::EcatCommand<TypeT, DirT>;
|
||||
std::array<uint16_t, 2> request{eeprom_cmd, eeprom_address};
|
||||
datagram::EcatDatagram<TCommand, std::array<uint16_t, 2>> datagram{ {{slave_address, ECT_REG_EEPCTL}}, request };
|
||||
|
||||
telegram_.transfer(datagram);
|
||||
}
|
||||
|
||||
template<typename TypeT, typename DirT, typename EcatDgDataT>
|
||||
void data_register(typename TypeT::TSlaveAddress& slave_address, EcatDgDataT& data) {
|
||||
using TCommand = command::EcatCommand<TypeT, DirT>;
|
||||
datagram::EcatDatagram<TCommand, EcatDgDataT> datagram{ {{slave_address, ECT_REG_EEPDAT}}, data };
|
||||
|
||||
telegram_.transfer(datagram);
|
||||
}
|
||||
|
||||
template<typename TypeT, typename EcatDgDataT>
|
||||
void read(typename TypeT::TSlaveAddress& slave_address, uint16_t eeprom_address, EcatDgDataT& data) {
|
||||
wait_busy<TypeT>(slave_address);
|
||||
|
||||
control_register<TypeT, command::WR>(slave_address, EC_ECMD_READ, eeprom_address);
|
||||
|
||||
wait_busy<TypeT>(slave_address);
|
||||
|
||||
data_register<TypeT, command::RD, EcatDgDataT>(slave_address, data);
|
||||
}
|
||||
|
||||
template<typename TypeT, typename EcatDgDataT>
|
||||
void write(typename TypeT::TSlaveAddress& slave_address, uint16_t eeprom_address, EcatDgDataT& data) {
|
||||
wait_busy<TypeT>(slave_address);
|
||||
|
||||
data_register<TypeT, command::WR, EcatDgDataT>(slave_address, data);
|
||||
|
||||
wait_busy<TypeT>(slave_address);
|
||||
|
||||
control_register<TypeT, command::WR>(slave_address, EC_ECMD_WRITE, eeprom_address);
|
||||
}
|
||||
|
||||
private:
|
||||
datagram::EcatTelegram& telegram_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_EEPROM_HPP_ */
|
||||
60
components/free_rtos/ethernet_industry/eth_ecat_types.h
Normal file
60
components/free_rtos/ethernet_industry/eth_ecat_types.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* eth_ecat_types.h
|
||||
*
|
||||
* Created on: 16 <EFBFBD><EFBFBD><EFBFBD>. 2023 <EFBFBD>.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_TYPES_H_
|
||||
#define FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ETH_PROT_ECAT_LE 0xa488 /// ETHERCAT
|
||||
#define ETH_PROT_ECAT_BE 0x88a4 /// ETHERCAT
|
||||
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>( <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> be)
|
||||
typedef struct
|
||||
{
|
||||
uint16_t length : 11; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 11
|
||||
uint16_t reserved : 1;
|
||||
uint16_t type : 4;
|
||||
}TEcatFrameHeaderBits;
|
||||
|
||||
/**
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ethercat
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
uint16_t all;
|
||||
TEcatFrameHeaderBits bits;
|
||||
}TEcatFrameHeader;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t len : 11;
|
||||
uint16_t reserved : 3;
|
||||
uint16_t c : 1; /// Circulating Datagram
|
||||
uint16_t m : 1; /// More EtherCAT Datagrams following
|
||||
}TEcatDgLenBits;
|
||||
|
||||
typedef union {
|
||||
uint16_t all;
|
||||
TEcatDgLenBits bits;
|
||||
}TEcatDgLen;
|
||||
|
||||
/**
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ethercat
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>( <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> be),
|
||||
* <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 8 <EFBFBD><EFBFBD><EFBFBD>.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint8_t idx;
|
||||
uint32_t address;
|
||||
TEcatDgLen len;
|
||||
uint16_t irq;
|
||||
} __attribute__ ((packed)) TEcatDgHeader; /// Ethercat datagram header
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_TYPES_H_ */
|
||||
300
components/free_rtos/ethernet_industry/ethercattype.hpp
Normal file
300
components/free_rtos/ethernet_industry/ethercattype.hpp
Normal file
@ -0,0 +1,300 @@
|
||||
/** \file
|
||||
* \brief
|
||||
* Типы данных и константы, используемые для работы с EtherCAT сетью.
|
||||
*/
|
||||
#ifndef ETHERCAT_MASTER_ETHERCATTYPE_HPP
|
||||
#define ETHERCAT_MASTER_ETHERCATTYPE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
const std::uint16_t COUNTER_INIT = 0u;
|
||||
const std::uint16_t MIN_DATA_VECTOR_SIZE = 2u;
|
||||
const std::uint16_t ONE_BYTE_SHIFT = 8u;
|
||||
const std::uint16_t TWO_BYTE_SHIFT = 16u;
|
||||
const std::uint16_t THREE_BYTE_SHIFT = 24u;
|
||||
|
||||
|
||||
const std::uint16_t RESERVED_VALUE = 0;
|
||||
|
||||
/*!
|
||||
* Constants used to add_slaves Ethernet network when working with EtherCAT.
|
||||
*/
|
||||
enum class ec_network : std::uint16_t {
|
||||
/** Port used to send EtherCAT datagrams */
|
||||
PROTOCOL_TYPE = 1u,
|
||||
ETHERCAT_PORT = 34980u
|
||||
|
||||
};
|
||||
|
||||
enum class sync_manager : std::uint16_t {
|
||||
SYNC_M0 = 0,
|
||||
SYNC_M1,
|
||||
SYNC_M2,
|
||||
SYNC_M3
|
||||
};
|
||||
enum class fmmu : std::uint16_t {
|
||||
FMMU0 = 0,
|
||||
FMMU1,
|
||||
FMMU2,
|
||||
FMMU3
|
||||
};
|
||||
|
||||
enum class DataDirection : std::uint8_t {
|
||||
READ = 0x1,
|
||||
WRITE = 0x2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Структура данных описывающая базовые настройки буффера данных, обрабатывающего меилбоксы.
|
||||
*/
|
||||
struct MbxBufferProperties {
|
||||
/** Адрес в памяти подчиненного устройства для доступа на запись запросов */
|
||||
std::uint16_t mbx_write_adr;
|
||||
/** Размер буфера данных, обрабатывающего меилбоксы */
|
||||
std::uint16_t mbx_write_len;
|
||||
/** Адрес в памяти подчиненного устройства для доступа на чтение ответов */
|
||||
std::uint16_t mbx_read_adr;
|
||||
/** Размер буфера данных, обрабатывающего меилбоксы */
|
||||
std::uint16_t mbx_read_len;
|
||||
/** Адрес в памяти подчиненного устройства для доступа на чтение ответов */
|
||||
std::uint16_t pdo_output_adr;
|
||||
/** Адрес в памяти подчиненного устройства для доступа на чтение ответов */
|
||||
std::uint16_t pdo_input_adr;
|
||||
};
|
||||
|
||||
/*!
|
||||
* EtherCAT commands types
|
||||
*/
|
||||
enum ec_cmdtype : std::uint16_t {
|
||||
/** No operation */
|
||||
EC_CMD_NOP = 0x0,
|
||||
/** Auto Increment Read */
|
||||
EC_CMD_APRD,
|
||||
/** Auto Increment Write */
|
||||
EC_CMD_APWR,
|
||||
/** Auto Increment Read Write */
|
||||
EC_CMD_APRW,
|
||||
/** Configured Address Read */
|
||||
EC_CMD_FPRD,
|
||||
/** Configured Address Write */
|
||||
EC_CMD_FPWR,
|
||||
/** Configured Address Read Write */
|
||||
EC_CMD_FPRW,
|
||||
/** Broadcast Read */
|
||||
EC_CMD_BRD,
|
||||
/** Broadcast Write */
|
||||
EC_CMD_BWR,
|
||||
/** Broadcast Read Write */
|
||||
EC_CMD_BRW,
|
||||
/** Logical Memory Read */
|
||||
EC_CMD_LRD,
|
||||
/** Logical Memory Write */
|
||||
EC_CMD_LWR,
|
||||
/** Logical Memory Read Write */
|
||||
EC_CMD_LRW,
|
||||
/** Auto Increment Read Multiple Write */
|
||||
EC_CMD_ARMW,
|
||||
/** Configured Read Multiple Write */
|
||||
EC_CMD_FRMW
|
||||
/** Reserved */
|
||||
} ;
|
||||
|
||||
/** Ethercat registers */
|
||||
enum ec_reg_offset : std::uint16_t
|
||||
{
|
||||
ECT_REG_TYPE = 0x0000,
|
||||
ECT_REG_PORTDES = 0x0007,
|
||||
ECT_REG_ESCSUP = 0x0008,
|
||||
ECT_REG_STADR = 0x0010,
|
||||
ECT_REG_ALIAS = 0x0012,
|
||||
ECT_REG_DLCTL = 0x0100,
|
||||
ECT_REG_DLPORT = 0x0101,
|
||||
ECT_REG_DLALIAS = 0x0103,
|
||||
ECT_REG_DLSTAT = 0x0110,
|
||||
ECT_REG_ALCTL = 0x0120,
|
||||
ECT_REG_ALSTAT = 0x0130,
|
||||
ECT_REG_ALSTATCODE = 0x0134,
|
||||
ECT_REG_PDICTL = 0x0140,
|
||||
ECT_REG_IRQMASK = 0x0200,
|
||||
ECT_REG_RXERR = 0x0300,
|
||||
ECT_REG_FRXERR = 0x0308,
|
||||
ECT_REG_EPUECNT = 0x030C,
|
||||
ECT_REG_PECNT = 0x030D,
|
||||
ECT_REG_PECODE = 0x030E,
|
||||
ECT_REG_LLCNT = 0x0310,
|
||||
ECT_REG_WD_DIV = 0x0400,
|
||||
ECT_REG_WD_TIME_PDI = 0x0410,
|
||||
ECT_REG_WD_TIME_PD = 0x0420,
|
||||
ECT_REG_WDCNT = 0x0442,
|
||||
ECT_REG_EEPCFG = 0x0500,
|
||||
ECT_REG_EEPCTL = 0x0502,
|
||||
ECT_REG_EEPSTAT = 0x0502,
|
||||
ECT_REG_EEPADR = 0x0504,
|
||||
ECT_REG_EEPDAT = 0x0508,
|
||||
ECT_REG_FMMU0 = 0x0600,
|
||||
ECT_REG_FMMU1 = ECT_REG_FMMU0 + 0x10,
|
||||
ECT_REG_FMMU2 = ECT_REG_FMMU1 + 0x10,
|
||||
ECT_REG_FMMU3 = ECT_REG_FMMU2 + 0x10,
|
||||
ECT_REG_SM0 = 0x0800,
|
||||
ECT_REG_SM1 = ECT_REG_SM0 + 0x08,
|
||||
ECT_REG_SM2 = ECT_REG_SM1 + 0x08,
|
||||
ECT_REG_SM3 = ECT_REG_SM2 + 0x08,
|
||||
ECT_REG_SM0STAT = ECT_REG_SM0 + 0x05,
|
||||
ECT_REG_SM1STAT = ECT_REG_SM1 + 0x05,
|
||||
ECT_REG_SM1ACT = ECT_REG_SM1 + 0x06,
|
||||
ECT_REG_SM1CONTR = ECT_REG_SM1 + 0x07,
|
||||
ECT_REG_DCTIME0 = 0x0900,
|
||||
ECT_REG_DCTIME1 = 0x0904,
|
||||
ECT_REG_DCTIME2 = 0x0908,
|
||||
ECT_REG_DCTIME3 = 0x090C,
|
||||
ECT_REG_DCSYSTIME = 0x0910,
|
||||
ECT_REG_DCSOF = 0x0918,
|
||||
ECT_REG_DCSYSOFFSET = 0x0920,
|
||||
ECT_REG_DCSYSDELAY = 0x0928,
|
||||
ECT_REG_DCSYSDIFF = 0x092C,
|
||||
ECT_REG_DCSPEEDCNT = 0x0930,
|
||||
ECT_REG_DCTIMEFILT = 0x0934,
|
||||
ECT_REG_DCCUC = 0x0980,
|
||||
ECT_REG_DCSYNCACT = 0x0981,
|
||||
ECT_REG_DCSTART0 = 0x0990,
|
||||
ECT_REG_DCCYCLE0 = 0x09A0,
|
||||
ECT_REG_DCCYCLE1 = 0x09A4
|
||||
};
|
||||
|
||||
/** Ethercat registers */
|
||||
enum ec_pdo_assigment : std::uint16_t {
|
||||
rx = 0x1C12,
|
||||
tx = 0X1c13
|
||||
};
|
||||
|
||||
enum MailboxesRegs {
|
||||
WRITE = 0,
|
||||
READ,
|
||||
EMPTY,
|
||||
AVAILABLE
|
||||
};
|
||||
|
||||
/** Possible EtherCAT slave states */
|
||||
typedef enum
|
||||
{
|
||||
/** No valid state. */
|
||||
EC_STATE_NONE = 0x00,
|
||||
/** Init state*/
|
||||
EC_STATE_INIT = 0x01,
|
||||
/** Pre-operational. */
|
||||
EC_STATE_PRE_OP = 0x02,
|
||||
/** Boot state*/
|
||||
EC_STATE_BOOT = 0x03,
|
||||
/** Safe-operational. */
|
||||
EC_STATE_SAFE_OP = 0x04,
|
||||
/** Operational */
|
||||
EC_STATE_OPERATIONAL = 0x08,
|
||||
/** Error or ACK error */
|
||||
EC_STATE_ACK = 0x10,
|
||||
EC_STATE_ERROR = 0x10
|
||||
} ec_state;
|
||||
|
||||
/** EEprom state machine read size */
|
||||
constexpr std::uint32_t EC_ESTAT_R64 = 0x0040;
|
||||
/** EEprom state machine busy flag */
|
||||
constexpr std::uint32_t EC_ESTAT_BUSY = 0x8000;
|
||||
/** EEprom state machine error flag mask */
|
||||
constexpr std::uint32_t EC_ESTAT_EMASK = 0x7800;
|
||||
/** EEprom state machine error acknowledge */
|
||||
constexpr std::uint32_t EC_ESTAT_NACK = 0x2000;
|
||||
|
||||
/** Ethercat EEprom command types */
|
||||
typedef enum
|
||||
{
|
||||
/** No operation */
|
||||
EC_ECMD_NOP = 0x0000,
|
||||
/** Read */
|
||||
EC_ECMD_READ = 0x0100,
|
||||
/** Write */
|
||||
EC_ECMD_WRITE = 0x0201,
|
||||
/** Reload */
|
||||
EC_ECMD_RELOAD = 0x0300
|
||||
} ec_ecmdtype;
|
||||
|
||||
/** Item offsets in SII general section */
|
||||
enum
|
||||
{
|
||||
ECT_SII_MANUF = 0x0008,
|
||||
ECT_SII_ID = 0x000a,
|
||||
ECT_SII_REV = 0x000c,
|
||||
ECT_SII_BOOTRXMBX = 0x0014,
|
||||
ECT_SII_BOOTTXMBX = 0x0016,
|
||||
ECT_SII_MBXSIZE = 0x0019,
|
||||
ECT_SII_TXMBXADR = 0x001a,
|
||||
ECT_SII_RXMBXADR = 0x0018,
|
||||
ECT_SII_MBXPROTO = 0x001c,
|
||||
ECT_PDOOUTPUTADR = 0x0078,
|
||||
ECT_PDOINPUTADR = 0x007c
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
* Circulating frames bit
|
||||
*/
|
||||
enum class ec_circframe : std::uint16_t {
|
||||
/** Frame is not circulating */
|
||||
EC_CIRCFRAME_NOT = 0u,
|
||||
/** Frame has circulated once */
|
||||
EC_CIRCFRAME_ONCE,
|
||||
} ;
|
||||
|
||||
/** standard SM0 flags configuration for mailbox slaves */
|
||||
constexpr std::uint32_t EC_DEFAULTMBXSM0 = 0x00010026;
|
||||
/** standard SM1 flags configuration for mailbox slaves */
|
||||
constexpr std::uint32_t EC_DEFAULTMBXSM1 = 0x00010022;
|
||||
/** standard SM2 flags configuration for mailbox slaves */
|
||||
constexpr std::uint32_t EC_DEFAULTMBXSM2 = 0x00010074;
|
||||
/** standard SM3 flags configuration for mailbox slaves */
|
||||
constexpr std::uint32_t EC_DEFAULTMBXSM3 = 0x00010030;
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* More EtherCAT datagrams bit
|
||||
*/
|
||||
enum ec_moredatagrams : std::uint16_t {
|
||||
/** Last EtherCAT datagram */
|
||||
EC_MOREDATAGRAMS_LAST = 0u,
|
||||
/** More EtherCAT datagrams will follow */
|
||||
EC_MOREDATAGRAMS_MORE,
|
||||
} ;
|
||||
|
||||
|
||||
/** EtherCAT Frame Header :
|
||||
* <br>Length - 11 bit : Length of the EtherCAT datagrams (excl. FCS)
|
||||
* <br>Reserved - 1 bit: Reserved, 0
|
||||
* <br>Type - 4 bit : Protocol type. Only EtherCAT commands (Type = 0x1) are supported by ESCs.
|
||||
*/
|
||||
struct EthercatFrameHeader {
|
||||
enum EthercatFrameHeaderSizes : std::uint16_t {
|
||||
RESERVED = 1u,
|
||||
TYPE = 4u,
|
||||
LENGHT = 11u
|
||||
};
|
||||
|
||||
|
||||
std::uint16_t lenght : EthercatFrameHeaderSizes::LENGHT;
|
||||
std::uint16_t res : EthercatFrameHeaderSizes::RESERVED;
|
||||
std::uint16_t type : EthercatFrameHeaderSizes::TYPE;
|
||||
};
|
||||
|
||||
constexpr static std::uint16_t write_synch_manager_buffer_size = 256;
|
||||
constexpr static std::uint16_t read_synch_manager_buffer_size = 256;
|
||||
|
||||
} // namespace ethercat
|
||||
|
||||
|
||||
#endif //ETHERCAT_MASTER_ETHERCATTYPE_HPP
|
||||
206
components/free_rtos/ethernet_ip/eth_arp.cpp
Normal file
206
components/free_rtos/ethernet_ip/eth_arp.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* eth_arp.cpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet_ip/eth_arp.hpp"
|
||||
#include "ethernet/eth_frame.h"
|
||||
#include "ethernet_ip/eth_prots_id.h"
|
||||
#include "ethernet_ip/eth_ip_types.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#define ARP_ETH_TYPE_BE 0x1000
|
||||
|
||||
void free_rtos::clock_timeout(ClockP_Object * obj, void * arg)
|
||||
{
|
||||
EthArp * p_arp = ( EthArp *)arg;
|
||||
|
||||
/// Çàïðàøèâàåì ñîáñòâåííûé ip
|
||||
if (p_arp->tmrGratuitous_.tick(100))
|
||||
{
|
||||
if (p_arp->table_mac_.empty()) {
|
||||
p_arp->request(p_arp->self_ip_);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& item : p_arp->table_ip_)
|
||||
{
|
||||
auto& ip_data = item.second;
|
||||
if (ip_data.tmr.tick(100))
|
||||
{
|
||||
if (++ip_data.attemps >= p_arp->max_attemps_)
|
||||
{
|
||||
ip_data.tmr.stop();
|
||||
ip_data.attemps = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_arp->request(item.first); /// Çàïðîñ mac àäðåñà ïî ip
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_rtos::EthArp::EthArp(EthStackIface& eth_stack) :
|
||||
eth_stack_{eth_stack}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool free_rtos::EthArp::init(TEthMacPorts eth_port_id, uint64_t self_mac, uint32_t self_ip)
|
||||
{
|
||||
self_mac_ = self_mac;
|
||||
self_ip_ = self_ip;
|
||||
|
||||
eth_port_id_ = eth_port_id;
|
||||
|
||||
init_request_pkt(self_mac_, self_ip_);
|
||||
|
||||
clock_.init(100, free_rtos::clock_timeout, this); /// 100ìñ
|
||||
|
||||
tmrGratuitous_.start(1000); /// 1 ðàç â ñåêóíäó
|
||||
|
||||
clock_.start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void free_rtos::EthArp::init_request_pkt(uint64_t self_mac, uint32_t self_ip)
|
||||
{
|
||||
TArpHeader * arp_hdr = (TArpHeader *)(request_pkt_.data + sizeof(TEthFrameHeader));
|
||||
|
||||
/// Çàïîëíÿåì çàãîëîâîê ARP
|
||||
memcpy(arp_hdr->ar_sha, &self_mac_, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
memset(arp_hdr->ar_tha, 0, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
memcpy(arp_hdr->ar_spa, &self_ip_, ETH_IP_ADDR_LEN);
|
||||
|
||||
arp_hdr->ar_op = arp_opr_be_[e_oprRequest];
|
||||
arp_hdr->ar_hrd = ARP_ETH_TYPE_BE;
|
||||
arp_hdr->ar_pro = ETH_PROT_IP_BE;
|
||||
|
||||
arp_hdr->ar_hln = ETH_FRAME_MAC_ADDR_LEN_BYTES;
|
||||
|
||||
arp_hdr->ar_pln = ETH_IP_ADDR_LEN;
|
||||
}
|
||||
|
||||
bool free_rtos::EthArp::request(uint32_t ip)
|
||||
{
|
||||
TArpHeader * arp_hdr = (TArpHeader *)(request_pkt_.data + sizeof(TEthFrameHeader));
|
||||
|
||||
/// Êîïèðóåì ip-àäðåñ äëÿ çàïðîñà
|
||||
memcpy(arp_hdr->ar_tpa, &ip, ETH_IP_ADDR_LEN);
|
||||
|
||||
request_pkt_.length = sizeof(TArpHeader);
|
||||
|
||||
/// Øèðîêîâåùàòåëüíûé çàïðîñ
|
||||
return eth_stack_.send_pkt(eth_port_id_, ETH_FRAME_MAC_ADDR_BROADCAST, ETH_PROT_ARP_BE, request_pkt_);
|
||||
}
|
||||
|
||||
bool free_rtos::EthArp::try_request(uint32_t ip)
|
||||
{
|
||||
ArpIpReqData * p_ip_req_data = nullptr;
|
||||
auto item = table_ip_.find(ip);
|
||||
|
||||
if (item == table_ip_.end())
|
||||
{
|
||||
p_ip_req_data = &table_ip_[ip]; ///
|
||||
}
|
||||
else
|
||||
{
|
||||
p_ip_req_data = &item->second;
|
||||
if (p_ip_req_data->mac != 0) {
|
||||
return true; /// Ìàê àäðåñ óæå èçâåñòåí
|
||||
}
|
||||
else if (p_ip_req_data->tmr.is_started()) {
|
||||
return true; /// Îïðîñ óæå èäåò
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
p_ip_req_data->attemps = 0;
|
||||
p_ip_req_data->tmr.start(1000); /// Îïðîñ 1 ðàçâ â ñåê
|
||||
|
||||
return request(ip);
|
||||
}
|
||||
|
||||
void free_rtos::EthArp::add(uint64_t mac, uint32_t ip) {
|
||||
table_mac_[mac] = ip;
|
||||
|
||||
auto& item = table_ip_[ip];
|
||||
|
||||
item.mac = mac;
|
||||
item.attemps = 0;
|
||||
item.tmr.stop();
|
||||
}
|
||||
|
||||
bool free_rtos::EthArp::getIpAddr(uint64_t mac, uint32_t& ip) {
|
||||
auto item = table_mac_.find(mac);
|
||||
|
||||
if (item == table_mac_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ip = item->second;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool free_rtos::EthArp::getMacAddr(uint32_t ip, uint64_t& mac) {
|
||||
auto item = table_ip_.find(ip);
|
||||
|
||||
if (item == table_ip_.end()) {
|
||||
try_request(ip);
|
||||
return false;
|
||||
}
|
||||
|
||||
mac = item->second.mac;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t free_rtos::EthArp::Process(uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
TArpHeader * arp_hdr = (TArpHeader *)(p_data);
|
||||
uint16_t type = arp_hdr->ar_op;
|
||||
|
||||
uint64_t mac_sender = 0;
|
||||
uint32_t ip_sender = 0;
|
||||
|
||||
memcpy(&mac_sender, arp_hdr->ar_sha, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
memcpy(&ip_sender, arp_hdr->ar_spa, ETH_IP_ADDR_LEN);
|
||||
|
||||
/**
|
||||
* åñëè ip == 0, òî ýòî çàïðîñ "Who has....".
|
||||
* Îòâå÷àòü íà íåãî íå íóæíî.
|
||||
*/
|
||||
if (ip_sender == 0) {
|
||||
return 0;
|
||||
}
|
||||
/// Äîáàâëÿåì çàïèñü â arp-òàáëèöó
|
||||
add(mac_sender, ip_sender);
|
||||
|
||||
if ( type == arp_opr_be_[e_oprRequest])
|
||||
{
|
||||
uint32_t ip_target;
|
||||
memcpy(&ip_target, arp_hdr->ar_tpa, ETH_IP_ADDR_LEN);
|
||||
|
||||
if (ip_target == self_ip_)
|
||||
{
|
||||
/// Òèï ïàêåòà - îòâåò
|
||||
arp_hdr->ar_op = arp_opr_be_[e_oprReply];
|
||||
/// Ìåíÿåì ìåñòàìè mac àäðåñ
|
||||
memcpy(arp_hdr->ar_tha, arp_hdr->ar_sha, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
memcpy(arp_hdr->ar_sha, &self_mac_, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
/// Ìåíÿåì ìåñòàìè ip àäðåñ
|
||||
memcpy(arp_hdr->ar_tpa, arp_hdr->ar_spa, ETH_IP_ADDR_LEN);
|
||||
memcpy(arp_hdr->ar_spa, &self_ip_, ETH_IP_ADDR_LEN);
|
||||
|
||||
/// Îòïðàâëÿåì ðàçìåð ïàêåòà äëÿ îòïðàâêè
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
79
components/free_rtos/ethernet_ip/eth_arp.hpp
Normal file
79
components/free_rtos/ethernet_ip/eth_arp.hpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* eth_arp.hpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_ARP_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_ARP_HPP_
|
||||
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
#include "ethernet_ip/eth_arp_iface.hpp"
|
||||
#include "ethernet_ip/eth_stack_iface.hpp"
|
||||
#include "handler_store/handler.hpp"
|
||||
#include "clock/clock.hpp"
|
||||
#include "timer_sw/timer_sw.hpp"
|
||||
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthArp : public Handler, public EthArpIface {
|
||||
public:
|
||||
EthArp(EthStackIface& eth_stack);
|
||||
|
||||
bool init(TEthMacPorts eth_port_id, uint64_t self_mac, uint32_t self_ip);
|
||||
|
||||
bool getIpAddr(uint64_t mac, uint32_t& ip);
|
||||
|
||||
virtual bool getMacAddr(uint32_t ip, uint64_t& mac) override;
|
||||
|
||||
bool try_request(uint32_t ip);
|
||||
|
||||
virtual int32_t Process(uint8_t * p_data, uint32_t len) override;
|
||||
private:
|
||||
bool request(uint32_t ip);
|
||||
|
||||
void add(uint64_t mac, uint32_t ip);
|
||||
|
||||
void init_request_pkt(uint64_t self_mac, uint32_t self_ip);
|
||||
|
||||
friend void clock_timeout(ClockP_Object * obj, void * arg);
|
||||
private:
|
||||
enum Operations {
|
||||
e_oprRequest,
|
||||
e_oprReply,
|
||||
e_oprTotal
|
||||
};
|
||||
|
||||
struct ArpIpReqData {
|
||||
uint64_t mac = 0; /// Ìàê-àäðåñ
|
||||
uint32_t attemps = 0; /// Êîëèò÷åñòâî ïîïûòîê çàïðîñà
|
||||
TimerSw tmr; /// Òàéìåð çàïðîñîâ
|
||||
};
|
||||
|
||||
static const uint32_t pkt_len = 42;
|
||||
const uint16_t arp_opr_be_[e_oprTotal] = {0x0100, 0x0200};
|
||||
const uint32_t max_attemps_ = 8;
|
||||
|
||||
TEthPkt request_pkt_;
|
||||
|
||||
std::map<uint64_t, uint32_t> table_mac_; /// Êëþ÷ mac, çíà÷åíèå ip
|
||||
std::map<uint32_t, ArpIpReqData> table_ip_; /// Êëþ÷ ip,
|
||||
|
||||
uint64_t self_mac_;
|
||||
uint32_t self_ip_;
|
||||
|
||||
TEthMacPorts eth_port_id_;
|
||||
|
||||
EthStackIface& eth_stack_;
|
||||
|
||||
Clock clock_;
|
||||
|
||||
TimerSw tmrGratuitous_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_ARP_HPP_ */
|
||||
24
components/free_rtos/ethernet_ip/eth_arp_iface.hpp
Normal file
24
components/free_rtos/ethernet_ip/eth_arp_iface.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* eth_arp_iface.hpp
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_ARP_IFACE_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_ARP_IFACE_HPP_
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthArpIface {
|
||||
public:
|
||||
virtual bool getMacAddr(uint32_t ip, uint64_t& mac) = 0;
|
||||
|
||||
virtual ~EthArpIface() {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_ARP_IFACE_HPP_ */
|
||||
27
components/free_rtos/ethernet_ip/eth_checksum.c
Normal file
27
components/free_rtos/ethernet_ip/eth_checksum.c
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* eth_checksum.c
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet_ip/eth_checksum.h"
|
||||
|
||||
uint16_t eth_calcChksum(uint32_t sum, uint8_t * const data, uint16_t len)
|
||||
{
|
||||
uint16_t i;
|
||||
uint16_t size = len - 1;
|
||||
|
||||
if ( !len )
|
||||
return 0;
|
||||
|
||||
for ( i = 0; i < size; i+=2 )
|
||||
sum += ((uint16_t)data[i] << 8) + data[i+1];
|
||||
|
||||
if (len & 0x01)
|
||||
sum += (uint16_t)data[i] << 8;
|
||||
|
||||
while ( sum >> 16 )
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
|
||||
return ~sum;
|
||||
}
|
||||
23
components/free_rtos/ethernet_ip/eth_checksum.h
Normal file
23
components/free_rtos/ethernet_ip/eth_checksum.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* eth_checksum.h
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_CHECKSUM_H_
|
||||
#define FREE_RTOS_ETHERNET_ETH_CHECKSUM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint16_t eth_calcChksum(uint32_t sum, uint8_t * const data, uint16_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_CHECKSUM_H_ */
|
||||
42
components/free_rtos/ethernet_ip/eth_icmp.cpp
Normal file
42
components/free_rtos/ethernet_ip/eth_icmp.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* eth_icmp.cpp
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet_ip/eth_icmp.hpp"
|
||||
#include "ethernet_ip/eth_icmp_types.h"
|
||||
#include "ethernet_ip/eth_ip_checksum.h"
|
||||
#include "base/swap.h"
|
||||
|
||||
int32_t free_rtos::EthIcmp::Process(uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
TIcmpEchoHeader * hdr = (TIcmpEchoHeader*)p_data;
|
||||
uint32_t ul_icmp_len = len;
|
||||
|
||||
if (hdr->type != ICMP_ECHO_REQUEST) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdr->type = ICMP_ECHO_REPLY;
|
||||
hdr->code = 0;
|
||||
hdr->cksum = 0;
|
||||
|
||||
/* Checksum of the ICMP message */
|
||||
if (ul_icmp_len % 2)
|
||||
{
|
||||
*(((uint8_t *) hdr) + ul_icmp_len) = 0;
|
||||
++ul_icmp_len;
|
||||
}
|
||||
|
||||
ul_icmp_len = ul_icmp_len / 2;
|
||||
|
||||
uint16_t chsum = eth_ip_calcChecksum((uint16_t *)hdr, ul_icmp_len);
|
||||
|
||||
hdr->cksum = BASE_SWAP16(chsum);
|
||||
|
||||
++rx_cnt_;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
28
components/free_rtos/ethernet_ip/eth_icmp.hpp
Normal file
28
components/free_rtos/ethernet_ip/eth_icmp.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* eth_icmp.hpp
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_ICMP_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_ICMP_HPP_
|
||||
|
||||
#include "handler_store/handler.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthIcmp : public Handler {
|
||||
public:
|
||||
virtual int32_t Process(uint8_t * p_data, uint32_t len) override;
|
||||
|
||||
uint32_t getStat() {return rx_cnt_;};
|
||||
private:
|
||||
uint32_t rx_cnt_ = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_ICMP_HPP_ */
|
||||
57
components/free_rtos/ethernet_ip/eth_icmp_types.h
Normal file
57
components/free_rtos/ethernet_ip/eth_icmp_types.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* eth_icmp_types.h
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_ICMP_TYPES_H_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_ICMP_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** ICMP types */
|
||||
/* http://www.iana.org/assignments/icmp-parameters */
|
||||
#define ICMP_ECHO_REPLY 0x00 /**< Echo reply (used to ping) */
|
||||
/* 1 and 2 Reserved */
|
||||
#define ICMP_DEST_UNREACHABLE 0x03 /**< Destination Unreachable */
|
||||
#define ICMP_SOURCE_QUENCH 0x04 /**< Source Quench */
|
||||
#define ICMP_REDIR_MESSAGE 0x05 /**< Redirect Message */
|
||||
#define ICMP_ALT_HOST_ADD 0x06 /**< Alternate Host Address */
|
||||
/* 0x07 Reserved */
|
||||
#define ICMP_ECHO_REQUEST 0x08 /**< Echo Request */
|
||||
#define ICMP_ROUTER_ADV 0x09 /**< Router Advertisement */
|
||||
#define ICMP_ROUTER_SOL 0x0A /**< Router Solicitation */
|
||||
#define ICMP_TIME_EXC 0x0B /**< Time Exceeded */
|
||||
#define ICMP_PARAM_PB 0x0C /**< Parameter Problem: Bad IP header */
|
||||
#define ICMP_TIMESTAMP 0x0D /**< Timestamp */
|
||||
#define ICMP_TIMESTAMP_REP 0x0E /**< Timestamp Reply */
|
||||
#define ICMP_INFO_REQ 0x0F /**< Information Request */
|
||||
#define ICMP_INFO_REPLY 0x10 /**< Information Reply */
|
||||
#define ICMP_ADD_MASK_REQ 0x11 /**< Address Mask Request */
|
||||
#define ICMP_ADD_MASK_REP 0x12 /**< Address Mask Reply */
|
||||
/* 0x13 Reserved for security */
|
||||
/* 0X14 through 0x1D Reserved for robustness experiment */
|
||||
#define ICMP_TRACEROUTE 0x1E /**< Traceroute */
|
||||
#define ICMP_DAT_CONV_ERROR 0x1F /**< Datagram Conversion Error */
|
||||
#define ICMP_MOB_HOST_RED 0x20 /**< Mobile Host Redirect */
|
||||
#define ICMP_W_A_Y 0x21 /**< Where-Are-You (originally meant for IPv6) */
|
||||
#define ICMP_H_I_A 0x22 /**< Here-I-Am (originally meant for IPv6) */
|
||||
#define ICMP_MOB_REG_REQ 0x23 /**< Mobile Registration Request */
|
||||
#define ICMP_MOB_REG_REP 0x24 /**< Mobile Registration Reply */
|
||||
#define ICMP_DOM_NAME_REQ 0x25 /**< Domain Name Request */
|
||||
#define ICMP_DOM_NAME_REP 0x26 /**< Domain Name Reply */
|
||||
#define ICMP_SKIP_ALGO_PROT 0x27 /**< SKIP Algorithm Discovery Protocol, Simple Key-Management for Internet Protocol */
|
||||
#define ICMP_PHOTURIS 0x28 /**< Photuris, Security failures */
|
||||
#define ICMP_EXP_MOBIL 0x29 /**< ICMP for experimental mobility protocols such as Seamoby [RFC4065] */
|
||||
|
||||
/** ICMP echo header structure */
|
||||
typedef struct {
|
||||
uint8_t type; /**< Type of message */
|
||||
uint8_t code; /**< Type subcode */
|
||||
uint16_t cksum; /**< 1's complement cksum of struct */
|
||||
uint16_t id; /**< Identifier */
|
||||
uint16_t seq; /**< Sequence number */
|
||||
} __attribute__ ((packed)) TIcmpEchoHeader; /* GCC */
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_ICMP_TYPES_H_ */
|
||||
129
components/free_rtos/ethernet_ip/eth_ip.cpp
Normal file
129
components/free_rtos/ethernet_ip/eth_ip.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* eth_ip.cpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet_ip/eth_ip.hpp"
|
||||
#include "ethernet_ip/eth_ip_types.h"
|
||||
#include "ethernet_ip/eth_checksum.h"
|
||||
|
||||
#include "ethernet/eth_frame.h"
|
||||
#include "base/swap.h"
|
||||
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#define IP_TIME_TO_LIVE 64
|
||||
#define IP_VER 4
|
||||
#define IP_HEADER_WORD_SIZE 5
|
||||
|
||||
static void ip_swap_ip ( uint8_t * const dest_ip, uint8_t * const source_ip )
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < ETH_IP_ADDR_LEN; i++)
|
||||
{
|
||||
uint8_t tmp = dest_ip[i];
|
||||
dest_ip[i] = source_ip[i];
|
||||
source_ip[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
free_rtos::EthIp::EthIp(EthStackIface& eth_stack, EthArpIface& arp) :
|
||||
eth_stack_{eth_stack},
|
||||
arp_{arp}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int32_t free_rtos::EthIp::Process(uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
TIpHeader * ip_hdr = (TIpHeader *)p_data;
|
||||
uint32_t ip_addr;
|
||||
|
||||
memcpy(&ip_addr, ip_hdr->ip_dst, ETH_IP_ADDR_LEN);
|
||||
|
||||
if (ip_addr != self_ip_) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t reply = handlers_.Process(ip_hdr->ip_p, p_data + sizeof(TIpHeader), len - sizeof(TIpHeader));
|
||||
|
||||
if (reply > 0) {
|
||||
uint16_t cksum;
|
||||
uint16_t len;
|
||||
/* Swap the IP destination address and the IP source address */
|
||||
ip_swap_ip(ip_hdr->ip_dst, ip_hdr->ip_src);
|
||||
reply += sizeof(TIpHeader);
|
||||
ip_hdr->ip_len = BASE_SWAP16(reply);
|
||||
ip_hdr->ip_id = BASE_SWAP16(ip_indet_);
|
||||
//-------------------------------------------------------
|
||||
ip_hdr->ip_sum = 0;
|
||||
len = (ip_hdr->ip_hl_v & 0x0F) * 4;
|
||||
cksum = eth_calcChksum(0,(uint8_t *)ip_hdr, len);
|
||||
ip_hdr->ip_sum = BASE_SWAP16(cksum);
|
||||
//-------------------------------------------------------
|
||||
++ip_indet_;
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
bool free_rtos::EthIp::send(TEthMacPorts port_id, uint32_t dest_ip, uint8_t prot_id, TEthPkt& pkt)
|
||||
{
|
||||
uint64_t mac_dst;
|
||||
|
||||
/// Áåðåì mac-àäðåñ èç arp òàáëèöû
|
||||
if (!arp_.getMacAddr(dest_ip, mac_dst)) {
|
||||
/*
|
||||
* Åñëè çàïèñè â arp-òàáëèöå íåò, òî àâòîìàòîì çàïðàøèâàåò arp-çàïðîñ
|
||||
* (ýòîò çàïðîñ âíóòðè ôóíêöèè getMacAddr)
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t cksum = 0;
|
||||
uint16_t len = 0;
|
||||
|
||||
TIpHeader * ip_header = (TIpHeader *)(pkt.data + sizeof(TEthFrameHeader));
|
||||
|
||||
memcpy(ip_header->ip_src, &self_ip_, ETH_IP_ADDR_LEN);
|
||||
|
||||
memcpy(ip_header->ip_dst, &dest_ip, ETH_IP_ADDR_LEN);
|
||||
|
||||
ip_header->ip_hl_v = (IP_VER << 4) | IP_HEADER_WORD_SIZE;
|
||||
|
||||
ip_header->ip_tos = 0;
|
||||
|
||||
ip_header->ip_id = BASE_SWAP16(ip_indet_);
|
||||
|
||||
++ip_indet_;
|
||||
|
||||
ip_header->ip_off = 0;
|
||||
|
||||
ip_header->ip_ttl = IP_TIME_TO_LIVE;
|
||||
|
||||
ip_header->ip_p = prot_id;
|
||||
|
||||
len = (ip_header->ip_hl_v & 0x0F) * 4;
|
||||
|
||||
pkt.length += len;
|
||||
|
||||
ip_header->ip_len = BASE_SWAP16(pkt.length);
|
||||
|
||||
ip_header->ip_sum = 0;
|
||||
|
||||
cksum = eth_calcChksum(0,(uint8_t *)ip_header, len);
|
||||
|
||||
ip_header->ip_sum = BASE_SWAP16(cksum);
|
||||
|
||||
/// Îòïðàâêà äàííûõ
|
||||
return eth_stack_.send_pkt(port_id, mac_dst, ETH_PROT_IP_BE, pkt);
|
||||
}
|
||||
|
||||
bool free_rtos::EthIp::Register(uint8_t prot_id, Handler * p_handler)
|
||||
{
|
||||
return handlers_.Register(prot_id, p_handler);
|
||||
}
|
||||
|
||||
50
components/free_rtos/ethernet_ip/eth_ip.hpp
Normal file
50
components/free_rtos/ethernet_ip/eth_ip.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* eth_ip.hpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_IP_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_IP_HPP_
|
||||
|
||||
#include "handler_store/handler_store.hpp"
|
||||
#include "ethernet_ip/eth_stack_iface.hpp"
|
||||
#include "ethernet/eth_frame.h"
|
||||
#include "ethernet_ip/eth_arp_iface.hpp"
|
||||
#include "ethernet_ip/eth_ip_iface.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthIp : public Handler, public EthIpIface {
|
||||
public:
|
||||
EthIp(EthStackIface& eth_stack, EthArpIface& arp);
|
||||
|
||||
void setSelfIpAddr(uint32_t ip) {self_ip_ = ip;};
|
||||
|
||||
virtual uint32_t getSelfIpAddr() override {return self_ip_;};
|
||||
|
||||
virtual int32_t Process(uint8_t * p_data, uint32_t len) override;
|
||||
|
||||
virtual bool send(TEthMacPorts port_id, uint32_t dest_ip, uint8_t prot_id, TEthPkt& pkt) override;
|
||||
|
||||
bool Register(uint8_t prot_id, Handler * p_handler);
|
||||
|
||||
private:
|
||||
HandlerStore handlers_;
|
||||
|
||||
EthStackIface& eth_stack_;
|
||||
EthArpIface& arp_;
|
||||
|
||||
uint16_t ip_indet_; /// Ïîëå ip_id
|
||||
|
||||
uint32_t self_ip_; /// Ñîáñòâåííûé ip-àäðåñ
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_IP_HPP_ */
|
||||
22
components/free_rtos/ethernet_ip/eth_ip_checksum.c
Normal file
22
components/free_rtos/ethernet_ip/eth_ip_checksum.c
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* eth_ip_checksum.c
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "eth_ip_checksum.h"
|
||||
#include "base/swap.h"
|
||||
|
||||
uint16_t eth_ip_calcChecksum(uint16_t * const data, uint32_t length)
|
||||
{
|
||||
uint32_t i, crc = 0;
|
||||
|
||||
for (i = 0 ; i < length; ++i ) {
|
||||
crc += BASE_SWAP16(data[i]);
|
||||
}
|
||||
|
||||
crc = (crc & 0xffff) + (crc >> 16);
|
||||
|
||||
return (uint16_t) (~crc);
|
||||
}
|
||||
|
||||
23
components/free_rtos/ethernet_ip/eth_ip_checksum.h
Normal file
23
components/free_rtos/ethernet_ip/eth_ip_checksum.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* eth_ip_checksum.h
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_IP_CHECKSUM_H_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_IP_CHECKSUM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint16_t eth_ip_calcChecksum(uint16_t * const data, uint32_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_IP_CHECKSUM_H_ */
|
||||
27
components/free_rtos/ethernet_ip/eth_ip_iface.hpp
Normal file
27
components/free_rtos/ethernet_ip/eth_ip_iface.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* eth_ip_iface.hpp
|
||||
*
|
||||
* Created on: 15 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_IP_IFACE_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_IP_IFACE_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include "ethernet/eth_types.h"
|
||||
#include "ethernet/eth_frame.h"
|
||||
|
||||
class EthIpIface {
|
||||
public:
|
||||
/**
|
||||
* Ïåðåäà÷à ïàêåòà
|
||||
*/
|
||||
virtual bool send(TEthMacPorts port_id, uint32_t dest_ip, uint8_t prot_id, TEthPkt& pkt) = 0;
|
||||
|
||||
virtual uint32_t getSelfIpAddr() = 0;
|
||||
|
||||
virtual ~EthIpIface() {};
|
||||
};
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_IP_IFACE_HPP_ */
|
||||
16
components/free_rtos/ethernet_ip/eth_ip_prots_id.h
Normal file
16
components/free_rtos/ethernet_ip/eth_ip_prots_id.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* eth_ip_prots_id.h
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_IP_PROTS_ID_H_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_IP_PROTS_ID_H_
|
||||
|
||||
#define IP_PROT_ICMP 1
|
||||
#define IP_PROT_IP 4
|
||||
#define IP_PROT_TCP 6
|
||||
#define IP_PROT_UDP 17
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_IP_PROTS_ID_H_ */
|
||||
51
components/free_rtos/ethernet_ip/eth_ip_types.h
Normal file
51
components/free_rtos/ethernet_ip/eth_ip_types.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* eth_ip_types.h
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_IP_TYPES_H_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_IP_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ETH_IP_ADDR_LEN (4u)
|
||||
|
||||
#define ETH_PROT_IP_LE 0x0800 /**< 2048 (0x0800) IPv4 */
|
||||
#define ETH_PROT_IP_BE 0x0008 /**< 2048 (0x0800) IPv4 */
|
||||
|
||||
typedef union {
|
||||
uint8_t bytes[4];
|
||||
uint32_t addr;
|
||||
}TEthIpAddr;
|
||||
|
||||
/** ARP header structure */
|
||||
typedef struct {
|
||||
uint16_t ar_hrd; /**< Format of hardware address */
|
||||
uint16_t ar_pro; /**< Format of protocol address */
|
||||
uint8_t ar_hln; /**< Length of hardware address */
|
||||
uint8_t ar_pln; /**< Length of protocol address */
|
||||
uint16_t ar_op; /**< Operation */
|
||||
uint8_t ar_sha[6]; /**< Sender hardware address */
|
||||
uint8_t ar_spa[4]; /**< Sender protocol address */
|
||||
uint8_t ar_tha[6]; /**< Target hardware address */
|
||||
uint8_t ar_tpa[4]; /**< Target protocol address */
|
||||
} __attribute__ ((packed)) TArpHeader;
|
||||
|
||||
/** IP Header structure */
|
||||
typedef struct {
|
||||
uint8_t ip_hl_v; /**< Header length and version */
|
||||
uint8_t ip_tos; /**< Type of service */
|
||||
uint16_t ip_len; /**< Total length */
|
||||
uint16_t ip_id; /**< Identification */
|
||||
uint16_t ip_off; /**< Fragment offset field */
|
||||
uint8_t ip_ttl; /**< Time to live */
|
||||
uint8_t ip_p; /**< Protocol */
|
||||
uint16_t ip_sum; /**< Checksum */
|
||||
uint8_t ip_src[4]; /**< Source IP address */
|
||||
uint8_t ip_dst[4]; /**< Destination IP address */
|
||||
} __attribute__ ((packed)) TIpHeader; /* GCC */
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_IP_TYPES_H_ */
|
||||
19
components/free_rtos/ethernet_ip/eth_prots_id.h
Normal file
19
components/free_rtos/ethernet_ip/eth_prots_id.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* eth_prot.h
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
* Èäåíòèôèêàòîðû ïðîòîêîëîâ Ethernet
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_ETH_PROTS_ID_H_
|
||||
#define FREE_RTOS_ETHERNET_ETH_PROTS_ID_H_
|
||||
|
||||
|
||||
#define ETH_PROT_ARP_LE 0x0806 /// ARP
|
||||
#define ETH_PROT_ARP_BE 0x0608 /// ARP
|
||||
|
||||
#define ETH_PROT_IP_LE 0x0800 /// IPv4
|
||||
#define ETH_PROT_IP_BE 0x0008 /// IPv4
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_ETH_PROTS_ID_H_ */
|
||||
101
components/free_rtos/ethernet_ip/eth_stack.cpp
Normal file
101
components/free_rtos/ethernet_ip/eth_stack.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* eth_stack.cpp
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet_ip/eth_stack.hpp"
|
||||
#include "ethernet_ip/eth_prots_id.h"
|
||||
#include "ethernet/eth_frame.h"
|
||||
|
||||
#include "ethernet_ip/eth_ip_prots_id.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
free_rtos::EthStack::EthStack(EthTxFlowIface& tx_flow) :
|
||||
tx_flow_{tx_flow},
|
||||
arp_{*this},
|
||||
ip_{*this, arp_},
|
||||
udp_{ip_}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool free_rtos::EthStack::init(Settings& sett) {
|
||||
|
||||
eth_.self_mac_ = sett.mac_addr_be;
|
||||
eth_.mac_port_ = sett.mac_port;
|
||||
eth_.self_ip_ = sett.ip_addr_be;
|
||||
|
||||
rx_pkt_handler_.Register(ETH_PROT_ARP_BE, &arp_);
|
||||
rx_pkt_handler_.Register(ETH_PROT_IP_BE, &ip_);
|
||||
|
||||
udp_.setPortId(eth_.mac_port_);
|
||||
|
||||
ip_.setSelfIpAddr(eth_.self_ip_);
|
||||
|
||||
ip_.Register(IP_PROT_ICMP, &icmp_);
|
||||
ip_.Register(IP_PROT_UDP, &udp_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool free_rtos::EthStack::Register(uint32_t prot_id, Handler * p_handler) {
|
||||
return rx_pkt_handler_.Register(prot_id, p_handler);
|
||||
}
|
||||
|
||||
void free_rtos::EthStack::set_mac_address(uint64_t mac_be) {
|
||||
eth_.self_mac_ = mac_be;
|
||||
arp_.init(eth_.mac_port_, eth_.self_mac_, eth_.self_ip_);
|
||||
}
|
||||
|
||||
bool free_rtos::EthStack::send_pkt(TEthMacPorts port_id, uint64_t mac_dst, uint16_t prot_id, TEthPkt& pkt)
|
||||
{
|
||||
TEthFrameHeader * p_eth_hdr = (TEthFrameHeader *)pkt.data;
|
||||
p_eth_hdr->prot_id = prot_id;
|
||||
memcpy(p_eth_hdr->mac_src, ð_.self_mac_, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
memcpy(p_eth_hdr->mac_dest, &mac_dst, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
|
||||
pkt.length+= sizeof(TEthFrameHeader);
|
||||
|
||||
return tx_flow_.send(eth_.mac_port_, pkt.data, pkt.length);
|
||||
}
|
||||
|
||||
void free_rtos::EthStack::rx_handler(uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
/// Ìèíèìàëüíàÿ äëèíà eth-ïàêåòà = 60 áàéò
|
||||
if ( len < ETH_FRAME_MIN_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// Ñ÷èòûâàåì àäðåñ íàçíà÷åíèÿ
|
||||
uint64_t dest_addr = *((uint64_t*)p_data);
|
||||
dest_addr &= ETH_FRAME_MAC_ADDR_MASK; /// îñòàâëÿåì 6 ìëàäøèõ áàéò
|
||||
|
||||
/// Ðåàãèðóåì òîëüêî êîãäà ìàê àäðåñ øèðîêîâåùàòåëüíûé èëè íàø ñîáñòâåííûé
|
||||
if ((ETH_FRAME_MAC_ADDR_BROADCAST != dest_addr) &&
|
||||
(eth_.self_mac_ != dest_addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TEthFrameHeader * p_eth_hdr = (TEthFrameHeader *)p_data;
|
||||
|
||||
/// Âûçûâàåì îáðàáîò÷èê
|
||||
int32_t reply_len = rx_pkt_handler_.Process(p_eth_hdr->prot_id,
|
||||
p_data + sizeof(TEthFrameHeader),
|
||||
len - sizeof(TEthFrameHeader));
|
||||
|
||||
/// Îòïðàâëÿåì îòâåò
|
||||
if (reply_len > 0) {
|
||||
/// Çàìåíÿåì àäðåñ íàçíà÷åíèÿ mac-àäðåñîì îòïðàâèòåëÿ
|
||||
memcpy(p_eth_hdr->mac_dest, p_eth_hdr->mac_src, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
/// Çàìåíÿåì àäðåñ èñòî÷íèêà ñâîèì mac-àäðåñîì
|
||||
memcpy(p_eth_hdr->mac_src, ð_.self_mac_, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||||
|
||||
reply_len+=sizeof(TEthFrameHeader);
|
||||
|
||||
/// Îòïðàâëÿåì äàííûå
|
||||
tx_flow_.send(eth_.mac_port_, p_data, reply_len);
|
||||
}
|
||||
}
|
||||
|
||||
71
components/free_rtos/ethernet_ip/eth_stack.hpp
Normal file
71
components/free_rtos/ethernet_ip/eth_stack.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* eth_stack.hpp
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_STACK_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_STACK_HPP_
|
||||
|
||||
#include "ethernet_ip/eth_arp.hpp"
|
||||
#include "ethernet_ip/eth_ip.hpp"
|
||||
#include "ethernet_ip/eth_icmp.hpp"
|
||||
#include "ethernet_ip/eth_udp_server.hpp"
|
||||
|
||||
#include "ethernet_ip/eth_stack_iface.hpp"
|
||||
#include "handler_store/handler_store.hpp"
|
||||
|
||||
#include "ethernet/eth_types.h"
|
||||
|
||||
#include "ethernet/eth_tx_flow_iface.hpp"
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthStack : public EthStackIface {
|
||||
public:
|
||||
struct Settings {
|
||||
uint64_t mac_addr_be; /// big endian
|
||||
uint32_t ip_addr_be; /// big endian
|
||||
TEthMacPorts mac_port;
|
||||
};
|
||||
|
||||
EthStack(EthTxFlowIface& tx_flow);
|
||||
|
||||
bool init(Settings& sett);
|
||||
|
||||
virtual void set_mac_address(uint64_t mac_be) override;
|
||||
|
||||
virtual void rx_handler(uint8_t * p_data, uint32_t len) override;
|
||||
|
||||
virtual bool send_pkt(TEthMacPorts port_id, uint64_t mac_dst, uint16_t prot_id, TEthPkt& pkt) override;
|
||||
|
||||
EthUdpServerIface * getUdpServerPtr() {return &udp_;}
|
||||
|
||||
/*
|
||||
* Ðåãèñòðàöèÿ îáðàáîò÷èêà ïðîòîêîëà íà óðîâíå ethernet
|
||||
*/
|
||||
virtual bool Register(uint32_t prot_id, Handler * p_handler) override;
|
||||
|
||||
private:
|
||||
struct EthData {
|
||||
uint64_t self_mac_; /// Ñîáñòâåííûé ìàê àäðåñ
|
||||
TEthMacPorts mac_port_;
|
||||
uint32_t self_ip_;
|
||||
};
|
||||
|
||||
EthTxFlowIface& tx_flow_;
|
||||
HandlerStore rx_pkt_handler_;
|
||||
|
||||
EthData eth_;
|
||||
EthArp arp_;
|
||||
EthIp ip_;
|
||||
EthIcmp icmp_;
|
||||
EthUdpServer udp_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_STACK_HPP_ */
|
||||
43
components/free_rtos/ethernet_ip/eth_stack_iface.hpp
Normal file
43
components/free_rtos/ethernet_ip/eth_stack_iface.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* eth_stack_iface.hpp
|
||||
*
|
||||
* Created on: 14 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_STACK_IFACE_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_STACK_IFACE_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include "ethernet/eth_types.h"
|
||||
#include "ethernet/eth_frame.h"
|
||||
#include "handler_store/handler.hpp"
|
||||
|
||||
class EthStackIface {
|
||||
public:
|
||||
/**
|
||||
* Óñòàíîâêà ñîáñòâåííîãî mac-àäðåñà
|
||||
*/
|
||||
virtual void set_mac_address(uint64_t mac_addr_be) = 0;
|
||||
|
||||
/**
|
||||
* Îáðàáîò÷èê eth ïàêåòîâ
|
||||
*/
|
||||
virtual void rx_handler(uint8_t * p_data, uint32_t len) = 0;
|
||||
|
||||
/**
|
||||
* Ïåðåäà÷à ïàêåòà
|
||||
*/
|
||||
virtual bool send_pkt(TEthMacPorts port_id, uint64_t mac_dst, uint16_t prot_id, TEthPkt& pkt) = 0;
|
||||
|
||||
/**
|
||||
* Ðåãèñòðàöèÿ îáðàáîò÷èêà eth-ïàêåòà
|
||||
*/
|
||||
virtual bool Register(uint32_t prot_id, Handler * p_handler) = 0;
|
||||
|
||||
virtual ~EthStackIface() {};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_STACK_IFACE_HPP_ */
|
||||
129
components/free_rtos/ethernet_ip/eth_udp_client.cpp
Normal file
129
components/free_rtos/ethernet_ip/eth_udp_client.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* eth_udp_client.cpp
|
||||
*
|
||||
* Created on: 15 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet_ip/eth_udp_client.hpp"
|
||||
#include "base/swap.h"
|
||||
#include "ethernet_ip/eth_udp_types.h"
|
||||
#include "ethernet_ip/eth_ip_types.h"
|
||||
#include "ethernet_ip/eth_checksum.h"
|
||||
#include "ethernet_ip/eth_ip_prots_id.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
free_rtos::EthUpdClient::EthUpdClient(EthIpIface& ip_iface, TEthMacPorts port_id,
|
||||
uint16_t port_dst_be, uint16_t port_src_be,
|
||||
bool use_chksum) :
|
||||
port_dst_be_{port_dst_be},
|
||||
port_src_be_{port_src_be},
|
||||
use_checksum_{use_chksum},
|
||||
ip_iface_{ip_iface},
|
||||
port_id_{port_id}
|
||||
{
|
||||
}
|
||||
|
||||
void free_rtos::EthUpdClient::put_data(uint32_t src_ip, uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
if ((p_data == nullptr) || (len == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// Êîïèðóåì äàííûå â áóôåð
|
||||
{
|
||||
LockGuard lock(rx_mut_); /// Áëîêèðóåì ìüþòåêñ
|
||||
|
||||
/// Îãðàíè÷èâàåì ìàêñèìàëüíûé ðàçìåð äàííûõ â áóôåðå
|
||||
if (buff_.size() < max_buf_size) {
|
||||
buff_.insert(buff_.end(), p_data, p_data + len);
|
||||
}
|
||||
}
|
||||
|
||||
src_ip_ = src_ip;
|
||||
|
||||
rx_sem_.post();
|
||||
}
|
||||
|
||||
int32_t free_rtos::EthUpdClient::read(uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
if ((p_data == nullptr) || (len == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Åñëè áóôåð ïóñò, îæèäàåì ïðèåìà äàííûõ
|
||||
if (buff_.empty()) {
|
||||
rx_sem_.pend();
|
||||
}
|
||||
|
||||
uint32_t size = buff_.size();
|
||||
|
||||
if (size > len) {
|
||||
size = len;
|
||||
}
|
||||
|
||||
{
|
||||
LockGuard lock(rx_mut_); /// Áëîêèðóåì ìüþòåêñ
|
||||
auto item_begin = buff_.begin();
|
||||
auto item_end = item_begin + size;
|
||||
|
||||
/// Èçâëåêàåì äàííûå èç áóôåðà è êîïèïóåì â áóôåð ïîëüçîâàòåëÿ
|
||||
std::copy(item_begin, item_end, p_data);
|
||||
/// Óäàëÿåì ñêîïèðîâàííûå äàííûå èç áóôåðà
|
||||
buff_.erase(item_begin, item_end);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void free_rtos::EthUpdClient::clear()
|
||||
{
|
||||
LockGuard lock(rx_mut_);
|
||||
buff_.clear();
|
||||
}
|
||||
|
||||
int32_t free_rtos::EthUpdClient::write(uint32_t ip_dst_be, uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
TUdpHeader * hdr = (TUdpHeader *)(eth_pkt_.data + sizeof(TIpHeader) + sizeof(TEthFrameHeader));
|
||||
uint8_t * p_udp_data = (uint8_t *)(eth_pkt_.data + sizeof(TIpHeader) + sizeof(TEthFrameHeader) + sizeof(TUdpHeader));
|
||||
|
||||
if (ip_dst_be == 0) {
|
||||
ip_dst_be = src_ip_;
|
||||
}
|
||||
|
||||
eth_pkt_.length = len + sizeof(TUdpHeader);
|
||||
|
||||
hdr->Src_port = port_src_be_;
|
||||
hdr->Dst_port = port_dst_be_;
|
||||
hdr->Length = BASE_SWAP16(eth_pkt_.length);
|
||||
hdr->Chk_sum = 0;
|
||||
|
||||
/// Êîïèðóåì äàííûå
|
||||
memcpy(p_udp_data, p_data, len);
|
||||
|
||||
/// Åñëè íóæíî ñ÷èòàòü êîíòðîîëüíóþ ñóììó
|
||||
if (use_checksum_) {
|
||||
uint32_t self_ip = ip_iface_.getSelfIpAddr();
|
||||
uint32_t chk_sum32 = 0;
|
||||
|
||||
uint8_t * const dst_ip = (uint8_t *)&ip_dst_be;
|
||||
uint8_t * const src_ip = (uint8_t *)&self_ip;
|
||||
|
||||
for (int j = 0; j < ETH_IP_ADDR_LEN; j += 2)
|
||||
{
|
||||
chk_sum32 += ((uint16_t)dst_ip[j] << 8) + dst_ip[j+1];
|
||||
chk_sum32 += ((uint16_t)src_ip[j] << 8) + src_ip[j+1];
|
||||
}
|
||||
|
||||
chk_sum32 += IP_PROT_UDP + eth_pkt_.length;
|
||||
|
||||
uint16_t chk_sum16 = eth_calcChksum(chk_sum32, (uint8_t *)hdr, eth_pkt_.length);
|
||||
|
||||
hdr->Chk_sum = BASE_SWAP16(chk_sum16);
|
||||
}
|
||||
|
||||
return ip_iface_.send(port_id_, ip_dst_be, IP_PROT_UDP, eth_pkt_);
|
||||
}
|
||||
|
||||
62
components/free_rtos/ethernet_ip/eth_udp_client.hpp
Normal file
62
components/free_rtos/ethernet_ip/eth_udp_client.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* eth_udp_client.hpp
|
||||
*
|
||||
* Created on: 15 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_UDP_CLIENT_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_UDP_CLIENT_HPP_
|
||||
|
||||
#include "semaphore/semaphore.hpp"
|
||||
#include "mutex/mutex.hpp"
|
||||
#include "ethernet/eth_frame.h"
|
||||
#include "ethernet_ip/eth_ip_iface.hpp"
|
||||
#include "ethernet/eth_types.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthUpdClient {
|
||||
friend class EthUdpServer;
|
||||
|
||||
public:
|
||||
EthUpdClient(EthIpIface& ip_iface, TEthMacPorts port_id,
|
||||
uint16_t port_dst_be, uint16_t port_src_be,
|
||||
bool use_chksum);
|
||||
|
||||
int32_t read(uint8_t * p_data, uint32_t len);
|
||||
|
||||
int32_t write(uint32_t ip_dst_be, uint8_t * p_data, uint32_t len);
|
||||
|
||||
void clear(); ///î÷èñòêà ïðèåìíîãî áóôåðà
|
||||
|
||||
private:
|
||||
void put_data(uint32_t src_ip, uint8_t * p_data, uint32_t len);
|
||||
|
||||
private:
|
||||
const uint32_t max_buf_size = 0x100000; // 1Mb
|
||||
|
||||
Semaphore rx_sem_;
|
||||
Mutex rx_mut_;
|
||||
|
||||
const uint16_t port_dst_be_; /// big endian
|
||||
const uint16_t port_src_be_; /// big endian
|
||||
const bool use_checksum_;
|
||||
|
||||
std::vector<uint8_t> buff_;
|
||||
|
||||
TEthPkt eth_pkt_;
|
||||
|
||||
EthIpIface& ip_iface_;
|
||||
|
||||
const TEthMacPorts port_id_;
|
||||
|
||||
uint32_t src_ip_; /// Ip Àäðåñ èñòî÷íèêà ïàêåòà UDP
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_UDP_CLIENT_HPP_ */
|
||||
75
components/free_rtos/ethernet_ip/eth_udp_server.cpp
Normal file
75
components/free_rtos/ethernet_ip/eth_udp_server.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* eth_udp.cpp
|
||||
*
|
||||
* Created on: 15 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "ethernet_ip/eth_udp_server.hpp"
|
||||
#include "ethernet_ip/eth_udp_types.h"
|
||||
#include "ethernet_ip/eth_ip_types.h"
|
||||
#include "base/swap.h"
|
||||
|
||||
|
||||
free_rtos::EthUdpServer::EthUdpServer(EthIpIface& ip_iface) :
|
||||
ip_iface_{ip_iface}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<free_rtos::EthUpdClient> free_rtos::EthUdpServer::createClient(uint16_t port_dst,
|
||||
uint16_t port_src,
|
||||
bool use_chksum)
|
||||
{
|
||||
port_dst = BASE_SWAP16(port_dst);
|
||||
port_src = BASE_SWAP16(port_src);
|
||||
|
||||
/// Êëèåíò óæå çàðåãèñòðèðîâàí íà ýòîò ïîðò
|
||||
if (connections_.count(port_dst)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<EthUpdClient> p_client = std::make_shared<EthUpdClient>(ip_iface_, port_id_,
|
||||
port_dst, port_src, use_chksum);
|
||||
|
||||
if (p_client == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
connections_[port_dst] = p_client;
|
||||
|
||||
return p_client;
|
||||
}
|
||||
|
||||
int32_t free_rtos::EthUdpServer::Process(uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
if (len <= sizeof(TUdpHeader)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TUdpHeader * hdr = (TUdpHeader *)p_data;
|
||||
|
||||
uint16_t port = hdr->Dst_port;
|
||||
|
||||
auto item = connections_.find(port);
|
||||
|
||||
/// Òàêîé ïîðò íå çàðåãèñòðèðîâàí
|
||||
if (item == connections_.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& client = item->second;
|
||||
|
||||
TIpHeader * p_ip_hdr = (TIpHeader*)(p_data - sizeof(TIpHeader));
|
||||
|
||||
uint32_t src_ip;
|
||||
|
||||
memcpy(&src_ip, p_ip_hdr->ip_src, ETH_IP_ADDR_LEN);
|
||||
|
||||
/// Êîïèðóåì äàííûå udp
|
||||
client->put_data(src_ip, p_data + sizeof(TUdpHeader), len - sizeof(TUdpHeader));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
44
components/free_rtos/ethernet_ip/eth_udp_server.hpp
Normal file
44
components/free_rtos/ethernet_ip/eth_udp_server.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* eth_udp.hpp
|
||||
*
|
||||
* Created on: 15 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_UDP_SERVER_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_UDP_SERVER_HPP_
|
||||
|
||||
#include "handler_store/handler_store.hpp"
|
||||
#include "ethernet_ip/eth_udp_server_iface.hpp"
|
||||
#include "ethernet_ip/eth_ip_iface.hpp"
|
||||
#include "ethernet/eth_types.h"
|
||||
#include <map>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthUdpServer : public Handler, public EthUdpServerIface {
|
||||
public:
|
||||
EthUdpServer(EthIpIface& ip_iface);
|
||||
|
||||
void setPortId(TEthMacPorts port_id) { port_id_ = port_id;};
|
||||
|
||||
virtual std::shared_ptr<EthUpdClient> createClient(uint16_t port_dst,
|
||||
uint16_t port_src,
|
||||
bool use_chksum) override;
|
||||
|
||||
virtual int32_t Process(uint8_t * p_data, uint32_t len) override;
|
||||
|
||||
private:
|
||||
EthIpIface& ip_iface_;
|
||||
|
||||
TEthMacPorts port_id_;
|
||||
|
||||
std::map<uint16_t, std::shared_ptr<EthUpdClient>> connections_; /// Êëþ÷ - ïîðò íàçíà÷åíèÿ
|
||||
|
||||
|
||||
///HandlerStore handlers_; /// Îáðàáîò÷èêè udp-äàííûõ
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_UDP_SERVER_HPP_ */
|
||||
28
components/free_rtos/ethernet_ip/eth_udp_server_iface.hpp
Normal file
28
components/free_rtos/ethernet_ip/eth_udp_server_iface.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* eth_udp_server_iface.hpp
|
||||
*
|
||||
* Created on: 15 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_UDP_SERVER_IFACE_HPP_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_UDP_SERVER_IFACE_HPP_
|
||||
|
||||
#include "ethernet_ip/eth_udp_client.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class EthUdpServerIface {
|
||||
public:
|
||||
virtual std::shared_ptr<EthUpdClient> createClient(uint16_t port_dst, uint16_t port_src, bool use_chksum) = 0;
|
||||
|
||||
virtual ~EthUdpServerIface() {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_UDP_SERVER_IFACE_HPP_ */
|
||||
21
components/free_rtos/ethernet_ip/eth_udp_types.h
Normal file
21
components/free_rtos/ethernet_ip/eth_udp_types.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* eth_udp_types.h
|
||||
*
|
||||
* Created on: 15 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_ETHERNET_IP_ETH_UDP_TYPES_H_
|
||||
#define FREE_RTOS_ETHERNET_IP_ETH_UDP_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t Src_port;
|
||||
uint16_t Dst_port;
|
||||
uint16_t Length;
|
||||
uint16_t Chk_sum;
|
||||
} __attribute__ ((packed)) TUdpHeader;
|
||||
|
||||
#endif /* FREE_RTOS_ETHERNET_IP_ETH_UDP_TYPES_H_ */
|
||||
54
components/free_rtos/gpio/gpio.cpp
Normal file
54
components/free_rtos/gpio/gpio.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* gpio.cpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#include "gpio/gpio.hpp"
|
||||
#include <drivers/gpio.h>
|
||||
|
||||
free_rtos::Gpio::Gpio(uint32_t num, Dir dir, uint32_t base_address) :
|
||||
num_{num},
|
||||
dir_{dir},
|
||||
base_addr_{base_address}
|
||||
{
|
||||
uint32_t gpio_dir = GPIO_DIRECTION_INPUT;
|
||||
if (dir_ == e_gpioDirOutput) {
|
||||
gpio_dir = GPIO_DIRECTION_OUTPUT;
|
||||
}
|
||||
|
||||
GPIO_setDirMode(base_addr_, num_, gpio_dir);
|
||||
}
|
||||
|
||||
void free_rtos::Gpio::set() {
|
||||
GPIO_pinWriteHigh(base_addr_, num_);
|
||||
}
|
||||
|
||||
void free_rtos::Gpio::clr() {
|
||||
GPIO_pinWriteLow(base_addr_, num_);
|
||||
}
|
||||
|
||||
void free_rtos::Gpio::toggle() {
|
||||
bool state = get();
|
||||
|
||||
if (state) {
|
||||
clr();
|
||||
}
|
||||
else {
|
||||
set();
|
||||
}
|
||||
}
|
||||
|
||||
bool free_rtos::Gpio::get() {
|
||||
bool out = false;
|
||||
|
||||
if (dir_ == e_gpioDirInput) {
|
||||
out = GPIO_pinRead(base_addr_, num_);
|
||||
}
|
||||
else if (dir_ == e_gpioDirOutput) {
|
||||
out = GPIO_pinOutValueRead(base_addr_, num_);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
45
components/free_rtos/gpio/gpio.hpp
Normal file
45
components/free_rtos/gpio/gpio.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* gpio.hpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
* Ïèíû äîëæíû áûòü ïðåäâàðèòåëüíî ñêîíôèãóðèðîâàíû â SysConfig â ðàçäåëå GPIO
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_GPIO_GPIO_HPP_
|
||||
#define FREE_RTOS_GPIO_GPIO_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class Gpio {
|
||||
public:
|
||||
enum Dir {
|
||||
e_gpioDirOutput = 0,
|
||||
e_gpioDirInput
|
||||
};
|
||||
/*
|
||||
* num - íîìåð ïèíà
|
||||
* Dir - íàïðàâëåíèå âõîä/âûõîä
|
||||
*/
|
||||
Gpio(uint32_t num, Dir dir, uint32_t base_address);
|
||||
|
||||
void set();
|
||||
|
||||
void clr();
|
||||
|
||||
bool get();
|
||||
|
||||
void toggle();
|
||||
|
||||
private:
|
||||
const uint32_t num_;
|
||||
const Dir dir_;
|
||||
const uint32_t base_addr_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_GPIO_GPIO_HPP_ */
|
||||
22
components/free_rtos/handler_store/handler.hpp
Normal file
22
components/free_rtos/handler_store/handler.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* handler_obj.hpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_HANDLER_STORE_HANDLER_HPP_
|
||||
#define FREE_RTOS_HANDLER_STORE_HANDLER_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class Handler {
|
||||
public:
|
||||
virtual int32_t Process(uint8_t * p_data, uint32_t len) = 0;
|
||||
|
||||
~Handler() {};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_HANDLER_STORE_HANDLER_HPP_ */
|
||||
46
components/free_rtos/handler_store/handler_store.cpp
Normal file
46
components/free_rtos/handler_store/handler_store.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* handler_store.cpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "handler_store/handler_store.hpp"
|
||||
|
||||
bool HandlerStore::Register(uint32_t prot_id, Handler * p_handler) {
|
||||
if (p_handler == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (handlers_.count(prot_id)) {
|
||||
return false; /// Îáðàáîò÷èê óæå çàðåãèñòðèðîâàí
|
||||
}
|
||||
|
||||
/// Ðåãèñòðàöèÿ îáðàáîò÷èêà
|
||||
handlers_[prot_id] = p_handler;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t HandlerStore::Process(uint32_t prot_id, uint8_t * p_data, uint32_t len)
|
||||
{
|
||||
if ((p_data == nullptr) || (len == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (handlers_.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto item = handlers_.find(prot_id);
|
||||
|
||||
/// Îáðàáîò÷èê íå çàðåãèñòðèðîâàí
|
||||
if (item == handlers_.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Âûçîâ îáðàáîò÷èêà
|
||||
return handlers_.at(prot_id)->Process(p_data, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
32
components/free_rtos/handler_store/handler_store.hpp
Normal file
32
components/free_rtos/handler_store/handler_store.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* handler_store.hpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_HANDLER_STORE_HANDLER_STORE_HPP_
|
||||
#define FREE_RTOS_HANDLER_STORE_HANDLER_STORE_HPP_
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
|
||||
#include "handler_store/handler.hpp"
|
||||
|
||||
class HandlerStore {
|
||||
public:
|
||||
/***
|
||||
* Ðåãèñòðàöèÿ îáðàáîò÷èêà
|
||||
*/
|
||||
bool Register(uint32_t prot_id, Handler * p_handler);
|
||||
/***
|
||||
* Îáðàáîòêà ïðèøåäøåãî ïàêåòà
|
||||
*/
|
||||
int32_t Process(uint32_t prot_id, uint8_t * p_data, uint32_t len);
|
||||
private:
|
||||
std::map<uint32_t, Handler *> handlers_; /// Îáðàáîò÷èêè ïàêåòîâ Ethernet
|
||||
};
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_HANDLER_STORE_HANDLER_STORE_HPP_ */
|
||||
35
components/free_rtos/mutex/mutex.cpp
Normal file
35
components/free_rtos/mutex/mutex.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* mutex.cpp
|
||||
*
|
||||
* Created on: 26 ñåíò. 2022 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "mutex/mutex.hpp"
|
||||
#include <kernel/dpl/DebugP.h>
|
||||
|
||||
free_rtos::Mutex::Mutex() {
|
||||
handle_ = xSemaphoreCreateMutex();
|
||||
DebugP_assert(nullptr != handle_);
|
||||
}
|
||||
|
||||
BaseType_t free_rtos::Mutex::lock(TickType_t wait) {
|
||||
return xSemaphoreTake( handle_, wait );
|
||||
}
|
||||
|
||||
void free_rtos::Mutex::unlock(void) {
|
||||
xSemaphoreGive(handle_);
|
||||
}
|
||||
|
||||
free_rtos::Mutex::~Mutex() {
|
||||
vSemaphoreDelete(handle_);
|
||||
}
|
||||
|
||||
free_rtos::LockGuard::LockGuard(Mutex& mutex) : mutex_{mutex} {
|
||||
mutex_.lock();
|
||||
}
|
||||
|
||||
free_rtos::LockGuard::~LockGuard() {
|
||||
mutex_.unlock();
|
||||
}
|
||||
|
||||
|
||||
57
components/free_rtos/mutex/mutex.hpp
Normal file
57
components/free_rtos/mutex/mutex.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* mutex.hpp
|
||||
*
|
||||
* Created on: 26 ñåíò. 2022 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef SRC_MUTEX_MUTEX_HPP_
|
||||
#define SRC_MUTEX_MUTEX_HPP_
|
||||
|
||||
#include <kernel/freertos/FreeRTOS-Kernel/include/FreeRTOS.h>
|
||||
#include <kernel/freertos/FreeRTOS-Kernel/include/semphr.h>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
/**
|
||||
* @brief Ñ++ îáåðòêà íà ìüþòåêñîì èç ti rtos
|
||||
*
|
||||
*/
|
||||
class Mutex {
|
||||
public:
|
||||
Mutex();
|
||||
|
||||
/**
|
||||
* wait - âðåìÿ îæèäàíèÿ â òèêàõ, ïî óìîë÷àíèþ
|
||||
* portMAX_DELAY - îæèäàíèå áåñêîíå÷íî, 0 - îæèäàíèå îòñóòñòâóåò
|
||||
* Âûçâðàùàåò pdTRUE åñëè óäàëîñü ïîëó÷èòü ñåìàôîð
|
||||
*/
|
||||
BaseType_t lock(TickType_t wait = portMAX_DELAY);
|
||||
|
||||
void unlock(void);
|
||||
|
||||
~Mutex();
|
||||
|
||||
private:
|
||||
SemaphoreHandle_t handle_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Ðåàëèçàöèÿ ïàòòåðíà LockGuard
|
||||
*
|
||||
*/
|
||||
class LockGuard {
|
||||
public:
|
||||
LockGuard(Mutex& mutex);
|
||||
|
||||
~LockGuard();
|
||||
|
||||
private:
|
||||
Mutex& mutex_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* SRC_MUTEX_MUTEX_HPP_ */
|
||||
57
components/free_rtos/semaphore/semaphore.hpp
Normal file
57
components/free_rtos/semaphore/semaphore.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef SRC_APP_SEMAPHORE_SEMAPHORE_HPP_
|
||||
#define SRC_APP_SEMAPHORE_SEMAPHORE_HPP_
|
||||
|
||||
#include <kernel/dpl/SemaphoreP.h>
|
||||
#include <kernel/dpl/DebugP.h>
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
/**
|
||||
* @brief Ñ++ îáåðòêà ñåìàôîðà â free rtos
|
||||
*
|
||||
*/
|
||||
class Semaphore {
|
||||
public:
|
||||
enum Type {
|
||||
e_semTypeBinary,
|
||||
e_semTypeCounting
|
||||
};
|
||||
|
||||
Semaphore() {
|
||||
int32_t status = SystemP_FAILURE;
|
||||
status = SemaphoreP_constructBinary(&sem_, 0);
|
||||
DebugP_assert(SystemP_SUCCESS == status);
|
||||
}
|
||||
|
||||
Semaphore(Semaphore::Type type, uint32_t init_val, uint32_t max_val) {
|
||||
int32_t status = SystemP_FAILURE;
|
||||
|
||||
if (type == Semaphore::e_semTypeBinary) {
|
||||
status = SemaphoreP_constructBinary(&sem_, init_val);
|
||||
}
|
||||
else if (type == Semaphore::e_semTypeCounting) {
|
||||
status = SemaphoreP_constructCounting(&sem_, init_val, max_val);
|
||||
}
|
||||
|
||||
DebugP_assert(SystemP_SUCCESS == status);
|
||||
}
|
||||
|
||||
void post() {
|
||||
SemaphoreP_post(&sem_);
|
||||
}
|
||||
|
||||
int32_t pend(uint32_t ticks = SystemP_WAIT_FOREVER) {
|
||||
return SemaphoreP_pend(&sem_, ticks);
|
||||
}
|
||||
|
||||
~Semaphore() {
|
||||
SemaphoreP_destruct(&sem_);
|
||||
}
|
||||
|
||||
private:
|
||||
SemaphoreP_Object sem_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
41
components/free_rtos/task/task.cpp
Normal file
41
components/free_rtos/task/task.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* task.cpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "task/task.hpp"
|
||||
|
||||
bool free_rtos::Task::Create(std::string name, uint32_t priority, TaskFunction task_fun,
|
||||
void * taskArg, int32_t stack_size_bytes)
|
||||
{
|
||||
if ( (priority > TaskPriorityHiest) || (task_fun == nullptr) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stack_size_bytes < 0)
|
||||
{
|
||||
stack_size_bytes = defStackSize_;
|
||||
}
|
||||
|
||||
/// Ñòåê äîëæåí áûòü âûðîâíåí ïî ãðàíèöå 32 áàéòà
|
||||
if (stack_size_bytes % 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ret = xTaskCreate(task_fun,
|
||||
name.c_str(),
|
||||
stack_size_bytes / sizeof(configSTACK_DEPTH_TYPE),
|
||||
taskArg,
|
||||
priority,
|
||||
&taskHandle_);
|
||||
|
||||
if (pdPASS != ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
52
components/free_rtos/task/task.hpp
Normal file
52
components/free_rtos/task/task.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* task.hpp
|
||||
*
|
||||
* Created on: 6 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
* Âî FreeRtos åñòü äâà ñïîñîáà ñîçäàòü çàäà÷ó:
|
||||
* xTaskCreate - ñòýê âûäåëÿåòñÿ äèíàìè÷åñêè ïðè ñîçäàíèè çàäà÷è
|
||||
* xTaskCreateStatic - ñòåê âûäåëÿåòñÿ ñòàòè÷åñêè
|
||||
* Äàííûé ìîäóëü ðåàëèçîâàí íà îñíîâå xTaskCreate
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_TASK_TASK_HPP_
|
||||
#define FREE_RTOS_TASK_TASK_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
namespace free_rtos {
|
||||
/**
|
||||
* @brief Êëàññ îáåðòêà ðåàëèçóþùèé ñîçäàíèå çàäà÷è âî free_rtos.
|
||||
*/
|
||||
class Task {
|
||||
public:
|
||||
/**
|
||||
* @brief Òèï óêàçàòåëÿ íà ôóíêöèþ çàäà÷è
|
||||
*
|
||||
*/
|
||||
using TaskFunction = TaskFunction_t;
|
||||
|
||||
static const uint32_t TaskPriorityHiest = configMAX_PRIORITIES - 1; // 31
|
||||
static const uint32_t TaskPriorityLowest = 0; // 0
|
||||
|
||||
bool Create(std::string name, uint32_t priority, TaskFunction task_fun,
|
||||
void * taskArg, int32_t stack_size_bytes = -1);
|
||||
|
||||
~Task() {
|
||||
vTaskDelete(taskHandle_);
|
||||
}
|
||||
|
||||
private:
|
||||
static const uint32_t defStackSize_ = 8192; /// Ðàçìåð ñòåêà ïî-óìîë÷àíèþ
|
||||
|
||||
TaskHandle_t taskHandle_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_TASK_TASK_HPP_ */
|
||||
77
components/free_rtos/timer/timer.cpp
Normal file
77
components/free_rtos/timer/timer.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* timer.cpp
|
||||
*
|
||||
* Created on: 10 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "timer/timer.hpp"
|
||||
#include <kernel/dpl/TimerP.h>
|
||||
#include <drivers/soc.h>
|
||||
#include <kernel/dpl/AddrTranslateP.h>
|
||||
|
||||
using namespace free_rtos;
|
||||
|
||||
void free_rtos::timer_isr_callback(void * arg)
|
||||
{
|
||||
Timer * const p_timer = (Timer * const)arg;
|
||||
|
||||
p_timer->sem_.post();
|
||||
|
||||
TimerP_clearOverflowInt(p_timer->base_addr_);
|
||||
HwiP_clearInt(p_timer->int_num_);
|
||||
}
|
||||
|
||||
bool free_rtos::Timer::Init(Settings& sett)
|
||||
{
|
||||
TimerP_Params timerParams;
|
||||
HwiP_Params timerHwiParams;
|
||||
int32_t status;
|
||||
|
||||
/* set timer clock source */
|
||||
SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_MAIN, 2);
|
||||
*(volatile uint32_t*)AddrTranslateP_getLocalAddr(sett.clock_src_mux_addr) = 0; /// CLOCK_SRC_MCU_HFOSC0
|
||||
SOC_controlModuleLockMMR(SOC_DOMAIN_ID_MAIN, 2);
|
||||
|
||||
base_addr_ = (uint32_t)AddrTranslateP_getLocalAddr(sett.base_address);
|
||||
|
||||
TimerP_Params_init(&timerParams);
|
||||
timerParams.inputPreScaler = 1;
|
||||
timerParams.inputClkHz = sett.input_clk_Hz;
|
||||
timerParams.periodInNsec = sett.period_us * 1000;
|
||||
timerParams.oneshotMode = 0;
|
||||
timerParams.enableOverflowInt = 1;
|
||||
timerParams.enableDmaTrigger = 0;
|
||||
|
||||
TimerP_setup(base_addr_, &timerParams);
|
||||
|
||||
int_num_ = sett.int_num;
|
||||
|
||||
HwiP_Params_init(&timerHwiParams);
|
||||
|
||||
timerHwiParams.intNum = int_num_;
|
||||
timerHwiParams.callback = free_rtos::timer_isr_callback;
|
||||
timerHwiParams.args = (void*)this;
|
||||
timerHwiParams.isPulse = 0;
|
||||
timerHwiParams.priority = sett.int_priority;
|
||||
|
||||
status = HwiP_construct(&hwi_obj_, &timerHwiParams);
|
||||
|
||||
return (status == SystemP_SUCCESS);
|
||||
}
|
||||
|
||||
void free_rtos::Timer::Wait() {
|
||||
sem_.pend();
|
||||
}
|
||||
|
||||
void free_rtos::Timer::Start() {
|
||||
TimerP_start(base_addr_);
|
||||
}
|
||||
|
||||
void free_rtos::Timer::Stop() {
|
||||
TimerP_stop(base_addr_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
56
components/free_rtos/timer/timer.hpp
Normal file
56
components/free_rtos/timer/timer.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* timer.hpp
|
||||
*
|
||||
* Created on: 10 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_TIMER_TIMER_HPP_
|
||||
#define FREE_RTOS_TIMER_TIMER_HPP_
|
||||
|
||||
#include <semaphore/semaphore.hpp>
|
||||
#include <cstdint>
|
||||
#include <kernel/dpl/HwiP.h>
|
||||
|
||||
|
||||
|
||||
namespace free_rtos {
|
||||
|
||||
class Timer {
|
||||
public:
|
||||
struct Settings {
|
||||
uint32_t input_clk_Hz; /// Òàêòîâàÿ ÷àñòîòà â Ãö
|
||||
uint32_t base_address; /// Áàçîâûé àäðåñ
|
||||
uint32_t clock_src_mux_addr; /// Àäðåñ êëîêà
|
||||
uint32_t int_num; /// Íîìåð ïðåðûâàíèÿ
|
||||
uint32_t int_priority; /// Ïðèîðèòåò ïðåðûâàíèÿ
|
||||
uint32_t period_us; /// Ïåðèîä òàéìåðà â ìêñ
|
||||
};
|
||||
|
||||
/**
|
||||
* Èíèöèàëèçàöèÿ òàéìåðà
|
||||
*/
|
||||
bool Init(Settings& sett);
|
||||
|
||||
/**
|
||||
* Îæèäàíèÿ ïåðåïîëíåíèå òàéìåðà. Áëîêèðóþùåå.
|
||||
*/
|
||||
void Wait();
|
||||
|
||||
void Start();
|
||||
|
||||
void Stop();
|
||||
private:
|
||||
friend void timer_isr_callback(void * arg);
|
||||
|
||||
private:
|
||||
uint32_t base_addr_; /// Áàçîâûé àäðåñ ðåãèñòðîâ òàéìåðà
|
||||
uint32_t int_num_; /// Íîìåð ïðåðûâàíèÿ
|
||||
HwiP_Object hwi_obj_; /// Óïðàâëåíèå ïðåðûâàíèÿìè ïî òàéìåðó
|
||||
|
||||
Semaphore sem_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* FREE_RTOS_TIMER_TIMER_HPP_ */
|
||||
33
components/free_rtos/timer_sw/timer_sw.cpp
Normal file
33
components/free_rtos/timer_sw/timer_sw.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* timer_sw.cpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
#include "timer_sw/timer_sw.hpp"
|
||||
|
||||
void TimerSw::start(uint32_t period) {
|
||||
enable_ = true;
|
||||
cnt_ = 0;
|
||||
prd_ = period;
|
||||
}
|
||||
|
||||
void TimerSw::stop() {
|
||||
enable_ = false;
|
||||
}
|
||||
|
||||
bool TimerSw::tick(uint32_t ticks) {
|
||||
|
||||
if (!enable_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cnt_+=ticks;
|
||||
|
||||
if (cnt_ >= prd_) {
|
||||
cnt_ = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
31
components/free_rtos/timer_sw/timer_sw.hpp
Normal file
31
components/free_rtos/timer_sw/timer_sw.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* timer_sw.hpp
|
||||
*
|
||||
* Created on: 13 ìàð. 2023 ã.
|
||||
* Author: sychev
|
||||
*/
|
||||
|
||||
#ifndef FREE_RTOS_TIMER_SW_TIMER_SW_HPP_
|
||||
#define FREE_RTOS_TIMER_SW_TIMER_SW_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class TimerSw {
|
||||
public:
|
||||
void start(uint32_t period);
|
||||
|
||||
void stop();
|
||||
|
||||
bool tick(uint32_t ticks);
|
||||
|
||||
bool is_started() { return enable_; }
|
||||
|
||||
private:
|
||||
bool enable_ = false;
|
||||
uint32_t cnt_ = 0;
|
||||
uint32_t prd_ = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FREE_RTOS_TIMER_SW_TIMER_SW_HPP_ */
|
||||
Loading…
Reference in New Issue
Block a user