Define the headre and frame structures of EtherCAT. Build testcases based on hfa21 Ethernet. Tested on an old commit 7b82f2a60b, whose AT command agent works.

it is OK
This commit is contained in:
xuedongliang 2022-03-02 11:35:28 +08:00
commit 777408e1b7
12 changed files with 878 additions and 1 deletions

View File

@ -21,6 +21,7 @@ extern int AdapterNbiotInit(void);
extern int AdapterBlueToothInit(void);
extern int AdapterWifiInit(void);
extern int AdapterEthernetInit(void);
extern int AdapterEthercatInit(void);
extern int AdapterZigbeeInit(void);
extern int AdapterLoraInit(void);
@ -142,6 +143,9 @@ static struct InitDesc connection_desc[] =
#ifdef CONNECTION_ADAPTER_ETHERNET
{ "ethernet adapter", AdapterEthernetInit},
#endif
#ifdef CONNECTION_ADAPTER_ETHERCAT
{ "ethercat adapter", AdapterEthercatInit},
#endif
#ifdef CONNECTION_ADAPTER_LORA
{ "lora adapter", AdapterLoraInit},
#endif

View File

@ -62,6 +62,12 @@ if SUPPORT_CONNECTION_FRAMEWORK
default n
if CONNECTION_ADAPTER_ETHERNET
source "$APP_DIR/Framework/connection/ethernet/Kconfig"
config CONNECTION_ADAPTER_ETHERCAT
bool "Using ethercat on ethernet adapter device"
default n
if CONNECTION_ADAPTER_ETHERCAT
source "$APP_DIR/Framework/connection/ethercat/Kconfig"
endif
endif
menuconfig CONNECTION_ADAPTER_BLUETOOTH

View File

@ -32,6 +32,10 @@ ifeq ($(CONFIG_CONNECTION_ADAPTER_ETHERNET),y)
SRC_DIR += ethernet
endif
ifeq ($(CONFIG_CONNECTION_ADAPTER_ETHERCAT),y)
SRC_DIR += ethercat
endif
ifeq ($(CONFIG_CONNECTION_ADAPTER_BLUETOOTH),y)
SRC_DIR += bluetooth
endif

View File

@ -0,0 +1,10 @@
config ADAPTER_HFA21_ETHERCAT
depends on ADAPTER_HFA21_ETHERNET # ADAPTER_HFA21_WIFI
help
Ethercat is dependant on Ethernet. Please enable hfa21 ethernet first. And this is a software-defined experiment module, without supports on ECS and on-the-fly.
bool "Using ethercat on ethernet adapter device HFA21"
default n
if ADAPTER_HFA21_ETHERCAT
source "$APP_DIR/Framework/connection/ethercat/hfa21_ethercat/Kconfig"
endif

View File

