mirror of
https://github.com/OpenEtherCATsociety/SOEM.git
synced 2026-09-28 16:13:23 +08:00
Add ERIKA Enterprise RTOS support
This patch adds support to SOEM for the ERIKA Enterprise RTOS (erika-enterprise.com). Current requirements for running SOEM on ERIKA RTOS: - x86-64 platform with 2+ cores - Xen hypervisor - Intel i210 PCIe Ethernet controller Signed-off-by: Claudio Scordino <claudio@evidence.eu.com> Signed-off-by: Luca Cuomo <l.cuomo@evidence.eu.com>
This commit is contained in:
committed by
nakarlsson
parent
ab89d557d5
commit
29df9ba013
@@ -29,6 +29,11 @@ Linux
|
||||
* `cmake ..`
|
||||
* `make`
|
||||
|
||||
ERIKA Enterprise RTOS
|
||||
---------------------
|
||||
|
||||
* Refer to http://www.erika-enterprise.com/wiki/index.php?title=EtherCAT_Master
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Licensed under the GNU General Public License version 2 with exceptions. See
|
||||
* LICENSE file in the project root for full license information
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <osal.h>
|
||||
|
||||
#include "ee_x86_64_tsc.h"
|
||||
|
||||
#define USECS_PER_SEC 1000000
|
||||
#define NSECS_PER_SEC 1000000000
|
||||
|
||||
uint64_t osEE_x86_64_tsc_read(void);
|
||||
|
||||
void ee_usleep(uint32 usec);
|
||||
|
||||
inline int osal_usleep (uint32 usec)
|
||||
{
|
||||
ee_usleep(usec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int osal_gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
uint64_t time = osEE_x86_64_tsc_read();
|
||||
tv->tv_sec = time/NSECS_PER_SEC;
|
||||
tv->tv_sec += 946684800UL; /* EtherCAT uses 2000-01-01 as epoch start */
|
||||
tv->tv_usec = (time%NSECS_PER_SEC)/1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ec_timet osal_current_time(void)
|
||||
{
|
||||
struct timeval current_time;
|
||||
ec_timet ret;
|
||||
|
||||
osal_gettimeofday(¤t_time, 0);
|
||||
ret.sec = current_time.tv_sec;
|
||||
ret.usec = current_time.tv_usec;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void osal_time_diff(ec_timet *start, ec_timet *end, ec_timet *diff)
|
||||
{
|
||||
if (end->usec < start->usec) {
|
||||
diff->sec = end->sec - start->sec - 1;
|
||||
diff->usec = end->usec + USECS_PER_SEC - start->usec;
|
||||
} else {
|
||||
diff->sec = end->sec - start->sec;
|
||||
diff->usec = end->usec - start->usec;
|
||||
}
|
||||
}
|
||||
|
||||
void osal_timer_start(osal_timert *self, uint32 timeout_usec)
|
||||
{
|
||||
struct timeval start_time;
|
||||
struct timeval timeout;
|
||||
struct timeval stop_time;
|
||||
|
||||
osal_gettimeofday(&start_time, 0);
|
||||
timeout.tv_sec = timeout_usec / USECS_PER_SEC;
|
||||
timeout.tv_usec = timeout_usec % USECS_PER_SEC;
|
||||
timeradd(&start_time, &timeout, &stop_time);
|
||||
|
||||
self->stop_time.sec = stop_time.tv_sec;
|
||||
self->stop_time.usec = stop_time.tv_usec;
|
||||
}
|
||||
|
||||
boolean osal_timer_is_expired (osal_timert *self)
|
||||
{
|
||||
struct timeval current_time;
|
||||
struct timeval stop_time;
|
||||
int is_not_yet_expired;
|
||||
|
||||
osal_gettimeofday (¤t_time, 0);
|
||||
stop_time.tv_sec = self->stop_time.sec;
|
||||
stop_time.tv_usec = self->stop_time.usec;
|
||||
is_not_yet_expired = timercmp (¤t_time, &stop_time, <);
|
||||
/* OSEE_PRINT("current: %d:%d -- expire: %d:%d -- result: %d\n", */
|
||||
/* current_time.tv_sec, */
|
||||
/* current_time.tv_usec, */
|
||||
/* stop_time.tv_sec, */
|
||||
/* stop_time.tv_usec, */
|
||||
/* is_not_yet_expired); */
|
||||
|
||||
return is_not_yet_expired == FALSE;
|
||||
}
|
||||
|
||||
void *osal_malloc(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void osal_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Licensed under the GNU General Public License version 2 with exceptions. See
|
||||
* LICENSE file in the project root for full license information
|
||||
*/
|
||||
|
||||
#ifndef _osal_defs_
|
||||
#define _osal_defs_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <ee.h>
|
||||
|
||||
// define if debug print is needed
|
||||
#define EC_DEBUG
|
||||
|
||||
#ifdef EC_DEBUG
|
||||
#define EC_PRINT OSEE_PRINT
|
||||
#else
|
||||
#define EC_PRINT(...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef PACKED
|
||||
#define PACKED_BEGIN
|
||||
#define PACKED __attribute__((__packed__))
|
||||
#define PACKED_END
|
||||
#endif
|
||||
|
||||
int osal_gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
void *osal_malloc(size_t size);
|
||||
void osal_free(void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Licensed under the GNU General Public License version 2 with exceptions. See
|
||||
* LICENSE file in the project root for full license information
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief
|
||||
* Headerfile for nicdrv.c
|
||||
*/
|
||||
|
||||
#ifndef _nicdrvh_
|
||||
#define _nicdrvh_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** socket connection used */
|
||||
int *sock;
|
||||
/** tx buffer */
|
||||
ec_bufT (*txbuf)[EC_MAXBUF];
|
||||
/** tx buffer lengths */
|
||||
int (*txbuflength)[EC_MAXBUF];
|
||||
/** temporary receive buffer */
|
||||
ec_bufT *tempbuf;
|
||||
/** rx buffers */
|
||||
ec_bufT (*rxbuf)[EC_MAXBUF];
|
||||
/** rx buffer status fields */
|
||||
int (*rxbufstat)[EC_MAXBUF];
|
||||
/** received MAC source address (middle word) */
|
||||
int (*rxsa)[EC_MAXBUF];
|
||||
} ec_stackT;
|
||||
|
||||
/** pointer structure to buffers for redundant port */
|
||||
typedef struct
|
||||
{
|
||||
ec_stackT stack;
|
||||
int sockhandle;
|
||||
/** rx buffers */
|
||||
ec_bufT rxbuf[EC_MAXBUF];
|
||||
/** rx buffer status */
|
||||
int rxbufstat[EC_MAXBUF];
|
||||
/** rx MAC source address */
|
||||
int rxsa[EC_MAXBUF];
|
||||
/** temporary rx buffer */
|
||||
ec_bufT tempinbuf;
|
||||
} ecx_redportt;
|
||||
|
||||
/** pointer structure to buffers, vars and mutexes for port instantiation */
|
||||
typedef struct
|
||||
{
|
||||
ec_stackT stack;
|
||||
int sockhandle;
|
||||
/** rx buffers */
|
||||
ec_bufT rxbuf[EC_MAXBUF];
|
||||
/** rx buffer status */
|
||||
int rxbufstat[EC_MAXBUF];
|
||||
/** rx MAC source address */
|
||||
int rxsa[EC_MAXBUF];
|
||||
/** temporary rx buffer */
|
||||
ec_bufT tempinbuf;
|
||||
/** temporary rx buffer status */
|
||||
int tempinbufs;
|
||||
/** transmit buffers */
|
||||
ec_bufT txbuf[EC_MAXBUF];
|
||||
/** transmit buffer lengths */
|
||||
int txbuflength[EC_MAXBUF];
|
||||
/** temporary tx buffer */
|
||||
ec_bufT txbuf2;
|
||||
/** temporary tx buffer length */
|
||||
int txbuflength2;
|
||||
/** last used frame index */
|
||||
int lastidx;
|
||||
/** current redundancy state */
|
||||
int redstate;
|
||||
/** pointer to redundancy port and buffers */
|
||||
ecx_redportt *redport;
|
||||
|
||||
/** Device id in the device pool */
|
||||
int dev_id;
|
||||
|
||||
// TODO: add mutex support
|
||||
} ecx_portt;
|
||||
|
||||
extern const uint16 priMAC[3];
|
||||
extern const uint16 secMAC[3];
|
||||
|
||||
#ifdef EC_VER1
|
||||
extern ecx_portt ecx_port;
|
||||
extern ecx_redportt ecx_redport;
|
||||
|
||||
int ec_setupnic(const char * ifname, int secondary);
|
||||
int ec_closenic(void);
|
||||
void ec_setbufstat(int idx, int bufstat);
|
||||
int ec_getindex(void);
|
||||
int ec_outframe(int idx, int sock);
|
||||
int ec_outframe_red(int idx);
|
||||
int ec_waitinframe(int idx, int timeout);
|
||||
int ec_srconfirm(int idx,int timeout);
|
||||
int ec_inframe(int idx, int stacknumber);
|
||||
#endif
|
||||
|
||||
void ec_setupheader(void *p);
|
||||
int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary);
|
||||
int ecx_closenic(ecx_portt *port);
|
||||
void ecx_setbufstat(ecx_portt *port, int idx, int bufstat);
|
||||
int ecx_getindex(ecx_portt *port);
|
||||
int ecx_outframe(ecx_portt *port, int idx, int sock);
|
||||
int ecx_outframe_red(ecx_portt *port, int idx);
|
||||
int ecx_waitinframe(ecx_portt *port, int idx, int timeout);
|
||||
int ecx_srconfirm(ecx_portt *port, int idx,int timeout);
|
||||
|
||||
int ecx_inframe(ecx_portt *port, int idx, int stacknumber);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Licensed under the GNU General Public License version 2 with exceptions. See
|
||||
* LICENSE file in the project root for full license information
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "oshw.h"
|
||||
#include "intel_i210.h"
|
||||
#include "ethercat.h"
|
||||
|
||||
#if !defined(__gnu_linux__)
|
||||
#include <machine/endian.h>
|
||||
#else
|
||||
#include <endian.h>
|
||||
#define __htons(x) htobe16(x)
|
||||
#define __ntohs(x) be16toh(x)
|
||||
#endif
|
||||
|
||||
ec_adaptert adapters [DEVS_MAX_NB];
|
||||
|
||||
/**
|
||||
* Host to Network byte order (i.e. to big endian).
|
||||
*
|
||||
* Note that Ethercat uses little endian byte order, except for the Ethernet
|
||||
* header which is big endian as usual.
|
||||
*/
|
||||
inline uint16 oshw_htons(uint16 host)
|
||||
{
|
||||
// __htons() is provided by the bare-metal x86 compiler
|
||||
return __htons(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Network (i.e. big endian) to Host byte order.
|
||||
*
|
||||
* Note that Ethercat uses little endian byte order, except for the Ethernet
|
||||
* header which is big endian as usual.
|
||||
*/
|
||||
inline uint16 oshw_ntohs(uint16 network)
|
||||
{
|
||||
// __ntohs() is provided by the bare-metal x86 compiler
|
||||
return __ntohs(network);
|
||||
}
|
||||
|
||||
/** Create list over available network adapters.
|
||||
* @return First element in linked list of adapters
|
||||
*/
|
||||
ec_adaptert* oshw_find_adapters(void)
|
||||
{
|
||||
ec_adaptert *ret = NULL;
|
||||
if (eth_discover_devices() >= 0) {
|
||||
for (int i = 0;; ++i) {
|
||||
struct eth_device *dev = eth_get_device(i);
|
||||
if (dev == NULL) {
|
||||
adapters[i-1].next = NULL;
|
||||
break;
|
||||
}
|
||||
strncpy(adapters[i].name, dev->name, MAX_DEVICE_NAME);
|
||||
adapters[i].next = &adapters[i+1];
|
||||
}
|
||||
ret = &(adapters[0]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Free memory allocated memory used by adapter collection.
|
||||
* @param[in] adapter = First element in linked list of adapters
|
||||
* EC_NOFRAME.
|
||||
*/
|
||||
void oshw_free_adapters(ec_adaptert *adapter)
|
||||
{
|
||||
}
|
||||
|
||||
extern int ec_slavecount;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Licensed under the GNU General Public License version 2 with exceptions. See
|
||||
* LICENSE file in the project root for full license information
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief
|
||||
* Headerfile for ethercatbase.c
|
||||
*/
|
||||
|
||||
#ifndef _oshw_
|
||||
#define _oshw_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ethercattype.h"
|
||||
#include "nicdrv.h"
|
||||
#include "ethercatmain.h"
|
||||
|
||||
uint16 oshw_htons(uint16 hostshort);
|
||||
uint16 oshw_ntohs(uint16 networkshort);
|
||||
ec_adaptert* oshw_find_adapters(void);
|
||||
void oshw_free_adapters(ec_adaptert * adapter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user