fp@104: /******************************************************************************
fp@104: *
fp@1341: * $Id$
fp@1341: *
fp@1341: * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
fp@1341: *
fp@1341: * This file is part of the IgH EtherCAT master userspace library.
fp@1341: *
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: * .
fp@1341: *
fp@1363: * ---
fp@1363: *
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@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()
fp@1535: * 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@1510: * - Added ecrt_master_sdo_download() and ecrt_master_sdo_upload()
fp@1510: * methods to let an application transfer SDOs 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@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@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:
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@779: /******************************************************************************
fp@779: * 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@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@792: unsigned int slaves_responding; /**< Number of slaves in the bus. */
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@1022: unsigned int link_up : 1; /**< \a true, if the network link is up. */
fp@792: } ec_master_state_t;
fp@792:
fp@792: /*****************************************************************************/
fp@792:
fp@792: /** Slave configuration state.
fp@792: *
fp@1020: * This is used as an output parameter of ecrt_slave_config_state().
fp@1020: *
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. */
fp@1804: 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:
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. */
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@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.
fp@1055: *
fp@1055: * This is the data type of the \a pdos field in ec_sync_info_t.
fp@1055: *
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. */
fp@1092: 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@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.
fp@792: *
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@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: */
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@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@1513: void *cb_data /**< Arbitraty 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@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@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@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@1510: /** Executes an SDO write request to download data.
fp@1510: *
fp@1510: * This function operates aside of the normal way to request SDOs. Before the
fp@1510: * activation of the master, these requests are processed by the master state
fp@1510: * machine itself. After activation the user has to ensure cyclic processing.
fp@1510: *
fp@1510: * \retval 0 Success.
fp@1510: * \retval -1 An error occured.
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@1510: /** Executes a SDO read request to upload data.
fp@1510: *
fp@1510: * This function operates aside of the normal way to request SDOs. Before the
fp@1510: * activation of the master, these requests are processed by the master state
fp@1510: * machine itself. After activation the user have to ensure cyclic
fp@1510: * processing.
fp@1510: *
fp@1510: * \retval 0 Success.
fp@1512: * \retval -1 Error occurred.
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@1497: #endif /* #ifndef __KERNEL__ */
fp@1441:
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@879: * not be called!
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@1530: */
fp@1530: void ecrt_master_deactivate(
fp@1530: ec_master_t *master /**< EtherCAT master. */
fp@1530: );
fp@1530:
martin@1585:
martin@1600: /** Set interval between calls to ecrt_master_send
martin@1600: *
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@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@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.
fp@1466: *
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().
fp@1434: *
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@1535: /** Queues the DC synchonity monitoring datagram for sending.
fp@1535: *
fp@1535: * The datagram broadcast-reads all "System time difference" registers (\a
fp@1535: * 0x092c) to get an upper estiomation of the DC synchony. 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@1535: /** Processes the DC synchonity 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@1535: * \return Upper estination 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@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@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@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@1536: default ist 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@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.
fp@1055: *
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@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@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: * };
fp@792: *
fp@1082: * ec_pdo_entry_info_t el3162_channel2[] = {
fp@842: * {0x3102, 1, 8}, // status
fp@842: * {0x3102, 2, 16} // value
fp@842: * };
fp@842: *
fp@1082: * ec_pdo_info_t el3162_pdos[] = {
fp@1055: * {0x1A00, 2, el3162_channel1},
fp@1082: * {0x1A01, 2, el3162_channel2}
fp@842: * };
fp@842: *
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: * };
fp@1055: *
fp@1082: * if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3162_syncs)) {
fp@1082: * // handle error
fp@1082: * }
fp@792: * \endcode
fp@879: *
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: * };
fp@792: *
fp@1082: * ec_sync_info_t syncs[] = {
fp@1082: * {3, EC_DIR_INPUT, 2, pdos},
fp@1055: * };
fp@1055: *
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@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@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. */
fp@925: unsigned int *bit_position /**< Optional address if bit addressing
ha@923: is desired */
fp@916: );
fp@916:
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@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@1804: uint32_t sync0_shift, /**< SYNC0 shift time [ns]. */
fp@1438: uint32_t sync1_cycle, /**< SYNC1 cycle time [ns]. */
fp@1804: uint32_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@893: * that the this function does not do any endianess correction. If
fp@893: * datatype-specific functions are needed (that automatically correct the
fp@893: * endianess), have a look at ecrt_slave_config_sdo8(),
fp@893: * ecrt_slave_config_sdo16() and ecrt_slave_config_sdo32().
fp@893: *
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@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@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@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@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@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@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@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@792: /** Outputs the state of the slave configuration.
fp@792: *
fp@792: * Stores the state information in the given \a state structure.
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@199: /******************************************************************************
fp@779: * Domain methods
fp@199: *****************************************************************************/
fp@104:
fp@1327: /** Registers a bunch of PDO entries for a domain.
fp@792: *
fp@792: * \todo doc
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@1258: #ifdef __KERNEL__
fp@1258:
fp@792: /** Returns the current size of the domain's process data.
fp@792: *
fp@792: * \return Size of the process data image.
fp@792: */
fp@792: size_t ecrt_domain_size(
fp@1257: const ec_domain_t *domain /**< Domain. */
fp@792: );
fp@792:
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@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@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@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@864: * returns EC_SDO_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@864: * returns EC_SDO_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@864: * ecrt_sdo_request_state() returns EC_SDO_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@1209: * This method executes the VoE handler. It has to be called in every bus cycle
fp@1209: * 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@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