@ -0,0 +1,7 @@
SRC_FILES := adapter_ethercat.c
ifeq ($(CONFIG_ADAPTER_HFA21_ETHERCAT),y)
SRC_DIR += hfa21_ethercat
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,210 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file adapter_ethercat.c
* @brief Implement the connection ethercat adapter function, reuse the ethernet implementations
* @version 1.1
* @author AIIT XUOS Lab
* @date 2021.10.15
*/
#include <adapter.h>
#include <ethercat.h>
#ifdef ADAPTER_HFA21_ETHERCAT
extern AdapterProductInfoType Hfa21EthercatAttach(struct Adapter *adapter);
#endif
#define ADAPTER_ETHERCAT_NAME "ethercat"
/**
* @description: clear the datagram in ethercat frame, do not free the frame itself, since it may be a memory space on stack
* @param frame - ethercat frame pointer
*/
void EcatClear(EcatFramePtr frame)
{
EcatDatagramPtr datagram = frame->datagram;
while (datagram)
{
EcatDatagramPtr temp = datagram->next;
PrivFree(datagram->data);
PrivFree(datagram);
datagram = temp;
}
memset(frame, 0, sizeof(EcatFrame));
frame->header.length = 2; // 2 bytes for the ethercat header
frame->header.res = 1;
frame->header.type = 0b1001;
}
/**
* @description: receive data from adapter
* @param frame - ethercat frame pointer
* @param address - ethercat address
* @param data - data to be carried inside frame
* @param data_len - length of provided `data`
* @return success: 0, else return error code.
*/
int EcatAppend(EcatFramePtr frame, EcatAddress address, uint8_t *data, uint16_t data_len)
{
EcatDatagramPtr datagram = frame->datagram;
if (!datagram)
{
datagram = PrivMalloc(sizeof(EcatDatagram));
if (!datagram)
{
printf("EcatAppend malloc error\n");
return -1;
}
memset(datagram, 0, sizeof(EcatDatagram));
frame->datagram = datagram;
}
else
{
while (datagram->next)
{
datagram = datagram->next;
}
datagram->header.m = 1; // indcate the datagram is not the last one
datagram->next = PrivMalloc(sizeof(EcatDatagram));
if (!datagram->next)
{
printf("EcatAppend malloc error\n");
return -1;
}
memset(datagram->next, 0, sizeof(EcatDatagram));
datagram = datagram->next;
}
datagram->header.address = address;
datagram->header.length = data_len;
datagram->data = data;
datagram->work_counter++;
frame->header.length += sizeof(datagram->header) + data_len + sizeof(datagram->work_counter);
printf("EcatAppend change length to %d\n", frame->header.length);
return 0;
}
/**
* @description: find datagram for self and update its content
* @param frame - ethercat frame pointer
* @param address - ethercat address
* @param data - data to be carried inside frame
* @param data_len - length of provided `data`
* @return success: 0, else return error code.
*/
int EcatUpdate(EcatFramePtr frame, uint8_t *data, uint16_t data_len)
{
EcatDatagramPtr datagram = frame->datagram;
if (!datagram)
{
printf("EcatUpdate error: null datagram.\n");
return -1;
}
while (datagram)
{
if (datagram->self)
{
datagram->header.length = data_len;
frame->header.length -= strlen(datagram->data);
datagram->data = data;
frame->header.length += data_len;
datagram->work_counter++;
return 0;
}
else
{
datagram = datagram->next;
}
}
printf("EcatUpdate error: cannot find datagram for node itself.\n");
return -2;
}
static int AdapterEthercatRegister(struct Adapter *adapter)
{
int ret = 0;
strncpy(adapter->name, ADAPTER_ETHERCAT_NAME, NAME_NUM_MAX);
adapter->net_protocol = IP_PROTOCOL;
adapter->adapter_status = UNREGISTERED;
ret = AdapterDeviceRegister(adapter);
if (ret < 0)
{
printf("AdapterEthercat register error\n");
return -1;
}
return ret;
}
int AdapterEthercatInit(void)
{
int ret = 0;
struct Adapter *adapter = PrivMalloc(sizeof(struct Adapter));
if (!adapter)
{
printf("AdapterEthercatInit malloc error\n");
PrivFree(adapter);
return -1;
}
memset(adapter, 0, sizeof(struct Adapter));
ret = AdapterEthercatRegister(adapter);
if (ret < 0)
{
printf("AdapterEthercatInit register ethercat adapter error\n");
PrivFree(adapter);
return -1;
}
#ifdef ADAPTER_HFA21_ETHERCAT
AdapterProductInfoType product_info = Hfa21EthercatAttach(adapter);
if (!product_info)
{
printf("AdapterEthercatInit hfa21 attach error\n");
PrivFree(adapter);
return -1;
}
adapter->product_info_flag = 1;
adapter->info = product_info;
adapter->done = product_info->model_done;
#endif
return ret;
}
/******************ethercat TEST*********************/
extern int Hfa21EthercatSlaveTest(struct Adapter *adapter);
extern int Hfa21EthercatMasterTest(struct Adapter *adapter);
int AdapterEthercatTest(void)
{
struct Adapter *adapter = AdapterDeviceFindByName(ADAPTER_ETHERCAT_NAME);
#ifdef ADAPTER_HFA21_ETHERCAT
#ifdef AS_ETHERCAT_SLAVE_ROLE
Hfa21EthercatSlaveTest(adapter);
#else // AS_ETHERCAT_MASTER_ROLE
Hfa21EthercatMasterTest(adapter);
#endif
#endif
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_PARAM_NUM(0) | SHELL_CMD_DISABLE_RETURN, AdapterEthercatTest, AdapterEthercatTest, show adapter ethercat information);

View File

