SOEM v1.2.5
|
EtherCAT RAW socket driver. More...
#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <netpacket/packet.h>
#include <pthread.h>
#include "ethercattype.h"
#include "nicdrv.h"
Data Structures | |
struct | ec_stackT |
Defines | |
#define | RX_PRIM priMAC[1] |
#define | RX_SEC secMAC[1] |
Enumerations | |
enum | { ECT_RED_NONE, ECT_RED_DOUBLE } |
Functions | |
int | ec_setupnic (const char *ifname, int secondary) |
int | ec_closenic (void) |
void | ec_setupheader (void *p) |
uint8 | ec_getindex (void) |
void | ec_setbufstat (uint8 idx, int bufstat) |
int | ec_outframe (uint8 idx, int stacknumber) |
int | ec_outframe_red (uint8 idx) |
static int | ec_recvpkt (int stacknumber) |
int | ec_inframe (uint8 idx, int stacknumber) |
static int | ec_waitinframe_red (uint8 idx, struct timeval tvs) |
int | ec_waitinframe (uint8 idx, int timeout) |
int | ec_srconfirm (uint8 idx, int timeout) |
Variables | |
ec_bufT | ec_rxbuf [EC_MAXBUF] |
int | ec_rxbufstat [EC_MAXBUF] |
static int | ec_rxsa [EC_MAXBUF] |
static ec_bufT | ec_tempinbuf |
static int | ec_tempinbufs |
static ec_bufT | ec_rxbuf2 [EC_MAXBUF] |
static int | ec_rxbufstat2 [EC_MAXBUF] |
static int | ec_rxsa2 [EC_MAXBUF] |
static ec_bufT | ec_tempinbuf2 |
ec_bufT | ec_txbuf [EC_MAXBUF] |
int | ec_txbuflength [EC_MAXBUF] |
ec_bufT | ec_txbuf2 |
int | ec_txbuflength2 |
int | sockhandle = -1 |
int | sockhandle2 = -1 |
static ec_stackT | ec_stack [2] |
static uint8 | ec_lastidx |
int | ec_incnt |
int | ec_errcnt |
int | ec_redstate |
int | hlp_txtime |
int | hlp_rxtime |
const uint16 | priMAC [3] = { 0x0101, 0x0101, 0x0101 } |
const uint16 | secMAC [3] = { 0x0404, 0x0404, 0x0404 } |
pthread_mutex_t | ec_getindex_mutex = PTHREAD_MUTEX_INITIALIZER |
pthread_mutex_t | ec_tx_mutex = PTHREAD_MUTEX_INITIALIZER |
pthread_mutex_t | ec_rx_mutex = PTHREAD_MUTEX_INITIALIZER |
EtherCAT RAW socket driver.
Low level interface functions to send and receive EtherCAT packets. EtherCAT has the property that packets are only send by the master, and the send packets allways return in the receive buffer. There can be multiple packets "on the wire" before they return. To combine the received packets with the original send packets a buffer system is installed. The identifier is put in the index item of the EtherCAT header. The index is stored and compared when a frame is recieved. If there is a match the packet can be combined with the transmit packet and returned to the higher level function.
The socket layer can exhibit a reversal in the packet order (rare). If the Tx order is A-B-C the return order could be A-C-B. The indexed buffer will reorder the packets automatically.
The "redundant" option will configure two sockets and two NIC interfaces. Slaves are connected to both interfaces, one on the IN port and one on the OUT port. Packets are send via both interfaces. Any one of the connections (also an interconnect) can be removed and the slaves are still serviced with packets. The software layer will detect the possible failure modes and compensate. If needed the packets from interface A are resend through interface B. This layer if fully transparent for the higher layers.
#define RX_PRIM priMAC[1] |
second MAC word is used for identification
#define RX_SEC secMAC[1] |
second MAC word is used for identification
anonymous enum |
int ec_closenic | ( | void | ) |
Close sockets used
uint8 ec_getindex | ( | void | ) |
Get new frame identifier index and allocate corresponding rx buffer.
int ec_inframe | ( | uint8 | idx, |
int | stacknumber | ||
) |
Non blocking receive frame function. Uses RX buffer and index to combine read frame with transmitted frame. To compensate for received frames that are out-of-order all frames are stored in their respective indexed buffer. If a frame was placed in the buffer previously, the function retreives it from that buffer index without calling ec_recvpkt. If the requested index is not already in the buffer it calls ec_recvpkt to fetch it. There are three options now, 1 no frame read, so exit. 2 frame read but other than requested index, store in buffer and exit. 3 frame read with matching index, store in buffer, set completed flag in buffer status and exit.
[in] | idx | = requested index of frame |
[in] | stacknumber | = 0=primary 1=secondary stack |
int ec_outframe | ( | uint8 | idx, |
int | stacknumber | ||
) |
Transmit buffer over socket (non blocking).
[in] | idx | = index in tx buffer array |
[in] | stacknumber | = 0=Primary 1=Secondary stack |
int ec_outframe_red | ( | uint8 | idx | ) |
Transmit buffer over socket (non blocking).
[in] | idx | = index in tx buffer array |
static int ec_recvpkt | ( | int | stacknumber | ) | [static] |
Non blocking read of socket. Put frame in temporary buffer.
[in] | stacknumber | = 0=primary 1=secondary stack |
void ec_setbufstat | ( | uint8 | idx, |
int | bufstat | ||
) |
Set rx buffer status.
[in] | idx | = index in buffer array |
[in] | bufstat | = status to set |
void ec_setupheader | ( | void * | p | ) |
Fill buffer with ethernet header structure. Destination MAC is allways broadcast. Ethertype is allways ETH_P_ECAT.
[out] | p | = buffer |
int ec_setupnic | ( | const char * | ifname, |
int | secondary | ||
) |
Basic setup to connect NIC to socket.
[in] | ifname | = Name of NIC device, f.e. "eth0" |
[in] | secondary | = if >0 then use secondary stack instead of primary |
int ec_srconfirm | ( | uint8 | idx, |
int | timeout | ||
) |
Blocking send and recieve frame function. Used for non processdata frames. A datagram is build into a frame and transmitted via this function. It waits for an answer and returns the workcounter. The function retries if time is left and the result is WKC=0 or no frame received.
The function calls ec_outframe_red() and ec_waitinframe_red().
[in] | idx | = index of frame |
[in] | timeout | = timeout in us |
int ec_waitinframe | ( | uint8 | idx, |
int | timeout | ||
) |
Blocking receive frame function. Calls ec_waitinframe_red().
[in] | idx | = requested index of frame |
[in] | timeout | = timeout in us |
static int ec_waitinframe_red | ( | uint8 | idx, |
struct timeval | tvs | ||
) | [static] |
Blocking redundant receive frame function. If redundant mode is not active then it skips the secondary stack and redundancy functions. In redundant mode it waits for both (primary and secondary) frames to come in. The result goes in an decision tree that decides, depending on the route of the packet and its possible missing arrival, how to reroute the original packet to get the data in an other try.
[in] | idx | = requested index of frame |
[in] | tvs | = timeout |
int ec_errcnt |
global error packet counter, ie non EtherCAT packets
pthread_mutex_t ec_getindex_mutex = PTHREAD_MUTEX_INITIALIZER |
int ec_incnt |
global rx packet counter, counts only EtherCAT packets
uint8 ec_lastidx [static] |
last used frame index
int ec_redstate |
current redundancy state
pthread_mutex_t ec_rx_mutex = PTHREAD_MUTEX_INITIALIZER |
int ec_rxbufstat[EC_MAXBUF] |
primary rx buffer status
int ec_rxbufstat2[EC_MAXBUF] [static] |
secondary rx buffer status
int ec_rxsa[EC_MAXBUF] [static] |
primary rx MAC source address
int ec_rxsa2[EC_MAXBUF] [static] |
secondary rx MAC source address
{{&sockhandle, &ec_txbuf, &ec_txbuflength, &ec_tempinbuf, &ec_rxbuf, &ec_rxbufstat, &ec_rxsa}, {&sockhandle2, &ec_txbuf, &ec_txbuflength, &ec_tempinbuf2, &ec_rxbuf2, &ec_rxbufstat2, &ec_rxsa2}}
primary and secondary tx/rx stack pointers
ec_bufT ec_tempinbuf [static] |
primary temporary rx buffer
ec_bufT ec_tempinbuf2 [static] |
secondary temporary rx buffer
int ec_tempinbufs [static] |
primary temporary rx buffer status
pthread_mutex_t ec_tx_mutex = PTHREAD_MUTEX_INITIALIZER |
int ec_txbuflength[EC_MAXBUF] |
transmit buffer lenghts
int ec_txbuflength2 |
temporary tx buffer length
int hlp_rxtime |
global helper var ri count time used in rx socket
int hlp_txtime |
global helper var to count time used in tx socket
Primary source MAC address used for EtherCAT. This address is not the MAC address used from the NIC. EtherCAT does not care about MAC addressing, but it is used here to differentiate the route the packet traverses through the EtherCAT segment. This is needed to find out the packet flow in redundant configurations.
int sockhandle = -1 |
primary socket handle
int sockhandle2 = -1 |
secondary socket handle