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@864: * EtherCAT Realtime Interface. fp@864: * fp@864: * \defgroup RealtimeInterface EtherCAT Realtime 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@792: * Changes in Version 1.4: fp@792: * fp@1083: * - Replaced ec_slave_t with ec_slave_config_t, separating the bus fp@1083: * configuration from the actual slaves. 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@807: * necessary due to alias/position addressing. 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@842: * offers the possibility to use a shared-memory region. Therefore, fp@809: * added the domain methods ecrt_domain_size() and fp@809: * ecrt_domain_external_memory(). fp@925: * - Pdo entry registration functions do not return a process data pointer, fp@925: * but an offset in the domain's process data. In addition, an optional bit fp@925: * position can be requested. This was necessary for the external domain fp@925: * memory. An additional advantage is, that the returned offset is fp@925: * immediately valid. If the domain's process data is allocated internally, fp@925: * the start address can be retrieved with ecrt_domain_data(). fp@792: * - Replaced ecrt_slave_pdo_mapping/add/clear() with fp@879: * ecrt_slave_config_pdo_assign_add() to add a Pdo to a sync manager's Pdo fp@879: * assignment and ecrt_slave_config_pdo_mapping_add() to add a Pdo entry to a fp@879: * Pdo's mapping. ecrt_slave_config_pdos() is a convenience function fp@879: * for both, that uses the new data types ec_pdo_info_t and fp@879: * ec_pdo_entry_info_t. Pdo entries, that are mapped with these functions fp@879: * can now immediately be registered, even if the bus is offline. 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@1083: * - Added ec_domain_state_t and #ec_wc_state_t for a new output parameter fp@832: * of ecrt_domain_state(). The domain state object does now contain fp@832: * information, if the process data was exchanged completely. 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@807: * to ecrt_slave_config_reg_pdo_entry(). fp@792: * - Removed ecrt_domain_register_pdo_range(), because it's functionality can fp@925: * be reached by specifying an explicit Pdo assignment/mapping and fp@925: * registering the mapped Pdo entries. fp@864: * - Added an Sdo access interface, working with Sdo requests. These can be fp@864: * scheduled for reading and writing during realtime operation. fp@893: * - Exported ecrt_slave_config_sdo(), the generic Sdo configuration function. fp@900: * - Removed the bus_state and bus_tainted flags from ec_master_state_t. 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@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@779: #define ECRT_VER_MINOR 4 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@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@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@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@925: /** 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@1055: /** 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@1055: uint16_t index; /**< Pdo entry index. */ fp@1055: uint8_t subindex; /**< Pdo entry subindex. */ 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@1055: /** 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@1055: uint16_t index; /**< Pdo index. */ fp@1082: 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@1055: 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@1055: * This can be use to configure multiple sync managers including the Pdo fp@1055: * 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@1082: unsigned int n_pdos; /**< Number of Pdos in \a pdos. */ fp@1055: ec_pdo_info_t *pdos; /**< Array with Pdos to assign. This must contain fp@1055: at least \a n_pdos Pdos. */ fp@1055: } ec_sync_info_t; fp@1055: fp@1055: /*****************************************************************************/ fp@1055: fp@792: /** 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@792: uint16_t index; /**< Pdo entry index. */ fp@792: uint8_t subindex; /**< Pdo entry subindex. */ fp@925: 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@1092: Pdo entry does not byte-align. */ fp@792: } ec_pdo_entry_reg_t; fp@416: fp@858: /*****************************************************************************/ fp@858: fp@861: /** Sdo request state. fp@861: * fp@861: * This is used as return type of ecrt_sdo_request_state(). fp@858: */ fp@858: typedef enum { fp@861: EC_SDO_REQUEST_UNUSED, /**< Not requested. */ fp@861: EC_SDO_REQUEST_BUSY, /**< Request is being processed. */ fp@861: EC_SDO_REQUEST_SUCCESS, /**< Request was processed successfully. */ fp@861: EC_SDO_REQUEST_ERROR, /**< Request processing failed. */ fp@861: } ec_sdo_request_state_t; fp@858: 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@1092: * Before an application can access an EtherCAT master, it has to reserve one fp@1092: * for exclusive use. fp@1092: * 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@1092: * \return Pointer to reserved master, or \a 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@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@792: /** Sets the locking callbacks. fp@792: * fp@1092: * For concurrent master access, the application has to provide a locking fp@1092: * mechanism (see section FIXME in the docs). The method takes two function fp@1092: * pointers and a data value as its parameters. The arbitrary \a cb_data value fp@1092: * will be passed as argument on every callback. Asynchronous master access fp@1092: * (like EoE processing) is only possible if the callbacks have been set. fp@1092: * fp@792: * The request_cb function must return zero, to allow another instance fp@1092: * (an EoE process for example) to access the master. Non-zero means, fp@1092: * that access is currently forbidden. 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@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@1092: * 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@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@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@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@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@1055: ec_direction_t dir /**< Input/Output. */ fp@1055: ); fp@1055: fp@879: /** 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@879: uint16_t index /**< Index of the Pdo to assign. */ fp@879: ); fp@879: fp@879: /** Clear a sync manager's Pdo assignment. fp@879: * fp@879: * 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@879: /** 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@879: uint16_t pdo_index, /**< Index of the Pdo. */ fp@842: uint16_t entry_index, /**< Index of the Pdo entry to add to the Pdo's fp@879: mapping. */ fp@842: uint8_t entry_subindex, /**< Subindex of the Pdo entry to add to the fp@879: Pdo's mapping. */ fp@842: uint8_t entry_bit_length /**< Size of the Pdo entry in bit. */ fp@842: ); fp@842: fp@879: /** Clear the mapping of a given Pdo. fp@879: * fp@879: * 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@879: uint16_t pdo_index /**< Index of the Pdo. */ fp@879: ); fp@879: fp@1055: /** 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@879: * 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@1055: * The next example shows, how to configure the Pdo assignment only. The fp@879: * entries for each assigned Pdo are taken from the Pdo's default mapping. fp@879: * 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@842: /** Registers a Pdo entry for process data exchange in a domain. fp@842: * fp@925: * 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@925: * respective sync manager's assigned Pdos are appended to the given domain, fp@925: * if not already done. The offset of the requested Pdo entry's data inside fp@925: * 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@925: * 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@842: * \retval >=0 Success: Offset of the Pdo entry's process data. fp@842: * \retval -1 Error: Pdo entry not found. fp@842: * \retval -2 Error: Failed to register Pdo entry. fp@916: * \retval -3 Error: Pdo entry is not byte-aligned. fp@807: */ fp@807: int ecrt_slave_config_reg_pdo_entry( fp@807: ec_slave_config_t *sc, /**< Slave configuration. */ fp@807: uint16_t entry_index, /**< Index of the Pdo entry to register. */ fp@807: 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@893: /** Add an Sdo configuration. fp@893: * fp@893: * 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@1104: * \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@893: * 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@893: * \return 0 in case of success, else < 0 fp@893: */ fp@893: int ecrt_slave_config_sdo( fp@893: ec_slave_config_t *sc, /**< Slave configuration. */ fp@893: uint16_t index, /**< Index of the Sdo to configure. */ fp@893: 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@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@893: * \see ecrt_slave_config_sdo(). 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@893: * \see ecrt_slave_config_sdo(). 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@858: /** Create an Sdo request to exchange Sdos during realtime operation. fp@858: * fp@858: * 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@858: uint16_t index, /**< Sdo index. */ fp@858: uint8_t subindex, /**< Sdo subindex. */ fp@858: size_t size /**< Data size to reserve. */ fp@858: ); fp@858: 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 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@809: /** Provide external memory to store the domain's process data. fp@809: * fp@809: * 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@809: * 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@809: /** Returns the domain's process data. fp@809: * fp@809: * If external memory was provided with ecrt_domain_external_memory(), the fp@809: * returned pointer will contain the address of that memory. Otherwise it will fp@809: * point to the internally allocated memory. fp@809: * 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@858: * Sdo request methods. fp@858: ****************************************************************************/ fp@858: fp@858: /** 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@858: 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@858: /** Access to the Sdo request's data. fp@858: * fp@868: * 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@864: * the internal Sdo data memory could be re-allocated if the read Sdo data do fp@864: * not fit inside. fp@858: * fp@858: * \return Pointer to the internal Sdo data memory. fp@858: */ fp@858: uint8_t *ecrt_sdo_request_data( fp@858: ec_sdo_request_t *req /**< Sdo request. */ fp@858: ); fp@858: fp@869: /** Returns the current Sdo data size. fp@869: * fp@869: * 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@869: * \return Sdo data size in bytes. fp@869: */ fp@869: size_t ecrt_sdo_request_data_size( fp@869: const ec_sdo_request_t *req /**< Sdo request. */ fp@869: ); fp@869: fp@858: /** Get the current state of the Sdo request. fp@858: * fp@858: * \return Request state. fp@858: */ fp@861: ec_sdo_request_state_t ecrt_sdo_request_state( fp@858: const ec_sdo_request_t *req /**< Sdo request. */ fp@858: ); fp@858: fp@858: /** 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@858: ec_sdo_request_t *req /**< Sdo request. */ fp@858: ); fp@858: fp@864: /** 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@858: ec_sdo_request_t *req /**< Sdo request. */ fp@858: ); fp@858: 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@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@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@104: /*****************************************************************************/ fp@104: fp@792: /** @} */ fp@792: fp@104: #endif