@ -0,0 +1,103 @@
#ifndef ETHERCAT_H
#define ETHERCAT_H
#include <stdint.h>
#define BIG_ENDIAN_PACK __attribute__((packed, scalar_storage_order("big-endian")))
#define LITTLE_ENDIAN_PACK __attribute__((packed, scalar_storage_order("little-endian")))
#define ETHERCAT_PORT "34980" // 0x88A4
#define MAX_FRAME_LEN 1500
#define MIN_FRAME_LEN 14
typedef union BIG_ENDIAN_PACK
{
struct BIG_ENDIAN_PACK
{
uint16_t length : 11;
uint16_t res : 1;
uint16_t type : 4;
};
uint16_t header;
} EcatHeader, *EcatHeaderPtr;
#define ECAT_HEADER_LENGTH 2
typedef union BIG_ENDIAN_PACK
{
struct BIG_ENDIAN_PACK
{
uint16_t position;
uint16_t pos_offset;
}; // Position Addressing
struct BIG_ENDIAN_PACK
{
uint16_t address;
uint16_t addr_offset;
}; // Node Addressing
uint32_t logical;
} EcatAddress, *EcatAddressPtr;
#define ECAT_ADDRESS_LENGTH 4
typedef struct
{
uint8_t cmd;
uint8_t idx;
EcatAddress address;
union BIG_ENDIAN_PACK
{
struct BIG_ENDIAN_PACK
{
uint16_t length : 11;
uint16_t r : 3;
uint16_t c : 1;
uint16_t m : 1; // followed by more datagrams or not
};
uint16_t suffix; // for easy parse
};
uint16_t irq : 16;
} EcatDataHeader, *EcatDataHeaderPtr;
#define ECAT_DATA_HEADER_LENGTH 10
typedef struct
{
// frame data
EcatDataHeader header; // 10 bytes
uint8_t *data; // 0-1486 bytes
uint16_t work_counter; // 2bytes
// utilities
uint8_t self; // indicating this datagram is mine
void *next; // EcatDatagramPtr
} EcatDatagram, *EcatDatagramPtr;
typedef struct
{
EcatHeader header; // 2 bytes
EcatDatagramPtr datagram; // 12-1470 bytes
} EcatFrame, *EcatFramePtr;
extern EcatFrame ecat_data;
void EcatClear(EcatFramePtr frame);
int EcatAppend(EcatFramePtr frame, EcatAddress address, uint8_t *data, uint16_t data_len);
int EcatUpdate(EcatFramePtr frame, uint8_t *data, uint16_t data_len);
#define READ8(buffer, offset) (((uint8_t *)buffer)[offset++])
#define READ16(buffer, offset) ((uint16_t)((uint8_t *)buffer)[offset++] << 8 | (uint16_t)((uint8_t *)buffer)[offset++])
#define READ32(buffer, offset) (uint32_t)((uint8_t *)buffer)[offset++] << 24 | \
(uint32_t)((uint8_t *)buffer)[offset++] << 16 | \
(uint32_t)((uint8_t *)buffer)[offset++] << 8 | \
(uint32_t)((uint8_t *)buffer)[offset++]
#define WRITE8(buffer, offset, value) ((uint8_t *)buffer)[offset++] = (uint8_t)(value & 0xFF);
#define WRITE16(buffer, offset, value) \
((uint8_t *)buffer)[offset++] = (uint8_t)(value >> 8 & 0xFF); \
((uint8_t *)buffer)[offset++] = (uint8_t)(value & 0xFF);
#define WRITE32(buffer, offset, value) \
((uint8_t *)buffer)[offset++] = (uint8_t)(value >> 24 & 0xFF); \
((uint8_t *)buffer)[offset++] = (uint8_t)(value >> 16 & 0xFF); \
((uint8_t *)buffer)[offset++] = (uint8_t)(value >> 8 & 0xFF); \
((uint8_t *)buffer)[offset++] = (uint8_t)(value & 0xFF);
#endif

View File

