/* * Licensed under the GNU General Public License version 2 with exceptions. See * LICENSE file in the project root for full license information */ /** \file * \brief * General typedefs and defines for EtherCAT. * * Defines that could need optimisation for specific applications * are the EC_TIMEOUTxxx. Assumptions for the standard settings are a * standard linux PC or laptop and a wired connection to maximal 100 slaves. * For use with wireless connections or lots of slaves the timeouts need * increasing. For fast systems running Xenomai and RT-net or alike the * timeouts need to be shorter. */ #ifndef _EC_TYPE_H #define _EC_TYPE_H #ifdef __cplusplus extern "C" { #endif #include "osal.h" /** define EC_VER1 if version 1 default context and functions are needed * define EC_VER2 if application uses only ecx_ functions and own context */ #if !defined(EC_VER1) && !defined(EC_VER2) # define EC_VER1 #endif /** Define little endian target by default if no endian is set */ #if !defined(EC_LITTLE_ENDIAN) && !defined(EC_BIG_ENDIAN) # define EC_LITTLE_ENDIAN #endif /** return value no frame returned */ #define EC_NOFRAME -1 /** return value unknown frame received */ #define EC_OTHERFRAME -2 /** return value general error */ #define EC_ERROR -3 /** return value too many slaves */ #define EC_SLAVECOUNTEXCEEDED -4 /** return value request timeout */ #define EC_TIMEOUT -5 /** maximum EtherCAT frame length in bytes */ #define EC_MAXECATFRAME 1518 /** maximum EtherCAT LRW frame length in bytes */ /* MTU - Ethernet header - length - datagram header - WCK - FCS */ #define EC_MAXLRWDATA (EC_MAXECATFRAME - 14 - 2 - 10 - 2 - 4) /** size of DC datagram used in first LRW frame */ #define EC_FIRSTDCDATAGRAM 20 /** standard frame buffer size in bytes */ #define EC_BUFSIZE EC_MAXECATFRAME /** datagram type EtherCAT */ #define EC_ECATTYPE 0x1000 /** number of frame buffers per channel (tx, rx1 rx2) */ #define EC_MAXBUF 16 /** timeout value in us for tx frame to return to rx */ #define EC_TIMEOUTRET 2000 /** timeout value in us for safe data transfer, max. triple retry */ #define EC_TIMEOUTRET3 (EC_TIMEOUTRET * 3) /** timeout value in us for return "safe" variant (f.e. wireless) */ #define EC_TIMEOUTSAFE 20000 /** timeout value in us for EEPROM access */ #define EC_TIMEOUTEEP 20000 /** timeout value in us for tx mailbox cycle */ #define EC_TIMEOUTTXM 20000 /** timeout value in us for rx mailbox cycle */ #define EC_TIMEOUTRXM 700000 /** timeout value in us for check statechange */ #define EC_TIMEOUTSTATE 2000000 /** size of EEPROM bitmap cache */ #define EC_MAXEEPBITMAP 128 /** size of EEPROM cache buffer */ #define EC_MAXEEPBUF EC_MAXEEPBITMAP << 5 /** default number of retries if wkc <= 0 */ #define EC_DEFAULTRETRIES 3 /** default group size in 2^x */ #define EC_LOGGROUPOFFSET 16 /** definition for frame buffers */ typedef uint8 ec_bufT[EC_BUFSIZE]; /** ethernet header definition */ PACKED_BEGIN typedef struct PACKED { /** destination MAC */ uint16 da0,da1,da2; /** source MAC */ uint16 sa0,sa1,sa2; /** ethernet type */ uint16 etype; } ec_etherheadert; PACKED_END /** ethernet header size */ #define ETH_HEADERSIZE sizeof(ec_etherheadert) /** EtherCAT datagram header definition */ PACKED_BEGIN typedef struct PACKED { /** length of EtherCAT datagram */ uint16 elength; /** EtherCAT command, see ec_cmdtype */ uint8 command; /** index, used in SOEM for Tx to Rx recombination */ uint8 index; /** ADP */ uint16 ADP; /** ADO */ uint16 ADO; /** length of data portion in datagram */ uint16 dlength; /** interrupt, currently unused */ uint16 irpt; } ec_comt; PACKED_END /** EtherCAT header size */ #define EC_HEADERSIZE sizeof(ec_comt) /** size of ec_comt.elength item in EtherCAT header */ #define EC_ELENGTHSIZE sizeof(uint16) /** offset position of command in EtherCAT header */ #define EC_CMDOFFSET EC_ELENGTHSIZE /** size of workcounter item in EtherCAT datagram */ #define EC_WKCSIZE sizeof(uint16) /** definition of datagram follows bit in ec_comt.dlength */ #define EC_DATAGRAMFOLLOWS (1 << 15) /** Possible error codes returned. */ typedef enum { /** No error */ EC_ERR_OK = 0, /** Library already initialized. */ EC_ERR_ALREADY_INITIALIZED, /** Library not initialized. */ EC_ERR_NOT_INITIALIZED, /** Timeout occurred during execution of the function. */ EC_ERR_TIMEOUT, /** No slaves were found. */ EC_ERR_NO_SLAVES, /** Function failed. */ EC_ERR_NOK } ec_err; /** 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; /** Possible buffer states */ typedef enum { /** Empty */ EC_BUF_EMPTY = 0x00, /** Allocated, but not filled */ EC_BUF_ALLOC = 0x01, /** Transmitted */ EC_BUF_TX = 0x02, /** Received, but not consumed */ EC_BUF_RCVD = 0x03, /** Cycle completed */ EC_BUF_COMPLETE = 0x04 } ec_bufstate; /** Ethercat data types */ typedef enum { ECT_BOOLEAN = 0x0001, ECT_INTEGER8 = 0x0002, ECT_INTEGER16 = 0x0003, ECT_INTEGER32 = 0x0004, ECT_UNSIGNED8 = 0x0005, ECT_UNSIGNED16 = 0x0006, ECT_UNSIGNED32 = 0x0007, ECT_REAL32 = 0x0008, ECT_VISIBLE_STRING = 0x0009, ECT_OCTET_STRING = 0x000A, ECT_UNICODE_STRING = 0x000B, ECT_TIME_OF_DAY = 0x000C, ECT_TIME_DIFFERENCE = 0x000D, ECT_DOMAIN = 0x000F, ECT_INTEGER24 = 0x0010, ECT_REAL64 = 0x0011, ECT_INTEGER64 = 0x0015, ECT_UNSIGNED24 = 0x0016, ECT_UNSIGNED64 = 0x001B, ECT_BIT1 = 0x0030, ECT_BIT2 = 0x0031, ECT_BIT3 = 0x0032, ECT_BIT4 = 0x0033, ECT_BIT5 = 0x0034, ECT_BIT6 = 0x0035, ECT_BIT7 = 0x0036, ECT_BIT8 = 0x0037 } ec_datatype; /** Ethercat command types */ typedef enum { /** No operation */ EC_CMD_NOP = 0x00, /** 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 */ } ec_cmdtype; /** 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; /** EEprom state machine read size */ #define EC_ESTAT_R64 0x0040 /** EEprom state machine busy flag */ #define EC_ESTAT_BUSY 0x8000 /** EEprom state machine error flag mask */ #define EC_ESTAT_EMASK 0x7800 /** EEprom state machine error acknowledge */ #define EC_ESTAT_NACK 0x2000 /* Ethercat SSI (Slave Information Interface) */ /** Start address SII sections in Eeprom */ #define ECT_SII_START 0x0040 enum { /** SII category strings */ ECT_SII_STRING = 10, /** SII category general */ ECT_SII_GENERAL = 30, /** SII category FMMU */ ECT_SII_FMMU = 40, /** SII category SM */ ECT_SII_SM = 41, /** SII category PDO */ ECT_SII_PDO = 50 }; /** 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 }; /** Mailbox types definitions */ enum { /** Error mailbox type */ ECT_MBXT_ERR = 0x00, /** ADS over EtherCAT mailbox type */ ECT_MBXT_AOE, /** Ethernet over EtherCAT mailbox type */ ECT_MBXT_EOE, /** CANopen over EtherCAT mailbox type */ ECT_MBXT_COE, /** File over EtherCAT mailbox type */ ECT_MBXT_FOE, /** Servo over EtherCAT mailbox type */ ECT_MBXT_SOE, /** Vendor over EtherCAT mailbox type */ ECT_MBXT_VOE = 0x0f }; /** CoE mailbox types */ enum { ECT_COES_EMERGENCY = 0x01, ECT_COES_SDOREQ, ECT_COES_SDORES, ECT_COES_TXPDO, ECT_COES_RXPDO, ECT_COES_TXPDO_RR, ECT_COES_RXPDO_RR, ECT_COES_SDOINFO }; /** CoE SDO commands */ enum { ECT_SDO_DOWN_INIT = 0x21, ECT_SDO_DOWN_EXP = 0x23, ECT_SDO_DOWN_INIT_CA = 0x31, ECT_SDO_UP_REQ = 0x40, ECT_SDO_UP_REQ_CA = 0x50, ECT_SDO_SEG_UP_REQ = 0x60, ECT_SDO_ABORT = 0x80 }; /** CoE Object Description commands */ enum { ECT_GET_ODLIST_REQ = 0x01, ECT_GET_ODLIST_RES = 0x02, ECT_GET_OD_REQ = 0x03, ECT_GET_OD_RES = 0x04, ECT_GET_OE_REQ = 0x05, ECT_GET_OE_RES = 0x06, ECT_SDOINFO_ERROR = 0x07 }; /** FoE opcodes */ enum { ECT_FOE_READ = 0x01, ECT_FOE_WRITE, ECT_FOE_DATA, ECT_FOE_ACK, ECT_FOE_ERROR, ECT_FOE_BUSY }; /** SoE opcodes */ enum { ECT_SOE_READREQ = 0x01, ECT_SOE_READRES, ECT_SOE_WRITEREQ, ECT_SOE_WRITERES, ECT_SOE_NOTIFICATION, ECT_SOE_EMERGENCY }; /** Ethercat registers */ enum { 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_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 }; /** standard SDO Sync Manager Communication Type */ #define ECT_SDO_SMCOMMTYPE 0x1c00 /** standard SDO PDO assignment */ #define ECT_SDO_PDOASSIGN 0x1c10 /** standard SDO RxPDO assignment */ #define ECT_SDO_RXPDOASSIGN 0x1c12 /** standard SDO TxPDO assignment */ #define ECT_SDO_TXPDOASSIGN 0x1c13 /** Ethercat packet type */ #define ETH_P_ECAT 0x88A4 /** Error types */ typedef enum { EC_ERR_TYPE_SDO_ERROR = 0, EC_ERR_TYPE_EMERGENCY = 1, EC_ERR_TYPE_PACKET_ERROR = 3, EC_ERR_TYPE_SDOINFO_ERROR = 4, EC_ERR_TYPE_FOE_ERROR = 5, EC_ERR_TYPE_FOE_BUF2SMALL = 6, EC_ERR_TYPE_FOE_PACKETNUMBER = 7, EC_ERR_TYPE_SOE_ERROR = 8, EC_ERR_TYPE_MBX_ERROR = 9, EC_ERR_TYPE_FOE_FILE_NOTFOUND = 10, EC_ERR_TYPE_EOE_INVALID_RX_DATA = 11 } ec_err_type; /** Struct to retrieve errors. */ typedef struct { /** Time at which the error was generated. */ ec_timet Time; /** Signal bit, error set but not read */ boolean Signal; /** Slave number that generated the error */ uint16 Slave; /** CoE SDO index that generated the error */ uint16 Index; /** CoE SDO subindex that generated the error */ uint8 SubIdx; /** Type of error */ ec_err_type Etype; union { /** General abortcode */ int32 AbortCode; /** Specific error for Emergency mailbox */ struct { uint16 ErrorCode; uint8 ErrorReg; uint8 b1; uint16 w1; uint16 w2; }; }; } ec_errort; /** Helper macros */ /** Set the count value in the Mailbox header */ #define MBX_HDR_SET_CNT(cnt) ((uint8)((cnt) << 4)) /** Macro to make a word from 2 bytes */ #define MK_WORD(msb, lsb) ((((uint16)(msb))<<8) | (lsb)) /** Macro to get hi byte of a word */ #define HI_BYTE(w) ((w) >> 8) /** Macro to get low byte of a word */ #define LO_BYTE(w) ((w) & 0x00ff) /** Macro to swap hi and low byte of a word */ #define SWAP(w) ((((w)& 0xff00) >> 8) | (((w) & 0x00ff) << 8)) /** Macro to get hi word of a dword */ #define LO_WORD(l) ((l) & 0xffff) /** Macro to get hi word of a dword */ #define HI_WORD(l) ((l) >> 16) #define get_unaligned(ptr) \ ({ __typeof__(*(ptr)) __tmp; memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) #define put_unaligned32(val, ptr) \ (memcpy((ptr), &(val), 4)) #define put_unaligned64(val, ptr) \ (memcpy((ptr), &(val), 8)) #if !defined(EC_BIG_ENDIAN) && defined(EC_LITTLE_ENDIAN) #define htoes(A) (A) #define htoel(A) (A) #define htoell(A) (A) #define etohs(A) (A) #define etohl(A) (A) #define etohll(A) (A) #elif !defined(EC_LITTLE_ENDIAN) && defined(EC_BIG_ENDIAN) #define htoes(A) ((((uint16)(A) & 0xff00) >> 8) | \ (((uint16)(A) & 0x00ff) << 8)) #define htoel(A) ((((uint32)(A) & 0xff000000) >> 24) | \ (((uint32)(A) & 0x00ff0000) >> 8) | \ (((uint32)(A) & 0x0000ff00) << 8) | \ (((uint32)(A) & 0x000000ff) << 24)) #define htoell(A) ((((uint64)(A) & (uint64)0xff00000000000000ULL) >> 56) | \ (((uint64)(A) & (uint64)0x00ff000000000000ULL) >> 40) | \ (((uint64)(A) & (uint64)0x0000ff0000000000ULL) >> 24) | \ (((uint64)(A) & (uint64)0x000000ff00000000ULL) >> 8) | \ (((uint64)(A) & (uint64)0x00000000ff000000ULL) << 8) | \ (((uint64)(A) & (uint64)0x0000000000ff0000ULL) << 24) | \ (((uint64)(A) & (uint64)0x000000000000ff00ULL) << 40) | \ (((uint64)(A) & (uint64)0x00000000000000ffULL) << 56)) #define etohs htoes #define etohl htoel #define etohll htoell #else #error "Must define one of EC_BIG_ENDIAN or EC_LITTLE_ENDIAN" #endif #ifdef __cplusplus } #endif #endif /* _EC_TYPE_H */