fp@104: /****************************************************************************** fp@104: * fp@125: * $Id$ fp@104: * fp@197: * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH fp@197: * fp@197: * This file is part of the IgH EtherCAT Master. fp@197: * fp@197: * The IgH EtherCAT Master is free software; you can redistribute it fp@197: * and/or modify it under the terms of the GNU General Public License fp@246: * as published by the Free Software Foundation; either version 2 of the fp@246: * License, or (at your option) any later version. fp@197: * fp@197: * The IgH EtherCAT Master is distributed in the hope that it will be fp@197: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of fp@197: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fp@197: * GNU General Public License for more details. fp@197: * fp@197: * You should have received a copy of the GNU General Public License fp@197: * along with the IgH EtherCAT Master; if not, write to the Free Software fp@197: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@197: * fp@246: * The right to use EtherCAT Technology is granted and comes free of fp@246: * charge under condition of compatibility of product made by fp@246: * Licensee. People intending to distribute/sell products based on the fp@246: * code, have to sign an agreement to guarantee that products using fp@246: * software based on IgH EtherCAT master stay compatible with the actual fp@246: * EtherCAT specification (which are released themselves as an open fp@246: * standard) as the (only) precondition to have the right to use EtherCAT fp@246: * Technology, IP and trade marks. fp@246: * fp@104: *****************************************************************************/ fp@104: fp@786: /** \file fp@786: * fp@786: * EtherCAT Real-Time Interface. fp@786: * fp@786: * \defgroup RealtimeInterface EtherCAT Real-Time Interface fp@786: * fp@786: * EtherCAT interface for realtime modules. This interface is designed for fp@786: * realtime modules that want to use EtherCAT. There are functions to request fp@786: * a master, to map process data, to communicate with slaves via CoE and to fp@786: * configure and activate the bus. fp@792: * fp@792: * Changes in Version 1.4: fp@792: * fp@792: * - Replaced ec_slave_t with ec_slave_config_t, separating the slave objects fp@792: * from the requested bus configuration. Therefore, renamed fp@792: * ecrt_master_get_slave() to ecrt_master_slave_config(). fp@792: * - Replaced slave address string with alias and position values. See fp@792: * ecrt_master_slave_config(). fp@792: * - Removed ecrt_master_get_slave_by_pos(), because it is no longer fp@792: * necessary (alias/position, slave configurations). fp@792: * - Added ec_slave_config_state_t for the new method fp@792: * ecrt_slave_config_state(). fp@792: * - Process data memory for a domain can now be allocated externally. This fp@792: * offers the possibility to use a shared-memory-region. Therefore, fp@792: * added the domain methods ecrt_domain_size() and ecrt_domain_memory(). fp@792: * - Replaced the process data pointers in the Pdo entry registration fp@792: * functions with a process data offset, that is now returned by fp@792: * ecrt_domain_reg_pdo_entry(). This was necessary for the external fp@792: * domain memory. An additional advantage is, that the returned offset value fp@792: * is directly usable. fp@792: * - Replaced ecrt_slave_pdo_mapping/add/clear() with fp@792: * ecrt_slave_config_mapping() that is now able to specify Pdo mapping and fp@792: * Pdo configuration. Pdo entries mapped in this way can now immediately be fp@792: * registered. The Pdo mapping and the configuration are described with the fp@792: * new data types ec_pdo_info_t and ec_pdo_entry_info_t. fp@792: * - Renamed ec_bus_status_t, ec_master_status_t to ec_bus_state_t and fp@792: * ec_master_state_t, respectively. Renamed ecrt_master_get_status() to fp@792: * ecrt_master_state(), for consistency reasons. fp@792: * - Added ec_domain_state_t and ec_wc_state_t for a new output parameter fp@792: * of ecrt_domain_state(). fp@792: * - Former "Pdo registration" meant Pdo entry registration in fact, therefore fp@792: * renamed ec_pdo_reg_t to ec_pdo_entry_reg_t and ecrt_domain_register_pdo() fp@792: * to ecrt_domain_reg_pdo_entry(). fp@792: * - Removed ecrt_domain_register_pdo_range(), because it's functionality can fp@792: * be reached by specifying an explicit Pdo mapping and registering those fp@792: * Pdo entries. fp@792: * fp@792: * @{ fp@786: */ fp@199: fp@199: /*****************************************************************************/ fp@199: fp@125: #ifndef __ECRT_H__ fp@125: #define __ECRT_H__ fp@104: fp@104: #include fp@104: fp@110: #ifdef __KERNEL__ fp@110: #include fp@110: #else fp@110: #include fp@110: #endif fp@110: fp@779: /****************************************************************************** fp@779: * Global definitions fp@779: *****************************************************************************/ fp@779: fp@779: /** EtherCAT real-time interface major version number. fp@758: */ fp@637: #define ECRT_VER_MAJOR 1 fp@758: fp@779: /** EtherCAT real-time interface minor version number. fp@779: */ fp@779: #define ECRT_VER_MINOR 4 fp@779: fp@779: /** EtherCAT real-time interface version word generator. fp@779: */ fp@779: #define ECRT_VERSION(a, b) (((a) << 8) + (b)) fp@779: fp@779: /** EtherCAT real-time interface version word. fp@758: */ fp@541: #define ECRT_VERSION_MAGIC ECRT_VERSION(ECRT_VER_MAJOR, ECRT_VER_MINOR) fp@541: 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@792: /*****************************************************************************/ fp@792: fp@792: /** Bus state. fp@792: * fp@792: * This is used in ec_master_state_t. fp@779: */ fp@612: typedef enum { fp@792: EC_BUS_FAILURE = -1, /**< At least one configured slave is offline. */ fp@792: EC_BUS_OK /**< All configured slaves are online. */ fp@792: } ec_bus_state_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Master state. fp@792: * fp@792: * This is used for the output parameter of ecrt_master_state(). fp@612: */ fp@612: typedef struct { fp@792: ec_bus_state_t bus_state; /**< \see ec_bus_state_t */ fp@792: unsigned int bus_tainted; /**< Non-zero, if the bus topology differs from fp@792: the requested configuration. */ fp@792: unsigned int slaves_responding; /**< Number of slaves in the bus. */ fp@792: } ec_master_state_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Slave configuration state. fp@792: * fp@792: * \see ecrt_slave_config_state(). fp@792: */ fp@792: typedef struct { fp@792: unsigned int online : 1; /**< The slave is online. */ fp@792: unsigned int configured : 1; /**< The slave was configured according to fp@792: the specified configuration. */ fp@792: } ec_slave_config_state_t; fp@792: fp@792: /*****************************************************************************/ fp@792: 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@792: EC_WC_ZERO = 0, /**< No Pdos were exchanged. */ fp@792: EC_WC_INCOMPLETE, /**< Some of the registered Pdos were exchanged. */ fp@792: EC_WC_COMPLETE /**< All registered Pdos 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@792: /** Direction type for Pdo mapping functions. fp@779: */ fp@635: typedef enum { fp@792: EC_DIR_OUTPUT, /**< Values written by the master. */ fp@792: EC_DIR_INPUT /**< Values read by the master. */ fp@792: } ec_direction_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** Pdo entry mapping. fp@792: * fp@792: * \see ecrt_slave_config_mapping(). fp@792: */ fp@792: typedef struct { fp@792: uint16_t index; /**< Index of the Pdo entry to add to the Pdo fp@792: configuration. */ fp@792: uint8_t subindex; /**< Subindex of the Pdo entry to add to the fp@792: Pdo configuration. */ fp@792: 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@792: /** Pdo information. fp@792: * fp@792: * \see ecrt_slave_config_mapping(). fp@792: */ fp@792: typedef struct { fp@792: ec_direction_t dir; /**< Pdo direction (input/output). */ fp@792: uint16_t index; /**< Index of the Pdo to map. */ fp@792: unsigned int n_entries; /**< Number of Pdo entries for the Pdo fp@792: configuration. Zero means, that the default Pdo fp@792: configuration shall be used. */ fp@793: const ec_pdo_entry_info_t *entries; /**< Pdo configuration array. This fp@793: array must contain at least \a fp@793: n_entries values. */ fp@792: } ec_pdo_info_t; fp@792: fp@792: /*****************************************************************************/ fp@792: fp@792: /** List record type for Pdo entry mass-registration. fp@792: * fp@792: * This type is used for the array parameter of the fp@792: * ecrt_domain_reg_pdo_entry_list() convenience function. 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@792: uint16_t index; /**< Pdo entry index. */ fp@792: uint8_t subindex; /**< Pdo entry subindex. */ fp@792: uint8_t *offset; /**< Pointer to a variable to store the Pdo's fp@792: offset in the process data. */ fp@792: } ec_pdo_entry_reg_t; fp@416: fp@199: /****************************************************************************** fp@779: * Global functions fp@199: *****************************************************************************/ fp@104: 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@792: * \return pointer to reserved master, or NULL on error 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@792: /** Releases a requested EtherCAT master. 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@792: /** Sets the locking callbacks. fp@792: * fp@792: * The request_cb function must return zero, to allow another instance fp@792: * (the EoE process for example) to access the master. Non-zero means, fp@792: * that access is forbidden at this time. fp@792: */ fp@792: void ecrt_master_callbacks( fp@792: ec_master_t *master, /**< EtherCAT master */ fp@792: int (*request_cb)(void *), /**< Lock request function. */ fp@792: void (*release_cb)(void *), /**< Lock release function. */ fp@792: void *cb_data /**< Arbitrary user data. */ fp@792: ); fp@792: fp@792: /** Creates a new domain. 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@792: uint32_t product_code /**< Expected product code. */ fp@792: ); fp@792: fp@792: /** Applies the bus configuration and switches to realtime mode. fp@792: * fp@792: * Does the complete configuration and activation for all slaves. Sets sync fp@792: * managers and FMMUs, and does the appropriate transitions, until the slave fp@792: * is operational. fp@792: * fp@792: * \return 0 in case of success, else < 0 fp@792: */ fp@792: int ecrt_master_activate( fp@792: ec_master_t *master /**< EtherCAT master. */ fp@792: ); fp@792: fp@792: /** Sends all datagrams in the queue. fp@792: * fp@792: * \todo doc 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@792: */ fp@792: void ecrt_master_receive( fp@792: ec_master_t *master /**< EtherCAT master. */ fp@792: ); fp@792: 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@792: /****************************************************************************** fp@792: * Slave configuration methods fp@792: *****************************************************************************/ fp@792: fp@792: /** Specify the Pdo mapping and (optionally) the Pdo configuration. fp@792: * fp@792: * The following example shows, how to specify a complete Pdo mapping fp@792: * including the Pdo configuration. With this information, the master is able fp@792: * to reserve the complete process data, even if the slave is not present fp@792: * at configuration time: fp@792: * fp@792: * \code fp@792: * const ec_pdo_info_t complete_mapping[] = { fp@792: * {EC_DIR_INPUT, 0x1600, 2, { // channel 1 fp@792: * {0x7000, 0, 16}, // value fp@792: * {0x7000, 1, 8}, // status fp@792: * }}, fp@792: * {EC_DIR_INPUT, 0x1601, 2, { // channel 2 fp@792: * {0x7001, 0, 16}, // value fp@792: * {0x7001, 1, 8}, // status fp@792: * }} fp@792: * }; fp@792: * fp@792: * if (ecrt_slave_config_mapping(slave_config_ana_in, 2, complete_mapping)) { fp@792: * // error fp@792: * } fp@792: * \endcode fp@792: * fp@792: * The next example shows, how to configure only the Pdo mapping. The entries fp@792: * for each mapped Pdo are taken from the default Pdo configuration. Please fp@792: * note, that Pdo entry registration will fail, if no Pdo configuration is fp@792: * specified and the slave is offline. fp@792: * fp@792: * \code fp@792: * const ec_pdo_info_t pdo_mapping[] = { fp@792: * {EC_DIR_INPUT, 0x1600}, // Channel 1 fp@792: * {EC_DIR_INPUT, 0x1601} // Channel 2 fp@792: * }; fp@792: * fp@792: * if (ecrt_slave_config_mapping(slave_config_ana_in, 2, pdo_mapping)) { fp@792: * // error fp@792: * } fp@792: * \endcode fp@792: * fp@792: * \return zero on success, else non-zero fp@792: */ fp@792: int ecrt_slave_config_mapping( fp@792: ec_slave_config_t *sc, /**< Slave configuration. */ fp@792: unsigned int n_entries, /**< Number of Pdos in \a pdos to map. */ fp@792: const ec_pdo_info_t pdos[] /**< List with Pdo mapping. */ fp@792: ); fp@792: fp@792: /** Add a configuration value for an 8-bit SDO. fp@792: * fp@792: * \todo doc fp@792: * \return 0 in case of success, else < 0 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@792: * \todo doc fp@792: * \return 0 in case of success, else < 0 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@792: * \todo doc fp@792: * \return 0 in case of success, else < 0 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@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@792: /** Registers a single Pdo entry for a domain. fp@792: * fp@792: * \return On success, the function returns the offset in the domain's process fp@792: * data, which can be zero or greater. On failure, it returns a value fp@792: * less than zero. fp@792: */ fp@792: fp@792: int ecrt_domain_reg_pdo_entry( fp@792: ec_domain_t *domain, /**< Domain. */ fp@792: ec_slave_config_t *sc, /**< Slave configuration. */ fp@792: uint16_t entry_index, /**< Index of the Pdo entry to register. */ fp@792: uint8_t entry_subindex /**< Subindex of the Pdo entry to register. */ fp@792: ); fp@792: fp@792: /** 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@792: 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@792: * \return Size of the process data image. fp@792: */ fp@792: size_t ecrt_domain_size( fp@792: ec_domain_t *domain /**< Domain. */ fp@792: ); fp@792: fp@792: /** Provide memory to store the domain's process data. fp@792: * fp@792: * Call this after all Pdo entries have been registered. Since interface fp@792: * version 1.4, you'll have to provide an external memory for the domain fp@792: * process data. fp@792: * fp@792: * The size of the allocated memory must be at least the return value of fp@792: * ecrt_domain_size(), after all Pdo entries have been registered. fp@792: */ fp@792: void ecrt_domain_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@792: /** Processes received datagrams. fp@792: * fp@792: * \todo doc 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@792: * \todo doc 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@792: * Stores the domain state in the giveb \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@199: /****************************************************************************** fp@779: * Bitwise read/write macros fp@779: *****************************************************************************/ fp@779: fp@779: /** Read a certain bit of an EtherCAT data byte. 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@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@779: * Read macros fp@779: *****************************************************************************/ fp@779: fp@779: /** Read an 8-bit unsigned value from EtherCAT data. 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@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@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@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@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@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@199: /****************************************************************************** fp@779: * Write macros fp@779: *****************************************************************************/ fp@779: fp@779: /** Write an 8-bit unsigned value to EtherCAT data. 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@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@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@199: *((uint16_t *) (DATA)) = (uint16_t) (VAL); \ fp@199: cpu_to_le16s(DATA); \ fp@199: } while (0) fp@199: fp@779: /** Write a 16-bit signed value to EtherCAT data. 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@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@199: *((uint32_t *) (DATA)) = (uint32_t) (VAL); \ fp@707: cpu_to_le32s(DATA); \ fp@199: } while (0) fp@199: fp@779: /** Write a 32-bit signed value to EtherCAT data. 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@104: /*****************************************************************************/ fp@104: fp@792: /** @} */ fp@792: fp@104: #endif