@ -0,0 +1,41 @@
config ADAPTER_ETHERCAT_HFA21
string "HFA21 EtherCAT adapter name"
default "hfa21_ethercat"
config ADAPTER_ETHERCAT_HFA21_ROLE
choice
prompt "EtherCAT adapter select net role type "
default AS_ETHERCAT_SLAVE_ROLE
config AS_ETHERCAT_MASTER_ROLE
bool "config as a master"
config AS_ETHERCAT_SLAVE_ROLE
bool "config as a slave"
endchoice
config ADAPTER_ETHERCAT_HFA21_NETMASK
string "Current EtherCAT adapter netmask"
default "255.255.255.0"
config ADAPTER_ETHERCAT_HFA21_GATEWAY
string "Current EtherCAT adapter gateway"
default "10.10.100.254"
config ADAPTER_ETHERCAT_HFA21_IP_SELF
string "Current EtherCAT adapter IP"
default "10.10.100.254"
config ADAPTER_ETHERCAT_ADDRESS_SELF
string "Current EtherCAT address"
default 0x12345678
config ADAPTER_ETHERCAT_HFA21_IP_FROM
string "Receive Packet from IP"
default "10.10.100.50"
config ADAPTER_ETHERCAT_HFA21_IP_TO
string "Send Packet to IP"
default "10.10.100.50"

View File

