fp@104: /****************************************************************************** fp@104: * fp@1341: * $Id$ fp@1341: * fp@2433: * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH fp@1341: * fp@1341: * This file is part of the IgH EtherCAT master userspace library. ch1010858@2241: * fp@1341: * The IgH EtherCAT master userspace library is free software; you can fp@1341: * redistribute it and/or modify it under the terms of the GNU Lesser General fp@1341: * Public License as published by the Free Software Foundation; version 2.1 fp@1341: * of the License. fp@1341: * fp@1341: * The IgH EtherCAT master userspace library is distributed in the hope that fp@1341: * it will be useful, but WITHOUT ANY WARRANTY; without even the implied fp@1341: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fp@1341: * GNU Lesser General Public License for more details. fp@1341: * fp@1341: * You should have received a copy of the GNU Lesser General Public License fp@1341: * along with the IgH EtherCAT master userspace library. If not, see fp@1341: * . ch1010858@2241: * fp@1363: * --- ch1010858@2241: * fp@1363: * The license mentioned above concerns the source code only. Using the fp@1363: * EtherCAT technology and brand is only permitted in compliance with the fp@1363: * industrial property and similar rights of Beckhoff Automation GmbH. fp@246: * fp@104: *****************************************************************************/ fp@104: fp@786: /** \file fp@786: * fp@1182: * EtherCAT master application interface. fp@1182: * fp@1182: * \defgroup ApplicationInterface EtherCAT Application Interface fp@786: * fp@879: * EtherCAT interface for realtime applications. This interface is designed fp@879: * for realtime modules that want to use EtherCAT. There are functions to fp@879: * request a master, to map process data, to communicate with slaves via CoE fp@879: * and to configure and activate the bus. fp@2419: * fp@2524: * Changes in version 1.5.2: fp@2368: * fp@2368: * - Added redundancy_active flag to ec_domain_state_t. fp@2380: * - Added ecrt_master_link_state() method and ec_master_link_state_t to query fp@2380: * the state of a redundant link. fp@2381: * - Added the EC_HAVE_REDUNDANCY define, to check, if the interface contains fp@2381: * redundancy features. fp@2434: * - Added ecrt_sdo_request_index() to change SDO index and subindex after fp@2434: * handler creation. fp@2438: * - Added interface for retrieving CoE emergency messages, i. e. fp@2438: * ecrt_slave_config_emerg_size(), ecrt_slave_config_emerg_pop(), fp@2438: * ecrt_slave_config_emerg_clear(), ecrt_slave_config_emerg_overruns() and fp@2438: * the defines EC_HAVE_EMERGENCY and EC_COE_EMERGENCY_MSG_SIZE. fp@2443: * - Added interface for direct EtherCAT register access: Added data type fp@2443: * ec_reg_request_t and methods ecrt_slave_config_create_reg_request(), fp@2443: * ecrt_reg_request_data(), ecrt_reg_request_state(), fp@2445: * ecrt_reg_request_write(), ecrt_reg_request_read() and the feature flag fp@2445: * EC_HAVE_REG_ACCESS. fp@2447: * - Added method to select the reference clock, fp@2447: * ecrt_master_select_reference_clock() and the feature flag fp@2447: * EC_HAVE_SELECT_REF_CLOCK to check, if the method is available. fp@2447: * - Added method to get the reference clock time, fp@2447: * ecrt_master_reference_clock_time() and the feature flag fp@2447: * EC_HAVE_REF_CLOCK_TIME to have the possibility to synchronize the master fp@2447: * clock to the reference clock. fp@2523: * - Changed the data types of the shift times in ecrt_slave_config_dc() to fp@2449: * int32_t to correctly display negative shift times. fp@2505: * - Added ecrt_slave_config_reg_pdo_entry_pos() and the feature flag fp@2505: * EC_HAVE_REG_BY_POS for registering PDO entries with non-unique indices fp@2505: * via their positions in the mapping. fp@792: * fp@1239: * Changes in version 1.5: fp@1239: * fp@1448: * - Added the distributed clocks feature and the respective method fp@1500: * ecrt_slave_config_dc() to configure a slave for cyclic operation, and fp@1500: * ecrt_master_application_time(), ecrt_master_sync_reference_clock() and fp@1500: * ecrt_master_sync_slave_clocks() for offset and drift compensation. The fp@1535: * EC_TIMEVAL2NANO() macro can be used for epoch time conversion, while the fp@1535: * ecrt_master_sync_monitor_queue() and ecrt_master_sync_monitor_process() ch1010858@2241: * methods can be used to monitor the synchrony. fp@1500: * - Improved the callback mechanism. ecrt_master_callbacks() now takes two fp@1500: * callback functions for sending and receiving datagrams. fp@1500: * ecrt_master_send_ext() is used to execute the sending of non-application fp@1500: * datagrams. fp@1509: * - Added watchdog configuration (method ecrt_slave_config_watchdog(), fp@1509: * #ec_watchdog_mode_t, \a watchdog_mode parameter in ec_sync_info_t and fp@1509: * ecrt_slave_config_sync_manager()). fp@1526: * - Added ecrt_slave_config_complete_sdo() method to download an SDO during fp@1526: * configuration via CompleteAccess. fp@1530: * - Added ecrt_master_deactivate() to remove the bus configuration. fp@1497: * - Added ecrt_open_master() and ecrt_master_reserve() separation for fp@1497: * userspace. fp@1510: * - Added bus information interface (methods ecrt_master(), fp@1510: * ecrt_master_get_slave(), ecrt_master_get_sync_manager(), fp@1510: * ecrt_master_get_pdo() and ecrt_master_get_pdo_entry()) to get information fp@1510: * about the currently connected slaves and the PDO entries provided. fp@2124: * - Added ecrt_master_sdo_download(), ecrt_master_sdo_download_complete() and fp@2124: * ecrt_master_sdo_upload() methods to let an application transfer SDOs fp@2124: * before activating the master. fp@1313: * - Changed the meaning of the negative return values of fp@1313: * ecrt_slave_config_reg_pdo_entry() and ecrt_slave_config_sdo*(). fp@1512: * - Implemented the Vendor-specific over EtherCAT mailbox protocol. See fp@1341: * ecrt_slave_config_create_voe_handler(). fp@1509: * - Renamed ec_sdo_request_state_t to #ec_request_state_t, because it is also fp@1341: * used by VoE handlers. fp@1352: * - Removed 'const' from argument of ecrt_sdo_request_state(), because the fp@1352: * userspace library has to modify object internals. fp@1384: * - Added 64-bit data access macros. fp@1913: * - Added ecrt_slave_config_idn() method for storing SoE IDN configurations, fp@1913: * and ecrt_master_read_idn() and ecrt_master_write_idn() to read/write IDNs fp@1913: * ad-hoc via the user-space library. fp@2009: * - Added ecrt_master_reset() to initiate retrying to configure slaves. fp@1239: * fp@792: * @{ fp@786: */ fp@199: fp@199: /*****************************************************************************/ fp@199: fp@125: #ifndef __ECRT_H__ fp@125: #define __ECRT_H__ fp@104: fp@1254: #ifdef __KERNEL__ fp@104: #include fp@110: #include fp@1396: #include fp@110: #else fp@1254: #include // for size_t fp@110: #include fp@1396: #include // for struct timeval fp@110: #endif fp@110: fp@779: /****************************************************************************** fp@779: * Global definitions fp@779: *****************************************************************************/ fp@779: fp@864: /** EtherCAT realtime interface major version number. fp@758: */ fp@637: #define ECRT_VER_MAJOR 1 fp@758: fp@864: /** EtherCAT realtime interface minor version number. fp@779: */ fp@1209: #define ECRT_VER_MINOR 5 fp@779: fp@864: /** EtherCAT realtime interface version word generator. fp@779: */ fp@779: #define ECRT_VERSION(a, b) (((a) << 8) + (b)) fp@779: fp@864: /** EtherCAT realtime interface version word. fp@758: */ fp@541: #define ECRT_VERSION_MAGIC ECRT_VERSION(ECRT_VER_MAJOR, ECRT_VER_MINOR) fp@541: fp@2381: /****************************************************************************** fp@2381: * Feature flags fp@2381: *****************************************************************************/ fp@2381: fp@2381: /** Defined, if the redundancy features are available. fp@2381: * fp@2381: * I. e. if the \a redundancy_active flag in ec_domain_state_t and the fp@2381: * ecrt_master_link_state() method are available. fp@2381: */ fp@2381: #define EC_HAVE_REDUNDANCY fp@2381: fp@2438: /** Defined, if the CoE emergency ring feature is available. fp@2438: * fp@2438: * I. e. if the ecrt_slave_config_emerg_*() methods are available. fp@2438: */ fp@2438: #define EC_HAVE_EMERGENCY fp@2438: fp@2445: /** Defined, if the register access interface is available. fp@2445: * fp@2445: * I. e. if the methods ecrt_slave_config_create_reg_request(), fp@2445: * ecrt_reg_request_data(), ecrt_reg_request_state(), ecrt_reg_request_write() fp@2445: * and ecrt_reg_request_read() are available. fp@2445: */ fp@2445: #define EC_HAVE_REG_ACCESS fp@2445: fp@2522: /** Defined if the method ecrt_master_select_reference_clock() is available. fp@2447: */ fp@2447: #define EC_HAVE_SELECT_REF_CLOCK fp@2447: fp@2522: /** Defined if the method ecrt_master_reference_clock_time() is available. fp@2447: */ fp@2447: #define EC_HAVE_REF_CLOCK_TIME fp@2447: fp@2522: /** Defined if the method ecrt_slave_config_reg_pdo_entry_pos() is available. fp@2505: */ fp@2505: #define EC_HAVE_REG_BY_POS fp@2505: fp@878: /*****************************************************************************/ fp@878: fp@1082: /** End of list marker. fp@1082: * fp@1082: * This can be used with ecrt_slave_config_pdos(). fp@879: */ fp@879: #define EC_END ~0U fp@878: fp@1082: /** Maximum number of sync managers per slave. fp@1082: */ fp@1082: #define EC_MAX_SYNC_MANAGERS 16 fp@1082: fp@1341: /** Maximum string length. fp@1341: * fp@1341: * Used in ec_slave_info_t. fp@1341: */ fp@1341: #define EC_MAX_STRING_LENGTH 64 fp@1341: ch1010858@2241: /** Maximum number of slave ports. */ ch1010858@2241: #define EC_MAX_PORTS 4 ch1010858@2241: fp@1417: /** Timeval to nanoseconds conversion. fp@1417: * fp@1512: * This macro converts a Unix epoch time to EtherCAT DC time. fp@1417: * fp@1466: * \see void ecrt_master_application_time() fp@1466: * fp@1466: * \param TV struct timeval containing epoch time. fp@1417: */ fp@1417: #define EC_TIMEVAL2NANO(TV) \ fp@1466: (((TV).tv_sec - 946684800ULL) * 1000000000ULL + (TV).tv_usec * 1000ULL) fp@1417: fp@2438: /** Size of a CoE emergency message in byte. fp@2438: * fp@2438: * \see ecrt_slave_config_emerg_pop(). fp@2438: */ fp@2438: #define EC_COE_EMERGENCY_MSG_SIZE 8 fp@2438: fp@779: /****************************************************************************** ch1010858@2241: * Data types fp@779: *****************************************************************************/ fp@541: fp@104: struct ec_master; fp@286: typedef struct ec_master ec_master_t; /**< \see ec_master */ fp@104: fp@792: struct ec_slave_config; fp@792: typedef struct ec_slave_config ec_slave_config_t; /**< \see ec_slave_config */ fp@792: fp@104: struct ec_domain; fp@286: typedef struct ec_domain ec_domain_t; /**< \see ec_domain */ fp@104: fp@858: struct ec_sdo_request; fp@858: typedef struct ec_sdo_request ec_sdo_request_t; /**< \see ec_sdo_request. */ fp@858: fp@1209: struct ec_voe_handler; fp@1209: typedef struct ec_voe_handler ec_voe_handler_t; /**< \see ec_voe_handler. */ fp@1209: fp@2443: struct ec_reg_request; fp@2443: typedef struct ec_reg_request ec_reg_request_t; /**< \see ec_sdo_request. */ fp@2443: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Master state. fp@792: * fp@792: * This is used for the output parameter of ecrt_master_state(). fp@1020: * fp@1020: * \see ecrt_master_state(). fp@612: */ fp@612: typedef struct { fp@2373: unsigned int slaves_responding; /**< Sum of responding slaves on all fp@2373: Ethernet devices. */ fp@1022: unsigned int al_states : 4; /**< Application-layer states of all slaves. fp@1022: The states are coded in the lower 4 bits. fp@1022: If a bit is set, it means that at least one fp@1022: slave in the bus is in the corresponding fp@1022: state: fp@1022: - Bit 0: \a INIT fp@1022: - Bit 1: \a PREOP fp@1022: - Bit 2: \a SAFEOP fp@1022: - Bit 3: \a OP */ fp@2373: unsigned int link_up : 1; /**< \a true, if at least one Ethernet link is fp@2373: up. */ fp@792: } ec_master_state_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@2380: /** Redundant link state. fp@2380: * fp@2380: * This is used for the output parameter of ecrt_master_link_state(). fp@2380: * fp@2380: * \see ecrt_master_link_state(). fp@2380: */ fp@2380: typedef struct { fp@2380: unsigned int slaves_responding; /**< Sum of responding slaves on the given fp@2380: link. */ fp@2380: unsigned int al_states : 4; /**< Application-layer states of the slaves on fp@2380: the given link. The states are coded in the fp@2380: lower 4 bits. If a bit is set, it means fp@2380: that at least one slave in the bus is in the fp@2380: corresponding state: fp@2380: - Bit 0: \a INIT fp@2380: - Bit 1: \a PREOP fp@2380: - Bit 2: \a SAFEOP fp@2380: - Bit 3: \a OP */ fp@2380: unsigned int link_up : 1; /**< \a true, if the given Ethernet link is up. fp@2380: */ fp@2380: } ec_master_link_state_t; fp@2380: fp@2380: /*****************************************************************************/ fp@2380: fp@792: /** Slave configuration state. fp@792: * fp@1020: * This is used as an output parameter of ecrt_slave_config_state(). ch1010858@2241: * fp@792: * \see ecrt_slave_config_state(). fp@792: */ fp@792: typedef struct { fp@792: unsigned int online : 1; /**< The slave is online. */ fp@1020: unsigned int operational : 1; /**< The slave was brought into \a OP state fp@1020: using the specified configuration. */ fp@1022: unsigned int al_state : 4; /**< The application-layer state of the slave. fp@1022: - 1: \a INIT fp@1022: - 2: \a PREOP fp@1022: - 4: \a SAFEOP fp@1022: - 8: \a OP fp@1022: fp@1022: Note that each state is coded in a different fp@1022: bit! */ fp@792: } ec_slave_config_state_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@1497: /** Master information. fp@1497: * fp@1497: * This is used as an output parameter of ecrt_master(). fp@1497: * fp@1497: * \see ecrt_master(). fp@1497: */ fp@1497: typedef struct { fp@1497: unsigned int slave_count; /**< Number of slaves in the bus. */ fp@1497: unsigned int link_up : 1; /**< \a true, if the network link is up. */ ch1010858@2241: uint8_t scan_busy; /**< \a true, while the master is scanning the bus */ fp@1497: uint64_t app_time; /**< Application time. */ fp@1497: } ec_master_info_t; fp@1497: fp@1497: /*****************************************************************************/ fp@1497: ch1010858@2241: /** EtherCAT slave port descriptor. ch1010858@2241: */ ch1010858@2241: typedef enum { ch1010858@2241: EC_PORT_NOT_IMPLEMENTED, /**< Port is not implemented. */ ch1010858@2241: EC_PORT_NOT_CONFIGURED, /**< Port is not configured. */ fp@2444: EC_PORT_EBUS, /**< Port is an E-Bus. */ fp@2444: EC_PORT_MII /**< Port is a MII. */ ch1010858@2241: } ec_slave_port_desc_t; ch1010858@2241: ch1010858@2241: /*****************************************************************************/ ch1010858@2241: ch1010858@2241: /** EtherCAT slave port information. ch1010858@2241: */ ch1010858@2241: typedef struct { ch1010858@2241: uint8_t link_up; /**< Link detected. */ ch1010858@2241: uint8_t loop_closed; /**< Loop closed. */ ch1010858@2241: uint8_t signal_detected; /**< Detected signal on RX port. */ ch1010858@2241: } ec_slave_port_link_t; ch1010858@2241: ch1010858@2241: /*****************************************************************************/ ch1010858@2241: fp@1341: /** Slave information. fp@1341: * fp@1510: * This is used as an output parameter of ecrt_master_get_slave(). fp@1510: * fp@1510: * \see ecrt_master_get_slave(). fp@1341: */ fp@1341: typedef struct { fp@1341: uint16_t position; /**< Offset of the slave in the ring. */ fp@1341: uint32_t vendor_id; /**< Vendor-ID stored on the slave. */ fp@1341: uint32_t product_code; /**< Product-Code stored on the slave. */ fp@1341: uint32_t revision_number; /**< Revision-Number stored on the slave. */ fp@1341: uint32_t serial_number; /**< Serial-Number stored on the slave. */ fp@1341: uint16_t alias; /**< The slaves alias if not equal to 0. */ fp@1466: int16_t current_on_ebus; /**< Used current in mA. */ ch1010858@2241: struct { fp@2243: ec_slave_port_desc_t desc; /**< Physical port type. */ fp@2243: ec_slave_port_link_t link; /**< Port link state. */ fp@2243: uint32_t receive_time; /**< Receive time on DC transmission delay fp@2243: measurement. */ fp@2243: uint16_t next_slave; /**< Ring position of next DC slave on that fp@2243: port. */ fp@2243: uint32_t delay_to_next_dc; /**< Delay [ns] to next DC slave. */ fp@2243: } ports[EC_MAX_PORTS]; /**< Port information. */ fp@1341: uint8_t al_state; /**< Current state of the slave. */ fp@1341: uint8_t error_flag; /**< Error flag for that slave. */ fp@1341: uint8_t sync_count; /**< Number of sync managers. */ fp@1512: uint16_t sdo_count; /**< Number of SDOs. */ fp@1341: char name[EC_MAX_STRING_LENGTH]; /**< Name of the slave. */ fp@1341: } ec_slave_info_t; fp@1341: fp@1341: /*****************************************************************************/ fp@1341: fp@792: /** Domain working counter interpretation. fp@792: * fp@792: * This is used in ec_domain_state_t. fp@792: */ fp@792: typedef enum { fp@925: EC_WC_ZERO = 0, /**< No registered process data were exchanged. */ fp@925: EC_WC_INCOMPLETE, /**< Some of the registered process data were fp@925: exchanged. */ fp@925: EC_WC_COMPLETE /**< All registered process data were exchanged. */ fp@792: } ec_wc_state_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Domain state. fp@792: * fp@792: * This is used for the output parameter of ecrt_domain_state(). fp@640: */ fp@640: typedef struct { fp@792: unsigned int working_counter; /**< Value of the last working counter. */ fp@792: ec_wc_state_t wc_state; /**< Working counter interpretation. */ fp@2368: unsigned int redundancy_active; /**< Redundant link is in use. */ fp@792: } ec_domain_state_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@1327: /** Direction type for PDO assignment functions. fp@779: */ fp@635: typedef enum { fp@1055: EC_DIR_INVALID, /**< Invalid direction. Do not use this value. */ fp@792: EC_DIR_OUTPUT, /**< Values written by the master. */ fp@1055: EC_DIR_INPUT, /**< Values read by the master. */ fp@1055: EC_DIR_COUNT /**< Number of directions. For internal use only. */ fp@792: } ec_direction_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@1509: /** Watchdog mode for sync manager configuration. fp@1509: * fp@1509: * Used to specify, if a sync manager's watchdog is to be enabled. fp@1509: */ fp@1509: typedef enum { fp@1509: EC_WD_DEFAULT, /**< Use the default setting of the sync manager. */ fp@1509: EC_WD_ENABLE, /**< Enable the watchdog. */ fp@1509: EC_WD_DISABLE, /**< Disable the watchdog. */ fp@1509: } ec_watchdog_mode_t; fp@1509: fp@1509: /*****************************************************************************/ fp@1509: fp@1327: /** PDO entry configuration information. fp@1055: * fp@1055: * This is the data type of the \a entries field in ec_pdo_info_t. fp@1055: * fp@1082: * \see ecrt_slave_config_pdos(). fp@792: */ fp@792: typedef struct { fp@1327: uint16_t index; /**< PDO entry index. */ fp@1327: uint8_t subindex; /**< PDO entry subindex. */ fp@1327: uint8_t bit_length; /**< Size of the PDO entry in bit. */ fp@792: } ec_pdo_entry_info_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@1327: /** PDO configuration information. ch1010858@2241: * fp@1055: * This is the data type of the \a pdos field in ec_sync_info_t. ch1010858@2241: * fp@1082: * \see ecrt_slave_config_pdos(). fp@792: */ fp@792: typedef struct { fp@1327: uint16_t index; /**< PDO index. */ fp@1327: unsigned int n_entries; /**< Number of PDO entries in \a entries to map. fp@879: Zero means, that the default mapping shall be fp@925: used (this can only be done if the slave is fp@925: present at bus configuration time). */ fp@1327: ec_pdo_entry_info_t *entries; /**< Array of PDO entries to map. Can either fp@1055: be \a NULL, or must contain at fp@1055: least \a n_entries values. */ fp@792: } ec_pdo_info_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@1055: /** Sync manager configuration information. fp@1055: * fp@1327: * This can be use to configure multiple sync managers including the PDO fp@1327: * assignment and PDO mapping. It is used as an input parameter type in fp@1082: * ecrt_slave_config_pdos(). fp@1055: */ fp@1055: typedef struct { fp@1083: uint8_t index; /**< Sync manager index. Must be less fp@1083: than #EC_MAX_SYNC_MANAGERS for a valid sync manager, fp@1083: but can also be \a 0xff to mark the end of the list. */ fp@1055: ec_direction_t dir; /**< Sync manager direction. */ fp@1327: unsigned int n_pdos; /**< Number of PDOs in \a pdos. */ fp@1327: ec_pdo_info_t *pdos; /**< Array with PDOs to assign. This must contain fp@1327: at least \a n_pdos PDOs. */ fp@1509: ec_watchdog_mode_t watchdog_mode; /**< Watchdog mode. */ fp@1055: } ec_sync_info_t; fp@1055: fp@1055: /*****************************************************************************/ fp@1055: fp@1327: /** List record type for PDO entry mass-registration. fp@792: * fp@792: * This type is used for the array parameter of the ha@923: * ecrt_domain_reg_pdo_entry_list() fp@792: */ fp@792: typedef struct { fp@792: uint16_t alias; /**< Slave alias address. */ fp@792: uint16_t position; /**< Slave position. */ fp@792: uint32_t vendor_id; /**< Slave vendor ID. */ fp@792: uint32_t product_code; /**< Slave product code. */ fp@1327: uint16_t index; /**< PDO entry index. */ fp@1327: uint8_t subindex; /**< PDO entry subindex. */ fp@1327: unsigned int *offset; /**< Pointer to a variable to store the PDO entry's fp@925: (byte-)offset in the process data. */ ch1010858@2241: unsigned int *bit_position; /**< Pointer to a variable to store a bit fp@1092: position (0-7) within the \a offset. Can be fp@1092: NULL, in which case an error is raised if the fp@1327: PDO entry does not byte-align. */ fp@792: } ec_pdo_entry_reg_t; fp@416: fp@858: /*****************************************************************************/ fp@858: fp@1209: /** Request state. fp@1209: * fp@1209: * This is used as return type for ecrt_sdo_request_state() and fp@1209: * ecrt_voe_handler_state(). fp@858: */ fp@858: typedef enum { fp@1209: EC_REQUEST_UNUSED, /**< Not requested. */ fp@1209: EC_REQUEST_BUSY, /**< Request is being processed. */ fp@1209: EC_REQUEST_SUCCESS, /**< Request was processed successfully. */ fp@1209: EC_REQUEST_ERROR, /**< Request processing failed. */ fp@1209: } ec_request_state_t; fp@858: fp@1944: /*****************************************************************************/ fp@1944: fp@1944: /** Application-layer state. fp@1944: */ fp@1944: typedef enum { fp@1944: EC_AL_STATE_INIT = 1, /**< Init. */ fp@1944: EC_AL_STATE_PREOP = 2, /**< Pre-operational. */ fp@1944: EC_AL_STATE_SAFEOP = 4, /**< Safe-operational. */ fp@1944: EC_AL_STATE_OP = 8, /**< Operational. */ fp@1944: } ec_al_state_t; fp@1944: fp@199: /****************************************************************************** fp@779: * Global functions fp@199: *****************************************************************************/ fp@104: fp@1288: #ifdef __cplusplus fp@1288: extern "C" { fp@1288: #endif fp@1288: fp@792: /** Returns the version magic of the realtime interface. fp@792: * fp@792: * \return Value of ECRT_VERSION_MAGIC() at EtherCAT master compile time. fp@792: */ fp@541: unsigned int ecrt_version_magic(void); fp@541: fp@792: /** Requests an EtherCAT master for realtime operation. ch1010858@2241: * fp@1092: * Before an application can access an EtherCAT master, it has to reserve one fp@1092: * for exclusive use. fp@1092: * fp@1497: * In userspace, this is a convenience function for ecrt_open_master() and fp@1497: * ecrt_master_reserve(). fp@1497: * fp@1092: * This function has to be the first function an application has to call to fp@1092: * use EtherCAT. The function takes the index of the master as its argument. fp@1092: * The first master has index 0, the n-th master has index n - 1. The number fp@1092: * of masters has to be specified when loading the master module. fp@1092: * fp@1312: * \return Pointer to the reserved master, otherwise \a NULL. fp@792: */ fp@792: ec_master_t *ecrt_request_master( fp@792: unsigned int master_index /**< Index of the master to request. */ fp@792: ); fp@792: fp@1497: #ifndef __KERNEL__ fp@1497: fp@1497: /** Opens an EtherCAT master for userspace access. fp@1497: * fp@1497: * This function has to be the first function an application has to call to fp@1497: * use EtherCAT. The function takes the index of the master as its argument. fp@1497: * The first master has index 0, the n-th master has index n - 1. The number fp@1497: * of masters has to be specified when loading the master module. fp@1497: * fp@1497: * For convenience, the function ecrt_request_master() can be used. fp@1497: * fp@1497: * \return Pointer to the opened master, otherwise \a NULL. fp@1497: */ fp@1497: ec_master_t *ecrt_open_master( fp@1804: unsigned int master_index /**< Index of the master to request. */ fp@1804: ); fp@1497: fp@1497: #endif // #ifndef __KERNEL__ fp@1497: fp@792: /** Releases a requested EtherCAT master. fp@1092: * fp@1092: * After use, a master it has to be released to make it available for other fp@1092: * applications. fp@2523: * fp@2523: * This method frees all created data structures. It should not be called in fp@2523: * realtime context. fp@2523: * fp@2523: * If the master was activated, ecrt_master_deactivate() is called internally. fp@792: */ fp@792: void ecrt_release_master( fp@792: ec_master_t *master /**< EtherCAT master */ fp@792: ); fp@792: fp@199: /****************************************************************************** fp@779: * Master methods fp@199: *****************************************************************************/ fp@104: fp@1497: #ifndef __KERNEL__ fp@1497: fp@1497: /** Reserves an EtherCAT master for realtime operation. fp@1497: * fp@1497: * Before an application can use PDO/domain registration functions or SDO fp@1497: * request functions on the master, it has to reserve one for exclusive use. fp@1497: * fp@1497: * \return 0 in case of success, else < 0 fp@1497: */ fp@1497: int ecrt_master_reserve( fp@1804: ec_master_t *master /**< EtherCAT master */ fp@1804: ); fp@1497: fp@1497: #endif // #ifndef __KERNEL__ fp@1497: fp@1244: #ifdef __KERNEL__ fp@1244: fp@792: /** Sets the locking callbacks. fp@792: * fp@1500: * For concurrent master access, i. e. if other instances than the application fp@1500: * want to send and receive datagrams on the bus, the application has to fp@1500: * provide a callback mechanism. This method takes two function pointers as fp@1500: * its parameters. Asynchronous master access (like EoE processing) is only fp@1500: * possible if the callbacks have been set. fp@1500: * fp@1512: * The task of the send callback (\a send_cb) is to decide, if the bus is fp@1512: * currently accessible and whether or not to call the ecrt_master_send_ext() fp@1500: * method. fp@1500: * fp@1500: * The task of the receive callback (\a receive_cb) is to decide, if a call to fp@1500: * ecrt_master_receive() is allowed and to execute it respectively. fp@2523: * fp@2523: * \attention This method has to be called before ecrt_master_activate(). fp@792: */ fp@792: void ecrt_master_callbacks( fp@792: ec_master_t *master, /**< EtherCAT master */ fp@1513: void (*send_cb)(void *), /**< Datagram sending callback. */ fp@1513: void (*receive_cb)(void *), /**< Receive callback. */ fp@2444: void *cb_data /**< Arbitrary pointer passed to the callback functions. fp@1513: */ fp@792: ); fp@792: fp@1244: #endif /* __KERNEL__ */ fp@1244: fp@1092: /** Creates a new process data domain. fp@1092: * fp@1092: * For process data exchange, at least one process data domain is needed. fp@1092: * This method creates a new process data domain and returns a pointer to the fp@1327: * new domain object. This object can be used for registering PDOs and fp@1092: * exchanging them in cyclic operation. fp@792: * fp@2523: * This method allocates memory and should be called in non-realtime context fp@2523: * before ecrt_master_activate(). fp@2523: * fp@792: * \return Pointer to the new domain on success, else NULL. fp@792: */ fp@792: ec_domain_t *ecrt_master_create_domain( fp@792: ec_master_t *master /**< EtherCAT master. */ fp@792: ); fp@792: fp@792: /** Obtains a slave configuration. fp@792: * fp@792: * Creates a slave configuration object for the given \a alias and \a position fp@792: * tuple and returns it. If a configuration with the same \a alias and \a fp@792: * position already exists, it will be re-used. In the latter case, the given fp@792: * vendor ID and product code are compared to the stored ones. On mismatch, an fp@792: * error message is raised and the function returns \a NULL. fp@792: * fp@792: * Slaves are addressed with the \a alias and \a position parameters. fp@792: * - If \a alias is zero, \a position is interpreted as the desired slave's fp@792: * ring position. fp@792: * - If \a alias is non-zero, it matches a slave with the given alias. In this fp@792: * case, \a position is interpreted as ring offset, starting from the fp@792: * aliased slave, so a position of zero means the aliased slave itself and a fp@792: * positive value matches the n-th slave behind the aliased one. fp@792: * fp@792: * If the slave with the given address is found during the bus configuration, fp@792: * its vendor ID and product code are matched against the given value. On fp@792: * mismatch, the slave is not configured and an error message is raised. fp@792: * fp@792: * If different slave configurations are pointing to the same slave during bus fp@792: * configuration, a warning is raised and only the first configuration is fp@792: * applied. fp@792: * fp@2523: * This method allocates memory and should be called in non-realtime context fp@2523: * before ecrt_master_activate(). fp@2523: * fp@792: * \retval >0 Pointer to the slave configuration structure. fp@792: * \retval NULL in the error case. fp@792: */ fp@792: ec_slave_config_t *ecrt_master_slave_config( fp@792: ec_master_t *master, /**< EtherCAT master */ fp@792: uint16_t alias, /**< Slave alias. */ fp@792: uint16_t position, /**< Slave position. */ fp@792: uint32_t vendor_id, /**< Expected vendor ID. */ fp@1010: uint32_t product_code /**< Expected product code. */ fp@792: ); fp@792: fp@2447: /** Selects the reference clock for distributed clocks. fp@2447: * fp@2447: * If this method is not called for a certain master, or if the slave fp@2447: * configuration pointer is NULL, then the first slave with DC functionality fp@2447: * will provide the reference clock. fp@2447: * fp@2447: * \return 0 on success, otherwise negative error code. fp@2447: */ fp@2447: int ecrt_master_select_reference_clock( fp@2447: ec_master_t *master, /**< EtherCAT master. */ fp@2447: ec_slave_config_t *sc /**< Slave config of the slave to use as the fp@2447: * reference slave (or NULL). */ fp@2447: ); fp@2447: fp@1497: /** Obtains master information. fp@1497: * fp@1497: * No memory is allocated on the heap in fp@1497: * this function. fp@1497: * fp@1497: * \attention The pointer to this structure must point to a valid variable. fp@1497: * fp@1497: * \return 0 in case of success, else < 0 fp@1497: */ fp@1497: int ecrt_master( fp@1804: ec_master_t *master, /**< EtherCAT master */ fp@1804: ec_master_info_t *master_info /**< Structure that will output the fp@1804: information */ fp@1804: ); fp@1497: fp@1341: /** Obtains slave information. fp@1341: * fp@1341: * Tries to find the slave with the given ring position. The obtained fp@1341: * information is stored in a structure. No memory is allocated on the heap in fp@1341: * this function. fp@1341: * fp@1341: * \attention The pointer to this structure must point to a valid variable. fp@1341: * fp@1341: * \return 0 in case of success, else < 0 fp@1341: */ fp@1510: int ecrt_master_get_slave( fp@1341: ec_master_t *master, /**< EtherCAT master */ fp@1510: uint16_t slave_position, /**< Slave position. */ fp@1341: ec_slave_info_t *slave_info /**< Structure that will output the fp@1341: information */ fp@1341: ); fp@1341: fp@1594: #ifndef __KERNEL__ fp@1594: fp@1510: /** Returns the proposed configuration of a slave's sync manager. fp@1510: * fp@1510: * Fills a given ec_sync_info_t structure with the attributes of a sync fp@1510: * manager. The \a pdos field of the return value is left empty. Use fp@1510: * ecrt_master_get_pdo() to get the PDO information. fp@1510: * fp@1510: * \return zero on success, else non-zero fp@1510: */ fp@1510: int ecrt_master_get_sync_manager( fp@1510: ec_master_t *master, /**< EtherCAT master. */ fp@1510: uint16_t slave_position, /**< Slave position. */ fp@1510: uint8_t sync_index, /**< Sync manager index. Must be less fp@1510: than #EC_MAX_SYNC_MANAGERS. */ fp@1510: ec_sync_info_t *sync /**< Pointer to output structure. */ fp@1510: ); fp@1510: fp@1510: /** Returns information about a currently assigned PDO. fp@1510: * fp@1510: * Fills a given ec_pdo_info_t structure with the attributes of a currently fp@1510: * assigned PDO of the given sync manager. The \a entries field of the return fp@1510: * value is left empty. Use ecrt_master_get_pdo_entry() to get the PDO fp@1510: * entry information. fp@1510: * fp@1510: * \retval zero on success, else non-zero fp@1510: */ fp@1510: int ecrt_master_get_pdo( fp@1510: ec_master_t *master, /**< EtherCAT master. */ fp@1510: uint16_t slave_position, /**< Slave position. */ fp@1510: uint8_t sync_index, /**< Sync manager index. Must be less fp@1510: than #EC_MAX_SYNC_MANAGERS. */ fp@1510: uint16_t pos, /**< Zero-based PDO position. */ fp@1510: ec_pdo_info_t *pdo /**< Pointer to output structure. */ fp@1510: ); fp@1510: fp@1510: /** Returns information about a currently mapped PDO entry. fp@1510: * fp@1510: * Fills a given ec_pdo_entry_info_t structure with the attributes of a fp@1510: * currently mapped PDO entry of the given PDO. fp@1510: * fp@1510: * \retval zero on success, else non-zero fp@1510: */ fp@1510: int ecrt_master_get_pdo_entry( fp@1510: ec_master_t *master, /**< EtherCAT master. */ fp@1510: uint16_t slave_position, /**< Slave position. */ fp@1510: uint8_t sync_index, /**< Sync manager index. Must be less fp@1510: than #EC_MAX_SYNC_MANAGERS. */ fp@1510: uint16_t pdo_pos, /**< Zero-based PDO position. */ fp@1510: uint16_t entry_pos, /**< Zero-based PDO entry position. */ fp@1510: ec_pdo_entry_info_t *entry /**< Pointer to output structure. */ fp@1510: ); fp@1510: fp@2109: #endif /* #ifndef __KERNEL__ */ fp@2109: fp@2109: /** Executes an SDO download request to write data to a slave. fp@2109: * fp@2109: * This request is processed by the master state machine. This method blocks, fp@2109: * until the request has been processed and may not be called in realtime fp@2109: * context. fp@1510: * fp@1510: * \retval 0 Success. fp@2109: * \retval <0 Error code. fp@1510: */ fp@1510: int ecrt_master_sdo_download( fp@1510: ec_master_t *master, /**< EtherCAT master. */ fp@1510: uint16_t slave_position, /**< Slave position. */ fp@1510: uint16_t index, /**< Index of the SDO. */ fp@1510: uint8_t subindex, /**< Subindex of the SDO. */ fp@1510: uint8_t *data, /**< Data buffer to download. */ fp@1510: size_t data_size, /**< Size of the data buffer. */ fp@1510: uint32_t *abort_code /**< Abort code of the SDO download. */ fp@1510: ); fp@1510: fp@2124: /** Executes an SDO download request to write data to a slave via complete fp@2124: * access. fp@2124: * fp@2124: * This request is processed by the master state machine. This method blocks, fp@2124: * until the request has been processed and may not be called in realtime fp@2124: * context. fp@2124: * fp@2124: * \retval 0 Success. fp@2124: * \retval <0 Error code. fp@2124: */ fp@2124: int ecrt_master_sdo_download_complete( fp@2124: ec_master_t *master, /**< EtherCAT master. */ fp@2124: uint16_t slave_position, /**< Slave position. */ fp@2124: uint16_t index, /**< Index of the SDO. */ fp@2124: uint8_t *data, /**< Data buffer to download. */ fp@2124: size_t data_size, /**< Size of the data buffer. */ fp@2124: uint32_t *abort_code /**< Abort code of the SDO download. */ fp@2124: ); fp@2124: fp@2109: /** Executes an SDO upload request to read data from a slave. fp@2109: * fp@2109: * This request is processed by the master state machine. This method blocks, fp@2109: * until the request has been processed and may not be called in realtime fp@2109: * context. fp@1510: * fp@1510: * \retval 0 Success. fp@2109: * \retval <0 Error code. fp@1510: */ fp@1510: int ecrt_master_sdo_upload( fp@1510: ec_master_t *master, /**< EtherCAT master. */ fp@1510: uint16_t slave_position, /**< Slave position. */ fp@1510: uint16_t index, /**< Index of the SDO. */ fp@1510: uint8_t subindex, /**< Subindex of the SDO. */ fp@1510: uint8_t *target, /**< Target buffer for the upload. */ fp@1510: size_t target_size, /**< Size of the target buffer. */ fp@1510: size_t *result_size, /**< Uploaded data size. */ fp@1510: uint32_t *abort_code /**< Abort code of the SDO upload. */ fp@1510: ); fp@1510: fp@1913: /** Executes an SoE write request. fp@1913: * fp@1913: * Starts writing an IDN and blocks until the request was processed, or an fp@1913: * error occurred. fp@1913: * fp@1913: * \retval 0 Success. fp@2433: * \retval <0 Error code. fp@1913: */ fp@1913: int ecrt_master_write_idn( fp@1913: ec_master_t *master, /**< EtherCAT master. */ fp@1913: uint16_t slave_position, /**< Slave position. */ fp@1952: uint8_t drive_no, /**< Drive number. */ fp@1913: uint16_t idn, /**< SoE IDN (see ecrt_slave_config_idn()). */ fp@1913: uint8_t *data, /**< Pointer to data to write. */ fp@1913: size_t data_size, /**< Size of data to write. */ fp@1947: uint16_t *error_code /**< Pointer to variable, where an SoE error code fp@1913: can be stored. */ fp@1913: ); fp@1913: fp@1913: /** Executes an SoE read request. fp@1913: * fp@1913: * Starts reading an IDN and blocks until the request was processed, or an fp@1913: * error occurred. fp@1913: * fp@1913: * \retval 0 Success. fp@2433: * \retval <0 Error code. fp@1913: */ fp@1913: int ecrt_master_read_idn( fp@1913: ec_master_t *master, /**< EtherCAT master. */ fp@1913: uint16_t slave_position, /**< Slave position. */ fp@1952: uint8_t drive_no, /**< Drive number. */ fp@1913: uint16_t idn, /**< SoE IDN (see ecrt_slave_config_idn()). */ fp@1913: uint8_t *target, /**< Pointer to memory where the read data can be fp@1913: stored. */ fp@1913: size_t target_size, /**< Size of the memory \a target points to. */ fp@1913: size_t *result_size, /**< Actual size of the received data. */ fp@1947: uint16_t *error_code /**< Pointer to variable, where an SoE error code fp@1913: can be stored. */ fp@1913: ); fp@1913: fp@1096: /** Finishes the configuration phase and prepares for cyclic operation. fp@879: * fp@925: * This function tells the master that the configuration phase is finished and fp@925: * the realtime operation will begin. The function allocates internal memory fp@925: * for the domains and calculates the logical FMMU addresses for domain fp@925: * members. It tells the master state machine that the bus configuration is fp@925: * now to be applied. fp@879: * fp@879: * \attention After this function has been called, the realtime application is fp@879: * in charge of cyclically calling ecrt_master_send() and fp@879: * ecrt_master_receive() to ensure bus communication. Before calling this fp@879: * function, the master thread is responsible for that, so these functions may fp@2523: * not be called! The method itself allocates memory and should not be called fp@2523: * in realtime context. fp@792: * fp@792: * \return 0 in case of success, else < 0 fp@792: */ fp@1007: int ecrt_master_activate( fp@1007: ec_master_t *master /**< EtherCAT master. */ fp@1007: ); fp@792: fp@1530: /** Deactivates the master. fp@1530: * fp@1530: * Removes the bus configuration. All objects created by fp@1530: * ecrt_master_create_domain(), ecrt_master_slave_config(), ecrt_domain_data() fp@1530: * ecrt_slave_config_create_sdo_request() and fp@1530: * ecrt_slave_config_create_voe_handler() are freed, so pointers to them fp@1530: * become invalid. fp@2523: * fp@2523: * This method should not be called in realtime context. fp@1530: */ fp@1530: void ecrt_master_deactivate( fp@1530: ec_master_t *master /**< EtherCAT master. */ fp@1530: ); fp@1530: fp@2423: /** Set interval between calls to ecrt_master_send(). fp@2433: * fp@2523: * This information helps the master to decide, how much data can be appended fp@2523: * to a frame by the master state machine. When the master is configured with fp@2523: * --enable-hrtimers, this is used to calculate the scheduling of the master fp@2523: * thread. fp@2523: * fp@2433: * \retval 0 on success. fp@2433: * \retval <0 Error code. martin@1600: */ martin@1600: int ecrt_master_set_send_interval( martin@1585: ec_master_t *master, /**< EtherCAT master. */ fp@1804: size_t send_interval /**< Send interval in us */ martin@1585: ); martin@1585: fp@792: /** Sends all datagrams in the queue. fp@792: * fp@1092: * This method takes all datagrams, that have been queued for transmission, fp@1092: * puts them into frames, and passes them to the Ethernet device for sending. fp@1092: * fp@1092: * Has to be called cyclically by the application after ecrt_master_activate() fp@1092: * has returned. fp@792: */ fp@792: void ecrt_master_send( fp@792: ec_master_t *master /**< EtherCAT master. */ fp@792: ); fp@792: fp@792: /** Fetches received frames from the hardware and processes the datagrams. fp@879: * fp@1092: * Queries the network device for received frames by calling the interrupt fp@1092: * service routine. Extracts received datagrams and dispatches the results to fp@1092: * the datagram objects in the queue. Received datagrams, and the ones that fp@1092: * timed out, will be marked, and dequeued. fp@1092: * fp@1092: * Has to be called cyclically by the realtime application after fp@879: * ecrt_master_activate() has returned. fp@792: */ fp@792: void ecrt_master_receive( fp@792: ec_master_t *master /**< EtherCAT master. */ fp@792: ); fp@792: fp@1500: /** Sends non-application datagrams. fp@1500: * fp@1500: * This method has to be called in the send callback function passed via fp@1500: * ecrt_master_callbacks() to allow the sending of non-application datagrams. fp@1500: */ fp@1500: void ecrt_master_send_ext( fp@1500: ec_master_t *master /**< EtherCAT master. */ fp@1500: ); fp@1500: fp@792: /** Reads the current master state. fp@792: * fp@792: * Stores the master state information in the given \a state structure. fp@2380: * fp@2380: * This method returns a global state. For the link-specific states in a fp@2380: * redundant bus topology, use the ecrt_master_link_state() method. fp@792: */ fp@792: void ecrt_master_state( fp@792: const ec_master_t *master, /**< EtherCAT master. */ fp@792: ec_master_state_t *state /**< Structure to store the information. */ fp@792: ); fp@792: fp@2380: /** Reads the current state of a redundant link. fp@2380: * fp@2380: * Stores the link state information in the given \a state structure. fp@2380: * fp@2380: * \return Zero on success, otherwise negative error code. fp@2380: */ fp@2380: int ecrt_master_link_state( fp@2380: const ec_master_t *master, /**< EtherCAT master. */ fp@2380: unsigned int dev_idx, /**< Index of the device (0 = main device, 1 = fp@2380: first backup device, ...). */ fp@2380: ec_master_link_state_t *state /**< Structure to store the information. fp@2380: */ fp@2380: ); fp@2380: fp@1434: /** Sets the application time. fp@1434: * fp@1466: * The master has to know the application's time when operating slaves with fp@1466: * distributed clocks. The time is not incremented by the master itself, so fp@1466: * this method has to be called cyclically. ch1010858@2241: * fp@2523: * \attention The first call of this method is used to calculate the phase fp@2523: * delay for the slaves' SYNC0/1 interrupts. Either the method has to be fp@2523: * called during the realtime cycle *only*, or the first time submitted must fp@2523: * be in-phase with the realtime cycle. Otherwise synchronisation problems can fp@2523: * occur. fp@2523: * fp@1466: * The time is used when setting the slaves' System Time Offset and fp@1466: * Cyclic Operation Start Time registers and when synchronizing the fp@1466: * DC reference clock to the application time via fp@1466: * ecrt_master_sync_reference_clock(). ch1010858@2241: * fp@1434: * The time is defined as nanoseconds from 2000-01-01 00:00. Converting an fp@1434: * epoch time can be done with the EC_TIMEVAL2NANO() macro. fp@1434: */ fp@1434: void ecrt_master_application_time( fp@1396: ec_master_t *master, /**< EtherCAT master. */ fp@1417: uint64_t app_time /**< Application time. */ fp@1394: ); fp@1394: fp@1434: /** Queues the DC reference clock drift compensation datagram for sending. fp@1434: * fp@1434: * The reference clock will by synchronized to the application time provided fp@1434: * by the last call off ecrt_master_application_time(). fp@1434: */ fp@1434: void ecrt_master_sync_reference_clock( fp@1434: ec_master_t *master /**< EtherCAT master. */ fp@1434: ); fp@1434: fp@1410: /** Queues the DC clock drift compensation datagram for sending. fp@1410: * fp@1410: * All slave clocks synchronized to the reference clock. fp@1410: */ fp@1410: void ecrt_master_sync_slave_clocks( fp@1410: ec_master_t *master /**< EtherCAT master. */ fp@1410: ); fp@1410: fp@2447: /** Get the lower 32 bit of the reference clock system time. fp@2447: * fp@2447: * This method can be used to synchronize the master to the reference clock. fp@2447: * fp@2447: * The reference clock system time is queried via the fp@2447: * ecrt_master_sync_slave_clocks() method, that reads the system time of the fp@2447: * reference clock and writes it to the slave clocks (so be sure to call it fp@2447: * cyclically to get valid data). fp@2447: * fp@2447: * \attention The returned time is the system time of the reference clock fp@2447: * minus the transmission delay of the reference clock. fp@2447: * fp@2447: * \retval 0 success, system time was written into \a time. fp@2447: * \retval -ENXIO No reference clock found. fp@2447: * \retval -EIO Slave synchronization datagram was not received. fp@2447: */ fp@2447: int ecrt_master_reference_clock_time( fp@2447: ec_master_t *master, /**< EtherCAT master. */ fp@2447: uint32_t *time /**< Pointer to store the queried system time. */ fp@2447: ); fp@2447: fp@2444: /** Queues the DC synchrony monitoring datagram for sending. fp@1535: * fp@1535: * The datagram broadcast-reads all "System time difference" registers (\a fp@2444: * 0x092c) to get an upper estimation of the DC synchrony. The result can be fp@1535: * checked with the ecrt_master_sync_monitor_process() method. fp@1535: */ fp@1535: void ecrt_master_sync_monitor_queue( fp@1535: ec_master_t *master /**< EtherCAT master. */ fp@1535: ); fp@1535: fp@2444: /** Processes the DC synchrony monitoring datagram. fp@1535: * fp@1535: * If the sync monitoring datagram was sent before with fp@1535: * ecrt_master_sync_monitor_queue(), the result can be queried with this fp@1535: * method. fp@1535: * fp@2444: * \return Upper estimation of the maximum time difference in ns. fp@1535: */ fp@1535: uint32_t ecrt_master_sync_monitor_process( fp@1535: ec_master_t *master /**< EtherCAT master. */ fp@1535: ); fp@1535: fp@2009: /** Retry configuring slaves. fp@2009: * fp@2009: * Via this method, the application can tell the master to bring all slaves to fp@2009: * OP state. In general, this is not necessary, because it is automatically fp@2009: * done by the master. But with special slaves, that can be reconfigured by fp@2009: * the vendor during runtime, it can be useful. fp@2009: */ fp@2009: void ecrt_master_reset( fp@2009: ec_master_t *master /**< EtherCAT master. */ fp@2009: ); fp@2009: fp@792: /****************************************************************************** fp@792: * Slave configuration methods fp@792: *****************************************************************************/ fp@792: fp@1055: /** Configure a sync manager. fp@1055: * fp@1082: * Sets the direction of a sync manager. This overrides the direction bits fp@1082: * from the default control register from SII. fp@1055: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@1055: * \return zero on success, else non-zero fp@1055: */ fp@1055: int ecrt_slave_config_sync_manager( fp@1055: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1083: uint8_t sync_index, /**< Sync manager index. Must be less fp@1082: than #EC_MAX_SYNC_MANAGERS. */ fp@1509: ec_direction_t direction, /**< Input/Output. */ fp@1509: ec_watchdog_mode_t watchdog_mode /** Watchdog mode. */ fp@1509: ); fp@1509: fp@1509: /** Configure a slave's watchdog times. fp@2523: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@1536: */ fp@1509: void ecrt_slave_config_watchdog( fp@1509: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1509: uint16_t watchdog_divider, /**< Number of 40 ns intervals. Used as a fp@1536: base unit for all slave watchdogs. If set fp@1536: to zero, the value is not written, so the fp@2444: default is used. */ fp@1509: uint16_t watchdog_intervals /**< Number of base intervals for process fp@1536: data watchdog. If set to zero, the value fp@1536: is not written, so the default is used. fp@1536: */ fp@1055: ); fp@1055: fp@1327: /** Add a PDO to a sync manager's PDO assignment. fp@879: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@1082: * \see ecrt_slave_config_pdos() fp@842: * \return zero on success, else non-zero fp@842: */ fp@879: int ecrt_slave_config_pdo_assign_add( fp@842: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1083: uint8_t sync_index, /**< Sync manager index. Must be less fp@1083: than #EC_MAX_SYNC_MANAGERS. */ fp@1327: uint16_t index /**< Index of the PDO to assign. */ fp@1327: ); fp@1327: fp@1327: /** Clear a sync manager's PDO assignment. fp@1327: * fp@1327: * This can be called before assigning PDOs via fp@1055: * ecrt_slave_config_pdo_assign_add(), to clear the default assignment of a fp@1055: * sync manager. ch1010858@2241: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@1082: * \see ecrt_slave_config_pdos() fp@879: */ fp@879: void ecrt_slave_config_pdo_assign_clear( fp@879: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1083: uint8_t sync_index /**< Sync manager index. Must be less fp@1083: than #EC_MAX_SYNC_MANAGERS. */ fp@879: ); fp@879: fp@1327: /** Add a PDO entry to the given PDO's mapping. fp@879: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@1082: * \see ecrt_slave_config_pdos() fp@842: * \return zero on success, else non-zero fp@842: */ fp@879: int ecrt_slave_config_pdo_mapping_add( fp@842: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1327: uint16_t pdo_index, /**< Index of the PDO. */ fp@1327: uint16_t entry_index, /**< Index of the PDO entry to add to the PDO's fp@879: mapping. */ fp@1327: uint8_t entry_subindex, /**< Subindex of the PDO entry to add to the fp@1327: PDO's mapping. */ fp@1327: uint8_t entry_bit_length /**< Size of the PDO entry in bit. */ fp@1327: ); fp@1327: fp@1327: /** Clear the mapping of a given PDO. fp@1327: * fp@1327: * This can be called before mapping PDO entries via fp@879: * ecrt_slave_config_pdo_mapping_add(), to clear the default mapping. fp@1055: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@1082: * \see ecrt_slave_config_pdos() fp@879: */ fp@879: void ecrt_slave_config_pdo_mapping_clear( fp@879: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1327: uint16_t pdo_index /**< Index of the PDO. */ fp@1327: ); fp@1327: fp@1327: /** Specify a complete PDO configuration. fp@879: * fp@879: * This function is a convenience wrapper for the functions fp@1055: * ecrt_slave_config_sync_manager(), ecrt_slave_config_pdo_assign_clear(), fp@1055: * ecrt_slave_config_pdo_assign_add(), ecrt_slave_config_pdo_mapping_clear() fp@1055: * and ecrt_slave_config_pdo_mapping_add(), that are better suitable for fp@1055: * automatic code generation. fp@1055: * fp@1055: * The following example shows, how to specify a complete configuration, fp@1327: * including the PDO mappings. With this information, the master is able to fp@879: * reserve the complete process data, even if the slave is not present at fp@879: * configuration time: fp@792: * fp@792: * \code fp@1082: * ec_pdo_entry_info_t el3162_channel1[] = { fp@842: * {0x3101, 1, 8}, // status fp@842: * {0x3101, 2, 16} // value fp@792: * }; ch1010858@2241: * fp@1082: * ec_pdo_entry_info_t el3162_channel2[] = { fp@842: * {0x3102, 1, 8}, // status fp@842: * {0x3102, 2, 16} // value fp@842: * }; ch1010858@2241: * fp@1082: * ec_pdo_info_t el3162_pdos[] = { fp@1055: * {0x1A00, 2, el3162_channel1}, fp@1082: * {0x1A01, 2, el3162_channel2} fp@842: * }; ch1010858@2241: * fp@1082: * ec_sync_info_t el3162_syncs[] = { fp@1082: * {2, EC_DIR_OUTPUT}, fp@1082: * {3, EC_DIR_INPUT, 2, el3162_pdos}, fp@1082: * {0xff} fp@1055: * }; ch1010858@2241: * fp@1082: * if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3162_syncs)) { fp@1082: * // handle error fp@1082: * } fp@792: * \endcode ch1010858@2241: * fp@1327: * The next example shows, how to configure the PDO assignment only. The fp@1327: * entries for each assigned PDO are taken from the PDO's default mapping. fp@1327: * Please note, that PDO entry registration will fail, if the PDO fp@879: * configuration is left empty and the slave is offline. fp@792: * fp@792: * \code fp@1082: * ec_pdo_info_t pdos[] = { fp@1055: * {0x1600}, // Channel 1 fp@1055: * {0x1601} // Channel 2 fp@792: * }; ch1010858@2241: * fp@1082: * ec_sync_info_t syncs[] = { fp@1082: * {3, EC_DIR_INPUT, 2, pdos}, fp@1055: * }; ch1010858@2241: * fp@1082: * if (ecrt_slave_config_pdos(slave_config_ana_in, 1, syncs)) { fp@1082: * // handle error fp@1082: * } fp@792: * \endcode fp@792: * fp@1055: * Processing of \a syncs will stop, if fp@1055: * - the number of processed items reaches \a n_syncs, or fp@1055: * - the \a index member of an ec_sync_info_t item is 0xff. In this case, fp@1055: * \a n_syncs should set to a number greater than the number of list items; fp@879: * using EC_END is recommended. fp@878: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@792: * \return zero on success, else non-zero fp@792: */ fp@1082: int ecrt_slave_config_pdos( fp@792: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1055: unsigned int n_syncs, /**< Number of sync manager configurations in fp@1055: \a syncs. */ fp@1055: const ec_sync_info_t syncs[] /**< Array of sync manager fp@1055: configurations. */ fp@792: ); fp@792: fp@1327: /** Registers a PDO entry for process data exchange in a domain. fp@1327: * fp@1327: * Searches the assigned PDOs for the given PDO entry. An error is raised, if fp@925: * the given entry is not mapped. Otherwise, the corresponding sync manager fp@925: * and FMMU configurations are provided for slave configuration and the fp@1327: * respective sync manager's assigned PDOs are appended to the given domain, fp@1327: * if not already done. The offset of the requested PDO entry's data inside fp@1327: * the domain's process data is returned. Optionally, the PDO entry bit fp@925: * position (0-7) can be retrieved via the \a bit_position output parameter. fp@1327: * This pointer may be \a NULL, in this case an error is raised if the PDO fp@925: * entry does not byte-align. fp@842: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@1327: * \retval >=0 Success: Offset of the PDO entry's process data. fp@1313: * \retval <0 Error code. fp@807: */ fp@807: int ecrt_slave_config_reg_pdo_entry( fp@807: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1327: uint16_t entry_index, /**< Index of the PDO entry to register. */ fp@1327: uint8_t entry_subindex, /**< Subindex of the PDO entry to register. */ ha@923: ec_domain_t *domain, /**< Domain. */ ch1010858@2241: unsigned int *bit_position /**< Optional address if bit addressing ha@923: is desired */ fp@916: ); fp@916: fp@2505: /** Registers a PDO entry using its position. fp@2505: * fp@2505: * Similar to ecrt_slave_config_reg_pdo_entry(), but not using PDO indices but fp@2505: * offsets in the PDO mapping, because PDO entry indices may not be unique fp@2505: * inside a slave's PDO mapping. An error is raised, if fp@2505: * one of the given positions is out of range. fp@2505: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@2505: * \retval >=0 Success: Offset of the PDO entry's process data. fp@2505: * \retval <0 Error code. fp@2505: */ fp@2505: int ecrt_slave_config_reg_pdo_entry_pos( fp@2505: ec_slave_config_t *sc, /**< Slave configuration. */ fp@2505: uint8_t sync_index, /**< Sync manager index. */ fp@2505: unsigned int pdo_pos, /**< Position of the PDO inside the SM. */ fp@2505: unsigned int entry_pos, /**< Position of the entry inside the PDO. */ fp@2505: ec_domain_t *domain, /**< Domain. */ fp@2505: unsigned int *bit_position /**< Optional address if bit addressing fp@2505: is desired */ fp@2505: ); fp@2505: fp@1448: /** Configure distributed clocks. fp@1448: * fp@1448: * Sets the AssignActivate word and the cycle and shift times for the sync fp@1448: * signals. fp@1392: * fp@1392: * The AssignActivate word is vendor-specific and can be taken from the XML fp@1392: * device description file (Device -> Dc -> AssignActivate). Set this to zero, fp@1396: * if the slave shall be operated without distributed clocks (default). fp@2449: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@2449: * \attention The \a sync1_shift time is ignored. fp@1392: */ fp@1448: void ecrt_slave_config_dc( fp@1804: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1448: uint16_t assign_activate, /**< AssignActivate word. */ fp@1438: uint32_t sync0_cycle, /**< SYNC0 cycle time [ns]. */ fp@2449: int32_t sync0_shift, /**< SYNC0 shift time [ns]. */ fp@1438: uint32_t sync1_cycle, /**< SYNC1 cycle time [ns]. */ fp@2449: int32_t sync1_shift /**< SYNC1 shift time [ns]. */ fp@1804: ); fp@1411: fp@1327: /** Add an SDO configuration. fp@1327: * fp@1327: * An SDO configuration is stored in the slave configuration object and is fp@893: * downloaded to the slave whenever the slave is being configured by the fp@893: * master. This usually happens once on master activation, but can be repeated fp@893: * subsequently, for example after the slave's power supply failed. fp@893: * fp@1327: * \attention The SDOs for PDO assignment (\p 0x1C10 - \p 0x1C2F) and PDO fp@1104: * mapping (\p 0x1600 - \p 0x17FF and \p 0x1A00 - \p 0x1BFF) should not be fp@1104: * configured with this function, because they are part of the slave fp@1104: * configuration done by the master. Please use ecrt_slave_config_pdos() and fp@1104: * friends instead. fp@1104: * fp@1327: * This is the generic function for adding an SDO configuration. Please note fp@2523: * that the this function does not do any endianness correction. If fp@893: * datatype-specific functions are needed (that automatically correct the fp@2523: * endianness), have a look at ecrt_slave_config_sdo8(), fp@893: * ecrt_slave_config_sdo16() and ecrt_slave_config_sdo32(). fp@893: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@1313: * \retval 0 Success. fp@1313: * \retval <0 Error code. fp@893: */ fp@893: int ecrt_slave_config_sdo( fp@893: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1327: uint16_t index, /**< Index of the SDO to configure. */ fp@1327: uint8_t subindex, /**< Subindex of the SDO to configure. */ fp@893: const uint8_t *data, /**< Pointer to the data. */ fp@893: size_t size /**< Size of the \a data. */ fp@893: ); fp@893: fp@792: /** Add a configuration value for an 8-bit SDO. fp@792: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@893: * \see ecrt_slave_config_sdo(). fp@1313: * fp@1313: * \retval 0 Success. fp@1313: * \retval <0 Error code. fp@792: */ fp@792: int ecrt_slave_config_sdo8( fp@792: ec_slave_config_t *sc, /**< Slave configuration */ fp@792: uint16_t sdo_index, /**< Index of the SDO to configure. */ fp@792: uint8_t sdo_subindex, /**< Subindex of the SDO to configure. */ fp@792: uint8_t value /**< Value to set. */ fp@792: ); fp@792: fp@792: /** Add a configuration value for a 16-bit SDO. fp@792: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@893: * \see ecrt_slave_config_sdo(). fp@1313: * fp@1313: * \retval 0 Success. fp@1313: * \retval <0 Error code. fp@792: */ fp@792: int ecrt_slave_config_sdo16( fp@792: ec_slave_config_t *sc, /**< Slave configuration */ fp@792: uint16_t sdo_index, /**< Index of the SDO to configure. */ fp@792: uint8_t sdo_subindex, /**< Subindex of the SDO to configure. */ fp@792: uint16_t value /**< Value to set. */ fp@792: ); fp@792: fp@792: /** Add a configuration value for a 32-bit SDO. fp@792: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@893: * \see ecrt_slave_config_sdo(). fp@1313: * fp@1313: * \retval 0 Success. fp@1313: * \retval <0 Error code. fp@792: */ fp@792: int ecrt_slave_config_sdo32( fp@792: ec_slave_config_t *sc, /**< Slave configuration */ fp@792: uint16_t sdo_index, /**< Index of the SDO to configure. */ fp@792: uint8_t sdo_subindex, /**< Subindex of the SDO to configure. */ fp@792: uint32_t value /**< Value to set. */ fp@792: ); fp@792: fp@1526: /** Add configuration data for a complete SDO. fp@1526: * fp@1526: * The SDO data are transferred via CompleteAccess. Data for the first fp@1526: * subindex (0) have to be included. fp@1526: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@1526: * \see ecrt_slave_config_sdo(). fp@1526: * fp@1526: * \retval 0 Success. fp@1526: * \retval <0 Error code. fp@1526: */ fp@1526: int ecrt_slave_config_complete_sdo( fp@1526: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1526: uint16_t index, /**< Index of the SDO to configure. */ fp@1526: const uint8_t *data, /**< Pointer to the data. */ fp@1526: size_t size /**< Size of the \a data. */ fp@1526: ); fp@1526: fp@2438: /** Set the size of the CoE emergency ring buffer. fp@2438: * fp@2438: * The initial size is zero, so all messages will be dropped. This method can fp@2438: * be called even after master activation, but it will clear the ring buffer! fp@2438: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@2438: * \return 0 on success, or negative error code. fp@2438: */ fp@2438: int ecrt_slave_config_emerg_size( fp@2438: ec_slave_config_t *sc, /**< Slave configuration. */ fp@2438: size_t elements /**< Number of records of the CoE emergency ring. */ fp@2438: ); fp@2438: fp@2438: /** Read and remove one record from the CoE emergency ring buffer. fp@2438: * fp@2438: * A record consists of 8 bytes: fp@2438: * fp@2438: * Byte 0-1: Error code (little endian) fp@2438: * Byte 2: Error register fp@2438: * Byte 3-7: Data fp@2438: * fp@2438: * \return 0 on success (record popped), or negative error code (i. e. fp@2438: * -ENOENT, if ring is empty). fp@2438: */ fp@2438: int ecrt_slave_config_emerg_pop( fp@2438: ec_slave_config_t *sc, /**< Slave configuration. */ fp@2438: uint8_t *target /**< Pointer to target memory (at least fp@2438: EC_COE_EMERGENCY_MSG_SIZE bytes). */ fp@2438: ); fp@2438: fp@2438: /** Clears CoE emergency ring buffer and the overrun counter. fp@2438: * fp@2438: * \return 0 on success, or negative error code. fp@2438: */ fp@2438: int ecrt_slave_config_emerg_clear( fp@2438: ec_slave_config_t *sc /**< Slave configuration. */ fp@2438: ); fp@2438: fp@2438: /** Read the number of CoE emergency overruns. fp@2438: * fp@2438: * The overrun counter will be incremented when a CoE emergency message could fp@2438: * not be stored in the ring buffer and had to be dropped. Call fp@2438: * ecrt_slave_config_emerg_clear() to reset the counter. fp@2438: * fp@2438: * \return Number of overruns since last clear, or negative error code. fp@2438: */ fp@2438: int ecrt_slave_config_emerg_overruns( fp@2438: ec_slave_config_t *sc /**< Slave configuration. */ fp@2438: ); fp@2438: fp@1327: /** Create an SDO request to exchange SDOs during realtime operation. fp@1327: * fp@1327: * The created SDO request object is freed automatically when the master is fp@858: * released. fp@2522: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@2522: * \return New SDO request, or NULL on error. fp@858: */ fp@858: ec_sdo_request_t *ecrt_slave_config_create_sdo_request( fp@858: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1327: uint16_t index, /**< SDO index. */ fp@1327: uint8_t subindex, /**< SDO subindex. */ fp@858: size_t size /**< Data size to reserve. */ fp@858: ); fp@858: fp@1209: /** Create an VoE handler to exchange vendor-specific data during realtime fp@1209: * operation. fp@1209: * fp@1267: * The number of VoE handlers per slave configuration is not limited, but fp@1267: * usually it is enough to create one for sending and one for receiving, if fp@1267: * both can be done simultaneously. fp@1267: * fp@1209: * The created VoE handler object is freed automatically when the master is fp@1209: * released. fp@2522: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@2522: * \return New VoE handler, or NULL on error. fp@1209: */ fp@1209: ec_voe_handler_t *ecrt_slave_config_create_voe_handler( fp@1209: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1209: size_t size /**< Data size to reserve. */ fp@1209: ); fp@1209: fp@2443: /** Create a register request to exchange EtherCAT register contents during fp@2443: * realtime operation. fp@2443: * fp@2443: * This interface should not be used to take over master functionality, fp@2443: * instead it is intended for debugging and monitoring reasons. fp@2443: * fp@2443: * The created register request object is freed automatically when the master fp@2443: * is released. fp@2522: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@2522: * \return New register request, or NULL on error. fp@2443: */ fp@2443: ec_reg_request_t *ecrt_slave_config_create_reg_request( fp@2443: ec_slave_config_t *sc, /**< Slave configuration. */ fp@2443: size_t size /**< Data size to reserve. */ fp@2443: ); fp@2443: fp@792: /** Outputs the state of the slave configuration. fp@792: * fp@1891: * Stores the state information in the given \a state structure. The state fp@1891: * information is updated by the master state machine, so it may take a few fp@1891: * cycles, until it changes. fp@1891: * fp@1891: * \attention If the state of process data exchange shall be monitored in fp@1891: * realtime, ecrt_domain_state() should be used. fp@792: */ fp@792: void ecrt_slave_config_state( fp@792: const ec_slave_config_t *sc, /**< Slave configuration */ fp@792: ec_slave_config_state_t *state /**< State object to write to. */ fp@792: ); fp@325: fp@1844: /** Add an SoE IDN configuration. fp@1844: * fp@1844: * A configuration for a Sercos-over-EtherCAT IDN is stored in the slave fp@1844: * configuration object and is written to the slave whenever the slave is fp@1844: * being configured by the master. This usually happens once on master fp@1844: * activation, but can be repeated subsequently, for example after the slave's fp@1844: * power supply failed. fp@1844: * fp@2444: * The \a idn parameter can be separated into several sections: fp@1861: * - Bit 15: Standard data (0) or Product data (1) fp@1861: * - Bit 14 - 12: Parameter set (0 - 7) fp@1861: * - Bit 11 - 0: Data block number (0 - 4095) fp@1861: * fp@2523: * Please note that the this function does not do any endianness correction. fp@2523: * Multi-byte data have to be passed in EtherCAT endianness (little-endian). fp@2523: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@1844: * fp@1844: * \retval 0 Success. fp@1844: * \retval <0 Error code. fp@1844: */ fp@1844: int ecrt_slave_config_idn( fp@1844: ec_slave_config_t *sc, /**< Slave configuration. */ fp@1952: uint8_t drive_no, /**< Drive number. */ fp@1844: uint16_t idn, /**< SoE IDN. */ fp@1944: ec_al_state_t state, /**< AL state in which to write the IDN (PREOP or fp@1944: SAFEOP). */ fp@1844: const uint8_t *data, /**< Pointer to the data. */ fp@1844: size_t size /**< Size of the \a data. */ fp@1844: ); fp@1844: fp@199: /****************************************************************************** fp@779: * Domain methods fp@199: *****************************************************************************/ fp@104: fp@1327: /** Registers a bunch of PDO entries for a domain. fp@792: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@2523: * \see ecrt_slave_config_reg_pdo_entry() fp@2523: * fp@792: * \attention The registration array has to be terminated with an empty fp@792: * structure, or one with the \a index field set to zero! fp@792: * \return 0 on success, else non-zero. fp@792: */ fp@792: int ecrt_domain_reg_pdo_entry_list( fp@792: ec_domain_t *domain, /**< Domain. */ fp@1327: const ec_pdo_entry_reg_t *pdo_entry_regs /**< Array of PDO fp@792: registrations. */ fp@792: ); fp@792: fp@792: /** Returns the current size of the domain's process data. fp@792: * fp@2504: * \return Size of the process data image, or a negative error code. fp@792: */ fp@792: size_t ecrt_domain_size( fp@1257: const ec_domain_t *domain /**< Domain. */ fp@792: ); fp@792: fp@2504: #ifdef __KERNEL__ fp@2504: fp@809: /** Provide external memory to store the domain's process data. fp@809: * fp@1327: * Call this after all PDO entries have been registered and before activating fp@809: * the master. fp@809: * fp@809: * The size of the allocated memory must be at least ecrt_domain_size(), after fp@1327: * all PDO entries have been registered. fp@2523: * fp@2523: * This method has to be called in non-realtime context before fp@2523: * ecrt_master_activate(). fp@2523: * fp@809: */ fp@809: void ecrt_domain_external_memory( fp@792: ec_domain_t *domain, /**< Domain. */ fp@792: uint8_t *memory /**< Address of the memory to store the process fp@792: data in. */ fp@792: ); fp@792: fp@1248: #endif /* __KERNEL__ */ fp@1248: fp@809: /** Returns the domain's process data. fp@809: * fp@1258: * - In kernel context: If external memory was provided with fp@1258: * ecrt_domain_external_memory(), the returned pointer will contain the fp@1258: * address of that memory. Otherwise it will point to the internally allocated fp@1258: * memory. In the latter case, this method may not be called before fp@1258: * ecrt_master_activate(). fp@1258: * fp@1258: * - In userspace context: This method has to be called after fp@1258: * ecrt_master_activate() to get the mapped domain process data memory. fp@1256: * fp@809: * \return Pointer to the process data memory. fp@809: */ fp@809: uint8_t *ecrt_domain_data( fp@809: ec_domain_t *domain /**< Domain. */ fp@809: ); fp@809: fp@886: /** Determines the states of the domain's datagrams. fp@886: * fp@886: * Evaluates the working counters of the received datagrams and outputs fp@886: * statistics, if necessary. This must be called after ecrt_master_receive() fp@886: * is expected to receive the domain datagrams in order to make fp@886: * ecrt_domain_state() return the result of the last process data exchange. fp@792: */ fp@792: void ecrt_domain_process( fp@792: ec_domain_t *domain /**< Domain. */ fp@792: ); fp@792: fp@792: /** (Re-)queues all domain datagrams in the master's datagram queue. fp@792: * fp@886: * Call this function to mark the domain's datagrams for exchanging at the fp@886: * next call of ecrt_master_send(). fp@792: */ fp@792: void ecrt_domain_queue( fp@792: ec_domain_t *domain /**< Domain. */ fp@792: ); fp@792: fp@792: /** Reads the state of a domain. fp@792: * fp@886: * Stores the domain state in the given \a state structure. fp@1891: * fp@1891: * Using this method, the process data exchange can be monitored in realtime. fp@792: */ fp@792: void ecrt_domain_state( fp@792: const ec_domain_t *domain, /**< Domain. */ fp@792: ec_domain_state_t *state /**< Pointer to a state object to store the fp@792: information. */ fp@792: ); fp@635: fp@858: /***************************************************************************** fp@1327: * SDO request methods. fp@858: ****************************************************************************/ fp@858: fp@2434: /** Set the SDO index and subindex. fp@2434: * fp@2434: * \attention If the SDO index and/or subindex is changed while fp@2439: * ecrt_sdo_request_state() returns EC_REQUEST_BUSY, this may lead to fp@2434: * unexpected results. fp@2434: */ fp@2434: void ecrt_sdo_request_index( fp@2434: ec_sdo_request_t *req, /**< SDO request. */ fp@2434: uint16_t index, /**< SDO index. */ fp@2434: uint8_t subindex /**< SDO subindex. */ fp@2434: ); fp@2434: fp@1327: /** Set the timeout for an SDO request. fp@858: * fp@858: * If the request cannot be processed in the specified time, if will be marked fp@858: * as failed. fp@1113: * fp@1113: * The timeout is permanently stored in the request object and is valid until fp@1113: * the next call of this method. fp@858: */ fp@858: void ecrt_sdo_request_timeout( fp@1327: ec_sdo_request_t *req, /**< SDO request. */ fp@880: uint32_t timeout /**< Timeout in milliseconds. Zero means no fp@880: timeout. */ fp@858: ); fp@858: fp@1327: /** Access to the SDO request's data. fp@1327: * fp@1327: * This function returns a pointer to the request's internal SDO data memory. fp@868: * fp@868: * - After a read operation was successful, integer data can be evaluated using fp@868: * the EC_READ_*() macros as usual. Example: fp@868: * \code fp@868: * uint16_t value = EC_READ_U16(ecrt_sdo_request_data(sdo))); fp@868: * \endcode fp@868: * - If a write operation shall be triggered, the data have to be written to fp@868: * the internal memory. Use the EC_WRITE_*() macros, if you are writing fp@868: * integer data. Be sure, that the data fit into the memory. The memory size fp@868: * is a parameter of ecrt_slave_config_create_sdo_request(). fp@868: * \code fp@868: * EC_WRITE_U16(ecrt_sdo_request_data(sdo), 0xFFFF); fp@868: * \endcode fp@868: * fp@864: * \attention The return value can be invalid during a read operation, because fp@1327: * the internal SDO data memory could be re-allocated if the read SDO data do fp@864: * not fit inside. fp@858: * fp@1327: * \return Pointer to the internal SDO data memory. fp@858: */ fp@858: uint8_t *ecrt_sdo_request_data( fp@1327: ec_sdo_request_t *req /**< SDO request. */ fp@1327: ); fp@1327: fp@1327: /** Returns the current SDO data size. fp@1327: * fp@1327: * When the SDO request is created, the data size is set to the size of the fp@869: * reserved memory. After a read operation the size is set to the size of the fp@869: * read data. The size is not modified in any other situation. fp@869: * fp@1327: * \return SDO data size in bytes. fp@869: */ fp@869: size_t ecrt_sdo_request_data_size( fp@1327: const ec_sdo_request_t *req /**< SDO request. */ fp@1327: ); fp@1327: fp@1327: /** Get the current state of the SDO request. fp@858: * fp@858: * \return Request state. fp@858: */ fp@1352: #ifdef __KERNEL__ fp@1209: ec_request_state_t ecrt_sdo_request_state( fp@1352: const ec_sdo_request_t *req /**< SDO request. */ fp@858: ); fp@1352: #else fp@1352: ec_request_state_t ecrt_sdo_request_state( fp@1352: ec_sdo_request_t *req /**< SDO request. */ fp@1352: ); fp@1352: #endif fp@858: fp@1327: /** Schedule an SDO write operation. fp@864: * fp@864: * \attention This method may not be called while ecrt_sdo_request_state() fp@2439: * returns EC_REQUEST_BUSY. fp@858: */ fp@858: void ecrt_sdo_request_write( fp@1327: ec_sdo_request_t *req /**< SDO request. */ fp@1327: ); fp@1327: fp@1327: /** Schedule an SDO read operation. fp@864: * fp@864: * \attention This method may not be called while ecrt_sdo_request_state() fp@2439: * returns EC_REQUEST_BUSY. fp@858: * fp@858: * \attention After calling this function, the return value of fp@864: * ecrt_sdo_request_data() must be considered as invalid while fp@2439: * ecrt_sdo_request_state() returns EC_REQUEST_BUSY. fp@858: */ fp@858: void ecrt_sdo_request_read( fp@1327: ec_sdo_request_t *req /**< SDO request. */ fp@858: ); fp@858: fp@1209: /***************************************************************************** fp@1209: * VoE handler methods. fp@1209: ****************************************************************************/ fp@1209: fp@1226: /** Sets the VoE header for future send operations. fp@1218: * fp@1218: * A VoE message shall contain a 4-byte vendor ID, followed by a 2-byte vendor fp@1267: * type at as header. These numbers can be set with this function. The values fp@1267: * are valid and will be used for future send operations until the next call fp@1267: * of this method. fp@1218: */ fp@1226: void ecrt_voe_handler_send_header( fp@1218: ec_voe_handler_t *voe, /**< VoE handler. */ fp@1218: uint32_t vendor_id, /**< Vendor ID. */ fp@1218: uint16_t vendor_type /**< Vendor-specific type. */ fp@1218: ); fp@1218: fp@1226: /** Reads the header data of a received VoE message. fp@1226: * fp@1267: * This method can be used to get the received VoE header information after a fp@1267: * read operation has succeeded. fp@1226: * fp@1226: * The header information is stored at the memory given by the pointer fp@1226: * parameters. fp@1226: */ fp@1226: void ecrt_voe_handler_received_header( fp@1226: const ec_voe_handler_t *voe, /**< VoE handler. */ fp@1226: uint32_t *vendor_id, /**< Vendor ID. */ fp@1226: uint16_t *vendor_type /**< Vendor-specific type. */ fp@1226: ); fp@1226: fp@1209: /** Access to the VoE handler's data. fp@1209: * fp@1267: * This function returns a pointer to the VoE handler's internal memory, that fp@1267: * points to the actual VoE data right after the VoE header (see fp@1267: * ecrt_voe_handler_send_header()). fp@1209: * fp@1209: * - After a read operation was successful, the memory contains the received fp@1209: * data. The size of the received data can be determined via fp@1209: * ecrt_voe_handler_data_size(). fp@1267: * - Before a write operation is triggered, the data have to be written to the fp@1267: * internal memory. Be sure, that the data fit into the memory. The reserved fp@1209: * memory size is a parameter of ecrt_slave_config_create_voe_handler(). fp@1209: * fp@1267: * \attention The returned pointer is not necessarily persistent: After a read fp@1267: * operation, the internal memory may have been reallocated. This can be fp@1267: * avoided by reserving enough memory via the \a size parameter of fp@1267: * ecrt_slave_config_create_voe_handler(). fp@1267: * fp@1209: * \return Pointer to the internal memory. fp@1209: */ fp@1209: uint8_t *ecrt_voe_handler_data( fp@1209: ec_voe_handler_t *voe /**< VoE handler. */ fp@1209: ); fp@1209: fp@1209: /** Returns the current data size. fp@1209: * fp@1218: * The data size is the size of the VoE data without the header (see fp@1226: * ecrt_voe_handler_send_header()). fp@1218: * fp@1209: * When the VoE handler is created, the data size is set to the size of the fp@1209: * reserved memory. At a write operation, the data size is set to the number fp@1209: * of bytes to write. After a read operation the size is set to the size of fp@1209: * the read data. The size is not modified in any other situation. fp@1209: * fp@1209: * \return Data size in bytes. fp@1209: */ fp@1209: size_t ecrt_voe_handler_data_size( fp@1209: const ec_voe_handler_t *voe /**< VoE handler. */ fp@1209: ); fp@1209: fp@1209: /** Start a VoE write operation. fp@1209: * fp@1209: * After this function has been called, the ecrt_voe_handler_execute() method fp@1226: * must be called in every bus cycle as long as it returns EC_REQUEST_BUSY. No fp@1226: * other operation may be started while the handler is busy. fp@1209: */ fp@1209: void ecrt_voe_handler_write( fp@1209: ec_voe_handler_t *voe, /**< VoE handler. */ fp@1218: size_t size /**< Number of bytes to write (without the VoE header). */ fp@1209: ); fp@1209: fp@1209: /** Start a VoE read operation. fp@1209: * fp@1209: * After this function has been called, the ecrt_voe_handler_execute() method fp@1226: * must be called in every bus cycle as long as it returns EC_REQUEST_BUSY. No fp@1226: * other operation may be started while the handler is busy. fp@1209: * fp@1267: * The state machine queries the slave's send mailbox for new data to be send fp@1267: * to the master. If no data appear within the EC_VOE_RESPONSE_TIMEOUT fp@1267: * (defined in master/voe_handler.c), the operation fails. fp@1267: * fp@1209: * On success, the size of the read data can be determined via fp@1226: * ecrt_voe_handler_data_size(), while the VoE header of the received data fp@1226: * can be retrieved with ecrt_voe_handler_received_header(). fp@1209: */ fp@1209: void ecrt_voe_handler_read( fp@1209: ec_voe_handler_t *voe /**< VoE handler. */ fp@1209: ); fp@1209: fp@1314: /** Start a VoE read operation without querying the sync manager status. fp@1314: * fp@1314: * After this function has been called, the ecrt_voe_handler_execute() method fp@1314: * must be called in every bus cycle as long as it returns EC_REQUEST_BUSY. No fp@1314: * other operation may be started while the handler is busy. fp@1314: * fp@1314: * The state machine queries the slave by sending an empty mailbox. The slave fp@1314: * fills its data to the master in this mailbox. If no data appear within the fp@1314: * EC_VOE_RESPONSE_TIMEOUT (defined in master/voe_handler.c), the operation fp@1314: * fails. fp@1314: * fp@1314: * On success, the size of the read data can be determined via fp@1314: * ecrt_voe_handler_data_size(), while the VoE header of the received data fp@1314: * can be retrieved with ecrt_voe_handler_received_header(). fp@1314: */ fp@1314: void ecrt_voe_handler_read_nosync( fp@1314: ec_voe_handler_t *voe /**< VoE handler. */ fp@1314: ); fp@1314: fp@1209: /** Execute the handler. fp@1209: * fp@2523: * This method executes the VoE handler. It has to be called in every bus fp@2523: * cycle as long as it returns EC_REQUEST_BUSY. fp@1209: * fp@1209: * \return Handler state. fp@1209: */ fp@1209: ec_request_state_t ecrt_voe_handler_execute( fp@1209: ec_voe_handler_t *voe /**< VoE handler. */ fp@1209: ); fp@1209: fp@2443: /***************************************************************************** fp@2443: * Register request methods. fp@2443: ****************************************************************************/ fp@2443: fp@2443: /** Access to the register request's data. fp@2443: * fp@2443: * This function returns a pointer to the request's internal memory. fp@2443: * fp@2523: * - After a read operation was successful, integer data can be evaluated fp@2523: * using the EC_READ_*() macros as usual. Example: fp@2443: * \code fp@2443: * uint16_t value = EC_READ_U16(ecrt_reg_request_data(reg_request))); fp@2443: * \endcode fp@2443: * - If a write operation shall be triggered, the data have to be written to fp@2443: * the internal memory. Use the EC_WRITE_*() macros, if you are writing fp@2443: * integer data. Be sure, that the data fit into the memory. The memory size fp@2443: * is a parameter of ecrt_slave_config_create_reg_request(). fp@2443: * \code fp@2443: * EC_WRITE_U16(ecrt_reg_request_data(reg_request), 0xFFFF); fp@2443: * \endcode fp@2443: * fp@2443: * \return Pointer to the internal memory. fp@2443: */ fp@2443: uint8_t *ecrt_reg_request_data( fp@2443: ec_reg_request_t *req /**< Register request. */ fp@2443: ); fp@2443: fp@2443: /** Get the current state of the register request. fp@2443: * fp@2443: * \return Request state. fp@2443: */ fp@2443: #ifdef __KERNEL__ fp@2443: ec_request_state_t ecrt_reg_request_state( fp@2443: const ec_reg_request_t *req /**< Register request. */ fp@2443: ); fp@2443: #else fp@2443: ec_request_state_t ecrt_reg_request_state( fp@2443: ec_reg_request_t *req /**< Register request. */ fp@2443: ); fp@2443: #endif fp@2443: fp@2443: /** Schedule an register write operation. fp@2443: * fp@2443: * \attention This method may not be called while ecrt_reg_request_state() fp@2443: * returns EC_REQUEST_BUSY. fp@2443: * fp@2443: * \attention The \a size parameter is truncated to the size given at request fp@2443: * creation. fp@2443: */ fp@2443: void ecrt_reg_request_write( fp@2443: ec_reg_request_t *req, /**< Register request. */ fp@2443: uint16_t address, /**< Register address. */ fp@2443: size_t size /**< Size to write. */ fp@2443: ); fp@2443: fp@2443: /** Schedule a register read operation. fp@2443: * fp@2443: * \attention This method may not be called while ecrt_reg_request_state() fp@2443: * returns EC_REQUEST_BUSY. fp@2443: * fp@2443: * \attention The \a size parameter is truncated to the size given at request fp@2443: * creation. fp@2443: */ fp@2443: void ecrt_reg_request_read( fp@2443: ec_reg_request_t *req, /**< Register request. */ fp@2443: uint16_t address, /**< Register address. */ fp@2443: size_t size /**< Size to write. */ fp@2443: ); fp@2443: fp@1288: /*****************************************************************************/ fp@1288: fp@1288: #ifdef __cplusplus fp@1288: } fp@1288: #endif fp@1288: fp@199: /****************************************************************************** fp@779: * Bitwise read/write macros fp@779: *****************************************************************************/ fp@779: fp@779: /** Read a certain bit of an EtherCAT data byte. fp@894: * fp@640: * \param DATA EtherCAT data pointer fp@640: * \param POS bit position fp@640: */ fp@199: #define EC_READ_BIT(DATA, POS) ((*((uint8_t *) (DATA)) >> (POS)) & 0x01) fp@199: fp@779: /** Write a certain bit of an EtherCAT data byte. fp@894: * fp@640: * \param DATA EtherCAT data pointer fp@640: * \param POS bit position fp@640: * \param VAL new bit value fp@640: */ fp@199: #define EC_WRITE_BIT(DATA, POS, VAL) \ fp@199: do { \ fp@199: if (VAL) *((uint8_t *) (DATA)) |= (1 << (POS)); \ fp@199: else *((uint8_t *) (DATA)) &= ~(1 << (POS)); \ fp@199: } while (0) fp@199: fp@199: /****************************************************************************** fp@1254: * Byte-swapping functions for user space fp@1254: *****************************************************************************/ fp@1254: fp@1254: #ifndef __KERNEL__ fp@1254: fp@1254: #if __BYTE_ORDER == __LITTLE_ENDIAN fp@1254: fp@1254: #define le16_to_cpu(x) x fp@1254: #define le32_to_cpu(x) x fp@1384: #define le64_to_cpu(x) x fp@1254: fp@1254: #define cpu_to_le16(x) x fp@1254: #define cpu_to_le32(x) x fp@1384: #define cpu_to_le64(x) x fp@1254: fp@1254: #elif __BYTE_ORDER == __BIG_ENDIAN fp@1254: fp@1254: #define swap16(x) \ fp@1254: ((uint16_t)( \ fp@1254: (((uint16_t)(x) & 0x00ffU) << 8) | \ fp@1254: (((uint16_t)(x) & 0xff00U) >> 8) )) fp@1254: #define swap32(x) \ fp@1254: ((uint32_t)( \ fp@1254: (((uint32_t)(x) & 0x000000ffUL) << 24) | \ fp@1254: (((uint32_t)(x) & 0x0000ff00UL) << 8) | \ fp@1254: (((uint32_t)(x) & 0x00ff0000UL) >> 8) | \ fp@1254: (((uint32_t)(x) & 0xff000000UL) >> 24) )) fp@1384: #define swap64(x) \ fp@1384: ((uint64_t)( \ fp@1384: (((uint64_t)(x) & 0x00000000000000ffULL) << 56) | \ fp@1384: (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ fp@1384: (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ fp@1384: (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ fp@1384: (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ fp@1384: (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ fp@1384: (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ fp@1384: (((uint64_t)(x) & 0xff00000000000000ULL) >> 56) )) fp@1254: fp@1254: #define le16_to_cpu(x) swap16(x) fp@1254: #define le32_to_cpu(x) swap32(x) fp@1384: #define le64_to_cpu(x) swap64(x) fp@1254: fp@1254: #define cpu_to_le16(x) swap16(x) fp@1254: #define cpu_to_le32(x) swap32(x) fp@1384: #define cpu_to_le64(x) swap64(x) fp@1254: fp@1254: #endif fp@1254: fp@1254: #define le16_to_cpup(x) le16_to_cpu(*((uint16_t *)(x))) fp@1254: #define le32_to_cpup(x) le32_to_cpu(*((uint32_t *)(x))) fp@1384: #define le64_to_cpup(x) le64_to_cpu(*((uint64_t *)(x))) fp@1254: fp@1254: #endif /* ifndef __KERNEL__ */ fp@1254: fp@1254: /****************************************************************************** fp@779: * Read macros fp@779: *****************************************************************************/ fp@779: fp@779: /** Read an 8-bit unsigned value from EtherCAT data. fp@894: * fp@779: * \return EtherCAT data value fp@779: */ fp@199: #define EC_READ_U8(DATA) \ fp@199: ((uint8_t) *((uint8_t *) (DATA))) fp@199: fp@779: /** Read an 8-bit signed value from EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \return EtherCAT data value fp@779: */ fp@199: #define EC_READ_S8(DATA) \ fp@288: ((int8_t) *((uint8_t *) (DATA))) fp@199: fp@779: /** Read a 16-bit unsigned value from EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \return EtherCAT data value fp@779: */ fp@199: #define EC_READ_U16(DATA) \ fp@199: ((uint16_t) le16_to_cpup((void *) (DATA))) fp@199: fp@779: /** Read a 16-bit signed value from EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \return EtherCAT data value fp@779: */ fp@199: #define EC_READ_S16(DATA) \ fp@288: ((int16_t) le16_to_cpup((void *) (DATA))) fp@199: fp@779: /** Read a 32-bit unsigned value from EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \return EtherCAT data value fp@779: */ fp@199: #define EC_READ_U32(DATA) \ fp@199: ((uint32_t) le32_to_cpup((void *) (DATA))) fp@199: fp@779: /** Read a 32-bit signed value from EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \return EtherCAT data value fp@779: */ fp@199: #define EC_READ_S32(DATA) \ fp@288: ((int32_t) le32_to_cpup((void *) (DATA))) fp@199: fp@1384: /** Read a 64-bit unsigned value from EtherCAT data. fp@1384: * fp@1384: * \param DATA EtherCAT data pointer fp@1384: * \return EtherCAT data value fp@1384: */ fp@1384: #define EC_READ_U64(DATA) \ fp@1384: ((uint64_t) le64_to_cpup((void *) (DATA))) fp@1384: fp@1384: /** Read a 64-bit signed value from EtherCAT data. fp@1384: * fp@1384: * \param DATA EtherCAT data pointer fp@1384: * \return EtherCAT data value fp@1384: */ fp@1384: #define EC_READ_S64(DATA) \ fp@1384: ((int64_t) le64_to_cpup((void *) (DATA))) fp@1384: fp@199: /****************************************************************************** fp@779: * Write macros fp@779: *****************************************************************************/ fp@779: fp@779: /** Write an 8-bit unsigned value to EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \param VAL new value fp@779: */ fp@199: #define EC_WRITE_U8(DATA, VAL) \ fp@199: do { \ fp@199: *((uint8_t *)(DATA)) = ((uint8_t) (VAL)); \ fp@199: } while (0) fp@199: fp@779: /** Write an 8-bit signed value to EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \param VAL new value fp@779: */ fp@199: #define EC_WRITE_S8(DATA, VAL) EC_WRITE_U8(DATA, VAL) fp@199: fp@779: /** Write a 16-bit unsigned value to EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \param VAL new value fp@779: */ fp@199: #define EC_WRITE_U16(DATA, VAL) \ fp@199: do { \ fp@894: *((uint16_t *) (DATA)) = cpu_to_le16((uint16_t) (VAL)); \ fp@199: } while (0) fp@199: fp@779: /** Write a 16-bit signed value to EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \param VAL new value fp@779: */ fp@199: #define EC_WRITE_S16(DATA, VAL) EC_WRITE_U16(DATA, VAL) fp@199: fp@779: /** Write a 32-bit unsigned value to EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \param VAL new value fp@779: */ fp@199: #define EC_WRITE_U32(DATA, VAL) \ fp@199: do { \ fp@894: *((uint32_t *) (DATA)) = cpu_to_le32((uint32_t) (VAL)); \ fp@199: } while (0) fp@199: fp@779: /** Write a 32-bit signed value to EtherCAT data. fp@894: * fp@779: * \param DATA EtherCAT data pointer fp@779: * \param VAL new value fp@779: */ fp@199: #define EC_WRITE_S32(DATA, VAL) EC_WRITE_U32(DATA, VAL) fp@199: fp@1384: /** Write a 64-bit unsigned value to EtherCAT data. fp@1384: * fp@1384: * \param DATA EtherCAT data pointer fp@1384: * \param VAL new value fp@1384: */ fp@1384: #define EC_WRITE_U64(DATA, VAL) \ fp@1384: do { \ fp@1384: *((uint64_t *) (DATA)) = cpu_to_le64((uint64_t) (VAL)); \ fp@1384: } while (0) fp@1384: fp@1384: /** Write a 64-bit signed value to EtherCAT data. fp@1384: * fp@1384: * \param DATA EtherCAT data pointer fp@1384: * \param VAL new value fp@1384: */ fp@1384: #define EC_WRITE_S64(DATA, VAL) EC_WRITE_U64(DATA, VAL) fp@1384: fp@104: /*****************************************************************************/ fp@104: fp@792: /** @} */ fp@792: fp@104: #endif