@ -0,0 +1,3 @@
SRC_FILES := hfa21_ethercat.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,485 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file hfa21_ethercat.c
* @brief Implement the connection ethercat adapter function, using HFA21 device
* @version 1.1
* @author AIIT XUOS Lab
* @date 2021.10.15
*/
#include <adapter.h>
#include <at_agent.h>
#include <ethercat.h>
// With HFA21, we use transparant transmission mode,
// therefore, only the TCP/UDP datagrams are considered,
// here EtherCAT is in fact an application layer protocol.
#define ADAPTER_ETHERNET_NAME "ethernet" //"wifi"
EcatFrame ecat_data;
static struct Adapter *ethernet;
uint32_t self_address;
/**
* @description: Open HFA21 ethernet uart function for ethercat
* @param adapter - ethercat device pointer
* @return success: 0, failure: -1
*/
static int Hfa21EthercatOpen(struct Adapter *adapter)
{
ethernet = AdapterDeviceFindByName(ADAPTER_ETHERNET_NAME);
AdapterDeviceOpen(ethernet);
ADAPTER_DEBUG("Hfa21Ethercat open done\n");
return 0;
}
/**
* @description: disconnnect ethercat from internet
* @param adapter - ethercat device pointer
* @return success: 0
*/
static int Hfa21EthercatSetDown(struct Adapter *adapter)
{
if (ethernet)
{
AdapterDeviceClose(ethernet);
ethernet = NULL;
}
return 0;
}
/**
* @description: Close HFA21 ethercat and uart function
* @param adapter - ethercat device pointer
* @return success: 0
*/
static int Hfa21EthercatClose(struct Adapter *adapter)
{
return Hfa21EthercatSetDown(adapter);
}
static int Hfa21EthercatBuildAndSend(struct Adapter *adapter)
{
int result = 0;
// fill the frame according to the ecat_data
uint16_t frame_len = sizeof(EcatHeader);
EcatDatagramPtr cur_data = ecat_data.datagram;
while (cur_data)
{
frame_len += sizeof(EcatDataHeader);
frame_len += cur_data->header.length;
frame_len += sizeof(cur_data->work_counter);
cur_data = (EcatDatagramPtr)cur_data->next;
}
if (frame_len > MAX_FRAME_LEN)
{
ADAPTER_DEBUG("frame_len is too long\n");
result = -2;
goto __exit;
}
if (frame_len < MIN_FRAME_LEN)
{
ADAPTER_DEBUG("frame_len is too short\n");
result = -2;
goto __exit;
}
uint8_t *frame = PrivMalloc(sizeof(uint8_t) * frame_len);
if (frame == NULL)
{
ADAPTER_DEBUG("Hfa21EthercatBuildAndSend: malloc failed\n");
result = -1;
goto __exit;
}
size_t idx = 0;
WRITE16(frame, idx, ecat_data.header.header);
cur_data = ecat_data.datagram;
while (cur_data)
{
WRITE8(frame, idx, cur_data->header.cmd);
WRITE8(frame, idx, cur_data->header.idx);
WRITE32(frame, idx, cur_data->header.address.logical);
WRITE16(frame, idx, cur_data->header.suffix);
WRITE16(frame, idx, cur_data->header.irq);
memcpy(frame + idx, cur_data->data, cur_data->header.length);
idx += cur_data->header.length;
WRITE16(frame, idx, cur_data->work_counter);
cur_data = (EcatDatagramPtr)cur_data->next;
}
// send the frame
if (ethernet && ethernet->agent)
{
result = EntmSend(ethernet->agent, (const char *)frame, frame_len);
if (result == 0)
{
result = frame_len;
}
}
else
{
printf("Hfa21Ethercat Send can not find agent!\n");
result = -1;
goto __exit;
}
__exit:
return result;
}
/**
* @description: send data to adapter
* @param adapter - ethercat device pointer
* @param data - data buffer, when it is NULL, it means to build frame according to `ecat_data`,
* otherwise, it means to replace datagram in `ecat_data` and make up a frame. Slave can use
* this function to update its data. Master have to construct frame according to `ecat_data` and
* pass NULL data to this function.
* @param data - data length
* @return success: sent frame len
*/
static int Hfa21EthercatSend(struct Adapter *adapter, const void *data, size_t len)
{
if (data == NULL || len == 0)
{
return Hfa21EthercatBuildAndSend(adapter);
}
EcatDatagramPtr cur_data = ecat_data.datagram;
size_t cur_len = 0;
while (cur_data)
{
if (cur_data->self)
{
PrivFree(cur_data->data);
cur_data->data = PrivMalloc(sizeof(uint8_t) * len);
memcpy(cur_data->data, data, len);
cur_data->header.length = len;
break;
}
cur_data = (EcatDatagramPtr)cur_data->next;
}
return Hfa21EthercatBuildAndSend(adapter);
}
/**
* @description: receive data from adapter
* @param adapter - ethercat device pointer
* @param data_buffer - data buffer, the whole received frame
* @param buffer_len - whole frame length, set it to maximum 1500 if you don't know the length
* @return success: data length, the data can be visited via variable `ecat_data`
*/
static int Hfa21EthercatReceive(struct Adapter *adapter, void *data_buffer, size_t buffer_len)
{
// in fact, the length of data must be less than buffer_len
int result = 0;
if (ethernet && ethernet->agent)
{
//
result = EntmRecv(ethernet->agent, data_buffer, buffer_len, 40000);
}
else
{
printf("Hfa21Ethercat::Receive can not find agent!\n");
result = -1;
goto __exit;
}
// parse header
size_t data_len = 0;
size_t idx = 0;
ecat_data.header.header = READ16(data_buffer, idx);
buffer_len -= ECAT_HEADER_LENGTH;
if (ecat_data.header.length > buffer_len)
{
printf("buffer size is less than the frame length!\n");
result = -2;
}
if (ecat_data.header.length <= ECAT_DATA_HEADER_LENGTH)
{
// the first datagram header is too short
printf("Datagram is empty!\n");
result = -3;
goto __exit;
}
// parse datagrams
ecat_data.datagram = (EcatDatagramPtr)PrivMalloc(sizeof(EcatDatagram));
EcatDatagramPtr cur_data = ecat_data.datagram;
do
{
// parse datagram header
cur_data->header.cmd = READ8(data_buffer, idx);
cur_data->header.idx = READ8(data_buffer, idx);
cur_data->header.address.logical = READ32(data_buffer, idx);
if (cur_data->header.address.logical == self_address)
{
cur_data->self = 1; // this datagram is mine
}
else
{
cur_data->self = 0;
}
cur_data->header.suffix = READ16(data_buffer, idx);
cur_data->header.irq = READ16(data_buffer, idx);
if (idx + cur_data->header.length + sizeof(cur_data->work_counter) > buffer_len)
{
printf("buffer size is less than the frame length!\n");
result = -2;
goto __exit;
}
// parse datagram data
if (cur_data->data)
{
PrivFree(cur_data->data);
}
cur_data->data = PrivMalloc(sizeof(char) * cur_data->header.length);
memcpy(cur_data->data, data_buffer + idx, cur_data->header.length);
idx += cur_data->header.length;
memcpy(data_buffer + data_len, cur_data->data, cur_data->header.length);
data_len += cur_data->header.length;
cur_data->work_counter = READ16(data_buffer, idx);
// check header flag `more` for next datagram, move to next datagram if exists
if (cur_data->header.m == 1 && buffer_len >= idx + ECAT_DATA_HEADER_LENGTH)
{
if (!cur_data->next)
{
cur_data->next = PrivMalloc(sizeof(EcatDatagram));
}
cur_data = (EcatDatagramPtr)cur_data->next;
}
else
{
cur_data = cur_data->next;
while (cur_data)
{
EcatDatagramPtr temp = (EcatDatagramPtr)cur_data->next;
PrivFree(cur_data->data);
PrivFree(cur_data);
cur_data = temp;
}
break;
}
} while (1);
result = data_len;
__exit:
return result;
}
/**
* @description: connnect Ethercat to internet
* @param adapter - Ethercat device pointer
* @return success: 0
*/
static int Hfa21EthercatSetUp(struct Adapter *adapter)
{
if (ethernet)
{
return AdapterDeviceSetUp(ethernet);
}
return -1;
}
/**
* @description: set ethercat ip/gateway/netmask address(in sta mode) working at WANN mode
* @param adapter - ethercat device pointer
* @param ip - ip address
* @param gateway - gateway address
* @param netmask - netmask address
* @return success: 0, failure: -ENOMEMORY or -1
*/
static int Hfa21EthercatSetAddr(struct Adapter *adapter, const char *ip, const char *gateway, const char *netmask)
{
if (ethernet)
{
return AdapterDeviceSetAddr(ethernet,
ip == NULL ? ADAPTER_ETHERCAT_HFA21_IP_SELF : ip,
gateway == NULL ? ADAPTER_ETHERCAT_HFA21_GATEWAY : gateway,
netmask == NULL ? ADAPTER_ETHERCAT_HFA21_NETMASK : netmask);
}
return -1;
}
/**
* @description: ethercat ping function
* @param adapter - ethercat device pointer
* @param destination - domain name or ip address
* @return success: 0, failure: -1
*/
static int Hfa21EthercatPing(struct Adapter *adapter, const char *destination)
{
if (ethernet)
{
return AdapterDevicePing(ethernet, destination);
}
return -1;
}
/**
* @description: ethercat connect function
* @param adapter - ethercat device pointer
* @param net_role - net role, CLIENT or SERVER
* @param ip - ip address
* @param port - port num
* @param ip_type - ip type, IPV4 or IPV6
* @return success: 0, failure: -1
*/
static int Hfa21EthercatConnect(struct Adapter *adapter, enum NetRoleType net_role, const char *ip, const char *port, enum IpType ip_type)
{
if (ethernet)
{
return AdapterDeviceConnect(ethernet, net_role, ip,
port == NULL ? ETHERCAT_PORT : port, ip_type);
}
return -1;
}
static int Hfa21EthercatIoctl(struct Adapter *adapter, int cmd, void *args)
{
if (ethernet)
{
return AdapterDeviceControl(ethernet, cmd, args);
}
return -1;
}
static const struct IpProtocolDone hfa21_ethercat_done =
{
.open = Hfa21EthercatOpen,
.close = Hfa21EthercatClose,
.ioctl = Hfa21EthercatIoctl,
.setup = Hfa21EthercatSetUp,
.setdown = Hfa21EthercatSetDown,
.setaddr = Hfa21EthercatSetAddr,
.setdns = NULL,
.setdhcp = NULL,
.ping = Hfa21EthercatPing,
.netstat = NULL,
.connect = Hfa21EthercatConnect,
.send = Hfa21EthercatSend,
.recv = Hfa21EthercatReceive,
.disconnect = NULL,
};
/**
* @description: Register ethercat device hfa21
* @return success: product_info, failure: NULL
*/
AdapterProductInfoType Hfa21EthercatAttach(struct Adapter *adapter)
{
struct AdapterProductInfo *product_info = PrivMalloc(sizeof(struct AdapterProductInfo));
if (!product_info)
{
printf("Hfa21EthercatAttach Attach malloc product_info error\n");
PrivFree(product_info);
return NULL;
}
strcpy(product_info->model_name, ADAPTER_ETHERCAT_HFA21);
product_info->model_done = (void *)&hfa21_ethercat_done;
printf("str address during init: %s\n", ADAPTER_ETHERCAT_ADDRESS_SELF);
self_address = strtoul(ADAPTER_ETHERCAT_ADDRESS_SELF, NULL, 16);
printf("self address during init: %x\n", self_address);
return product_info;
}
/**
* @description: Test case for slave ethercat device for hfa21
* @return success: 0, failure: -1
*/
int Hfa21EthercatSlaveTest(struct Adapter *adapter)
{
int baud_rate = BAUD_RATE_57600;
char ethercat_recv_msg[128] = {0};
int i, len = 0;
AdapterDeviceOpen(adapter);
AdapterDeviceControl(adapter, OPE_INT, &baud_rate);
AdapterDeviceSetUp(adapter);
// AdapterDeviceSetAddr(adapter, NULL, NULL, NULL);
enum IpType ip_type = IPV4;
printf("ready to test data transfer\n");
// for slave nodes, receive first, change the contents and then send it to next node
len = 1500;
for (i = 0; i < 10; i++)
{
// wait for neighbor node to send data
const char *ip_from = ADAPTER_ETHERCAT_HFA21_IP_FROM;
AdapterDeviceConnect(adapter, SERVER, ip_from, NULL, ip_type);
PrivTaskDelay(200);
AdapterDeviceRecv(adapter, ethercat_recv_msg, 1500);
printf("AdapterEthercatTest recv %s\n", ethercat_recv_msg);
memset(ethercat_recv_msg, 0, 128);
PrivTaskDelay(1000);
// send processed data to next node
const char *ip_to = ADAPTER_ETHERCAT_HFA21_IP_TO;
AdapterDeviceConnect(adapter, CLIENT, ip_to, NULL, ip_type);
PrivTaskDelay(200);
printf("AdapterEthercatTest send\n");
AdapterDeviceSend(adapter, NULL, len);
PrivTaskDelay(1000);
}
}
/**
* @description: Test case for master ethercat device for hfa21
* @return success: 0, failure: -1
*/
int Hfa21EthercatMasterTest(struct Adapter *adapter)
{
int baud_rate = BAUD_RATE_57600;
char ethercat_recv_msg[128] = {0};
int i, len = 0;
AdapterDeviceOpen(adapter);
AdapterDeviceControl(adapter, OPE_INT, &baud_rate);
AdapterDeviceSetUp(adapter);
// AdapterDeviceSetAddr(adapter, NULL, NULL, NULL);
// printf("setup addr\n");
enum IpType ip_type = IPV4;
// for master, manually build ethercat frame
EcatClear(&ecat_data);
printf("start build first block\n");
EcatAddress slave1;
slave1.logical = 0x01020304;
char data1[] = "cats";
EcatAppend(&ecat_data, slave1, data1, sizeof(data1));
printf("start build second block\n");
EcatAddress slave2;
slave2.logical = 0x20304050;
char data2[] = "dog";
EcatAppend(&ecat_data, slave2, data2, sizeof(data2));
printf("ready to test data transfer\n");
len = 1500;
for (i = 0; i < 10; i++)
{
// send a frame to a slave node
const char *ip_to = ADAPTER_ETHERCAT_HFA21_IP_TO;
AdapterDeviceConnect(adapter, CLIENT, ip_to, NULL, ip_type);
PrivTaskDelay(200);
printf("[AdapterEthercatTest send]\n");
AdapterDeviceSend(adapter, NULL, len);
PrivTaskDelay(1000);
// wait for slaves' responses
const char *ip_from = ADAPTER_ETHERCAT_HFA21_IP_FROM;
AdapterDeviceConnect(adapter, SERVER, ip_from, NULL, ip_type);
PrivTaskDelay(200);
AdapterDeviceRecv(adapter, ethercat_recv_msg, 1500);
printf("[AdapterEthercatTest recv] %s\n", ethercat_recv_msg);
memset(ethercat_recv_msg, 0, 128);
PrivTaskDelay(1000);
}
}

View File

@ -101,7 +101,7 @@ int AdapterEthernetTest(void)
const char *ip = "10.10.100.50";
const char *port = "12345";
enum NetRoleType net_role = SERVER;//CLIENT
enum NetRoleType net_role = CLIENT;//SERVER
enum IpType ip_type = IPV4;
AdapterDeviceConnect(adapter, net_role, ip, port, ip_type);

View File

@ -258,6 +258,10 @@ KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection #
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection/zigbee #
endif
ifeq ($(CONFIG_ADAPTER_HFA21_ETHERCAT), y)
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection/ethercat #
endif
ifeq ($(CONFIG_SUPPORT_KNOWING_FRAMEWORK), y)
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing #
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow-lite/tensorflow-lite-for-mcu/source #