3154 lines
108 KiB
C
3154 lines
108 KiB
C
/*****************************************************************************
|
|
*
|
|
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
|
|
*
|
|
* This file is part of the IgH EtherCAT master userspace library.
|
|
*
|
|
* The IgH EtherCAT master userspace library is free software; you can
|
|
* redistribute it and/or modify it under the terms of the GNU Lesser General
|
|
* Public License as published by the Free Software Foundation; version 2.1
|
|
* of the License.
|
|
*
|
|
* The IgH EtherCAT master userspace library is distributed in the hope that
|
|
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with the IgH EtherCAT master userspace library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/** \file
|
|
*
|
|
* EtherCAT master application interface.
|
|
*
|
|
* \defgroup ApplicationInterface EtherCAT Application Interface
|
|
*
|
|
* EtherCAT interface for realtime applications. This interface is designed
|
|
* for realtime modules that want to use EtherCAT. There are functions to
|
|
* request a master, to map process data, to communicate with slaves via CoE
|
|
* and to configure and activate the bus.
|
|
*
|
|
*
|
|
* Changes in version 1.6.0:
|
|
*
|
|
* - Added the ecrt_master_scan_progress() method, the
|
|
* ec_master_scan_progress_t structure and the EC_HAVE_SCAN_PROGRESS
|
|
* definition to check for its existence.
|
|
* - Added the EoE configuration methods ecrt_slave_config_eoe_mac_address(),
|
|
* ecrt_slave_config_eoe_ip_address(), ecrt_slave_config_eoe_subnet_mask(),
|
|
* ecrt_slave_config_eoe_default_gateway(),
|
|
* ecrt_slave_config_eoe_dns_address(),
|
|
* ecrt_slave_config_eoe_hostname() and the EC_HAVE_SET_IP
|
|
* definition to check for its existence.
|
|
* - Added ecrt_slave_config_state_timeout() to set the application-layer
|
|
* state change timeout and EC_HAVE_STATE_TIMEOUT to check for its
|
|
* existence.
|
|
*
|
|
* Changes since version 1.5.2:
|
|
*
|
|
* - Added the ecrt_slave_config_flag() method and the EC_HAVE_FLAGS
|
|
* definition to check for its existence.
|
|
* - Added SoE IDN requests, including the datatype ec_soe_request_t and the
|
|
* methods ecrt_slave_config_create_soe_request(),
|
|
* ecrt_soe_request_object(), ecrt_soe_request_timeout(),
|
|
* ecrt_soe_request_data(), ecrt_soe_request_data_size(),
|
|
* ecrt_soe_request_state(), ecrt_soe_request_write() and
|
|
* ecrt_soe_request_read(). Use the EC_HAVE_SOE_REQUESTS to check, if the
|
|
* functionality is available.
|
|
*
|
|
* Changes in version 1.5.2:
|
|
*
|
|
* - Added redundancy_active flag to ec_domain_state_t.
|
|
* - Added ecrt_master_link_state() method and ec_master_link_state_t to query
|
|
* the state of a redundant link.
|
|
* - Added the EC_HAVE_REDUNDANCY define, to check, if the interface contains
|
|
* redundancy features.
|
|
* - Added ecrt_sdo_request_index() to change SDO index and subindex after
|
|
* request creation.
|
|
* - Added interface for retrieving CoE emergency messages, i. e.
|
|
* ecrt_slave_config_emerg_size(), ecrt_slave_config_emerg_pop(),
|
|
* ecrt_slave_config_emerg_clear(), ecrt_slave_config_emerg_overruns() and
|
|
* the defines EC_HAVE_EMERGENCY and EC_COE_EMERGENCY_MSG_SIZE.
|
|
* - Added interface for direct EtherCAT register access: Added data type
|
|
* ec_reg_request_t and methods ecrt_slave_config_create_reg_request(),
|
|
* ecrt_reg_request_data(), ecrt_reg_request_state(),
|
|
* ecrt_reg_request_write(), ecrt_reg_request_read() and the feature flag
|
|
* EC_HAVE_REG_ACCESS.
|
|
* - Added method to select the reference clock,
|
|
* ecrt_master_select_reference_clock() and the feature flag
|
|
* EC_HAVE_SELECT_REF_CLOCK to check, if the method is available.
|
|
* - Added method to get the reference clock time,
|
|
* ecrt_master_reference_clock_time() and the feature flag
|
|
* EC_HAVE_REF_CLOCK_TIME to have the possibility to synchronize the master
|
|
* clock to the reference clock.
|
|
* - Changed the data types of the shift times in ecrt_slave_config_dc() to
|
|
* int32_t to correctly display negative shift times.
|
|
* - Added ecrt_slave_config_reg_pdo_entry_pos() and the feature flag
|
|
* EC_HAVE_REG_BY_POS for registering PDO entries with non-unique indices
|
|
* via their positions in the mapping.
|
|
*
|
|
* Changes in version 1.5:
|
|
*
|
|
* - Added the distributed clocks feature and the respective method
|
|
* ecrt_slave_config_dc() to configure a slave for cyclic operation, and
|
|
* ecrt_master_application_time(), ecrt_master_sync_reference_clock() and
|
|
* ecrt_master_sync_slave_clocks() for offset and drift compensation. The
|
|
* EC_TIMEVAL2NANO() macro can be used for epoch time conversion, while the
|
|
* ecrt_master_sync_monitor_queue() and ecrt_master_sync_monitor_process()
|
|
* methods can be used to monitor the synchrony.
|
|
* - Improved the callback mechanism. ecrt_master_callbacks() now takes two
|
|
* callback functions for sending and receiving datagrams.
|
|
* ecrt_master_send_ext() is used to execute the sending of non-application
|
|
* datagrams.
|
|
* - Added watchdog configuration (method ecrt_slave_config_watchdog(),
|
|
* #ec_watchdog_mode_t, \a watchdog_mode parameter in ec_sync_info_t and
|
|
* ecrt_slave_config_sync_manager()).
|
|
* - Added ecrt_slave_config_complete_sdo() method to download an SDO during
|
|
* configuration via CompleteAccess.
|
|
* - Added ecrt_master_deactivate() to remove the master configuration.
|
|
* - Added ecrt_open_master() and ecrt_master_reserve() separation for
|
|
* userspace.
|
|
* - Added master information interface (methods ecrt_master(),
|
|
* ecrt_master_get_slave(), ecrt_master_get_sync_manager(),
|
|
* ecrt_master_get_pdo() and ecrt_master_get_pdo_entry()) to get information
|
|
* about the currently connected slaves and the PDO entries provided.
|
|
* - Added ecrt_master_sdo_download(), ecrt_master_sdo_download_complete() and
|
|
* ecrt_master_sdo_upload() methods to let an application transfer SDOs
|
|
* before activating the master.
|
|
* - Changed the meaning of the negative return values of
|
|
* ecrt_slave_config_reg_pdo_entry() and ecrt_slave_config_sdo*().
|
|
* - Implemented the Vendor-specific over EtherCAT mailbox protocol. See
|
|
* ecrt_slave_config_create_voe_handler().
|
|
* - Renamed ec_sdo_request_state_t to #ec_request_state_t, because it is also
|
|
* used by VoE handlers.
|
|
* - Removed 'const' from argument of ecrt_sdo_request_state(), because the
|
|
* userspace library has to modify object internals.
|
|
* - Added 64-bit data access macros.
|
|
* - Added ecrt_slave_config_idn() method for storing SoE IDN configurations,
|
|
* and ecrt_master_read_idn() and ecrt_master_write_idn() to read/write IDNs
|
|
* ad-hoc via the user-space library.
|
|
* - Added ecrt_master_reset() to initiate retrying to configure slaves.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/****************************************************************************/
|
|
|
|
#ifndef __ECRT_H__
|
|
#define __ECRT_H__
|
|
|
|
#ifdef __KERNEL__
|
|
#include <asm/byteorder.h>
|
|
#include <linux/types.h>
|
|
#include <linux/time.h>
|
|
#include <linux/in.h> // struct in_addr
|
|
#else
|
|
#include <stdlib.h> // for size_t
|
|
#include <stdint.h>
|
|
#include <sys/time.h> // for struct timeval
|
|
#include <netinet/in.h> // struct in_addr
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* Global definitions
|
|
****************************************************************************/
|
|
|
|
/** EtherCAT realtime interface major version number.
|
|
*/
|
|
#define ECRT_VER_MAJOR 1
|
|
|
|
/** EtherCAT realtime interface minor version number.
|
|
*/
|
|
#define ECRT_VER_MINOR 6
|
|
|
|
/** EtherCAT realtime interface version word generator.
|
|
*/
|
|
#define ECRT_VERSION(a, b) (((a) << 8) + (b))
|
|
|
|
/** EtherCAT realtime interface version word.
|
|
*/
|
|
#define ECRT_VERSION_MAGIC ECRT_VERSION(ECRT_VER_MAJOR, ECRT_VER_MINOR)
|
|
|
|
/*****************************************************************************
|
|
* Feature flags
|
|
****************************************************************************/
|
|
|
|
/** Defined, if the redundancy features are available.
|
|
*
|
|
* I. e. if the \a redundancy_active flag in ec_domain_state_t and the
|
|
* ecrt_master_link_state() method are available.
|
|
*/
|
|
#define EC_HAVE_REDUNDANCY
|
|
|
|
/** Defined, if the CoE emergency ring feature is available.
|
|
*
|
|
* I. e. if the ecrt_slave_config_emerg_*() methods are available.
|
|
*/
|
|
#define EC_HAVE_EMERGENCY
|
|
|
|
/** Defined, if the register access interface is available.
|
|
*
|
|
* I. e. if the methods ecrt_slave_config_create_reg_request(),
|
|
* ecrt_reg_request_data(), ecrt_reg_request_state(), ecrt_reg_request_write()
|
|
* and ecrt_reg_request_read() are available.
|
|
*/
|
|
#define EC_HAVE_REG_ACCESS
|
|
|
|
/** Defined if the method ecrt_master_select_reference_clock() is available.
|
|
*/
|
|
#define EC_HAVE_SELECT_REF_CLOCK
|
|
|
|
/** Defined if the method ecrt_master_reference_clock_time() is available.
|
|
*/
|
|
#define EC_HAVE_REF_CLOCK_TIME
|
|
|
|
/** Defined if the method ecrt_slave_config_reg_pdo_entry_pos() is available.
|
|
*/
|
|
#define EC_HAVE_REG_BY_POS
|
|
|
|
/** Defined if the method ecrt_master_sync_reference_clock_to() is available.
|
|
*/
|
|
#define EC_HAVE_SYNC_TO
|
|
|
|
/** Defined if the method ecrt_slave_config_flag() is available.
|
|
*/
|
|
#define EC_HAVE_FLAGS
|
|
|
|
/** Defined if the methods ecrt_slave_config_create_soe_request(),
|
|
* ecrt_soe_request_object(), ecrt_soe_request_timeout(),
|
|
* ecrt_soe_request_data(), ecrt_soe_request_data_size(),
|
|
* ecrt_soe_request_state(), ecrt_soe_request_write() and
|
|
* ecrt_soe_request_read() and the datatype ec_soe_request_t are available.
|
|
*/
|
|
#define EC_HAVE_SOE_REQUESTS
|
|
|
|
/** Defined, if the method ecrt_master_scan_progress() and the
|
|
* ec_master_scan_progress_t structure are available.
|
|
*/
|
|
#define EC_HAVE_SCAN_PROGRESS
|
|
|
|
/** Defined, if the methods ecrt_slave_config_eoe_mac_address(),
|
|
* ecrt_slave_config_eoe_ip_address(), ecrt_slave_config_eoe_subnet_mask(),
|
|
* ecrt_slave_config_eoe_default_gateway(),
|
|
* ecrt_slave_config_eoe_dns_address(), ecrt_slave_config_eoe_hostname() are
|
|
* available.
|
|
*/
|
|
#define EC_HAVE_SET_IP
|
|
|
|
/** Defined, if the method ecrt_slave_config_state_timeout() is available.
|
|
*/
|
|
#define EC_HAVE_STATE_TIMEOUT
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Symbol visibility control macro.
|
|
*/
|
|
#ifndef EC_PUBLIC_API
|
|
# if defined(ethercat_EXPORTS) && !defined(__KERNEL__)
|
|
# define EC_PUBLIC_API __attribute__ ((visibility ("default")))
|
|
# else
|
|
# define EC_PUBLIC_API
|
|
# endif
|
|
#endif
|
|
|
|
/****************************************************************************/
|
|
|
|
/** End of list marker.
|
|
*
|
|
* This can be used with ecrt_slave_config_pdos().
|
|
*/
|
|
#define EC_END ~0U
|
|
|
|
/** Maximum number of sync managers per slave.
|
|
*/
|
|
#define EC_MAX_SYNC_MANAGERS 16
|
|
|
|
/** Maximum string length.
|
|
*
|
|
* Used in ec_slave_info_t.
|
|
*/
|
|
#define EC_MAX_STRING_LENGTH 64
|
|
|
|
/** Maximum number of slave ports. */
|
|
#define EC_MAX_PORTS 4
|
|
|
|
/** Timeval to nanoseconds conversion.
|
|
*
|
|
* This macro converts a Unix epoch time to EtherCAT DC time.
|
|
*
|
|
* \see void ecrt_master_application_time()
|
|
*
|
|
* \param TV struct timeval containing epoch time.
|
|
*/
|
|
#define EC_TIMEVAL2NANO(TV) \
|
|
(((TV).tv_sec - 946684800ULL) * 1000000000ULL + (TV).tv_usec * 1000ULL)
|
|
|
|
/** Size of a CoE emergency message in byte.
|
|
*
|
|
* \see ecrt_slave_config_emerg_pop().
|
|
*/
|
|
#define EC_COE_EMERGENCY_MSG_SIZE 8
|
|
|
|
/*****************************************************************************
|
|
* Data types
|
|
****************************************************************************/
|
|
|
|
struct ec_master;
|
|
typedef struct ec_master ec_master_t; /**< \see ec_master */
|
|
|
|
struct ec_slave_config;
|
|
typedef struct ec_slave_config ec_slave_config_t; /**< \see ec_slave_config */
|
|
|
|
struct ec_domain;
|
|
typedef struct ec_domain ec_domain_t; /**< \see ec_domain */
|
|
|
|
struct ec_sdo_request;
|
|
typedef struct ec_sdo_request ec_sdo_request_t; /**< \see ec_sdo_request. */
|
|
|
|
struct ec_soe_request;
|
|
typedef struct ec_soe_request ec_soe_request_t; /**< \see ec_soe_request. */
|
|
|
|
struct ec_voe_handler;
|
|
typedef struct ec_voe_handler ec_voe_handler_t; /**< \see ec_voe_handler. */
|
|
|
|
struct ec_reg_request;
|
|
typedef struct ec_reg_request ec_reg_request_t; /**< \see ec_reg_request. */
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Master state.
|
|
*
|
|
* This is used for the output parameter of ecrt_master_state().
|
|
*
|
|
* \see ecrt_master_state().
|
|
*/
|
|
typedef struct {
|
|
unsigned int slaves_responding; /**< Sum of responding slaves on all
|
|
Ethernet devices. */
|
|
unsigned int al_states : 4; /**< Application-layer states of all slaves.
|
|
The states are coded in the lower 4 bits.
|
|
If a bit is set, it means that at least one
|
|
slave in the network is in the corresponding
|
|
state:
|
|
- Bit 0: \a INIT
|
|
- Bit 1: \a PREOP
|
|
- Bit 2: \a SAFEOP
|
|
- Bit 3: \a OP */
|
|
unsigned int link_up : 1; /**< \a true, if at least one Ethernet link is
|
|
up. */
|
|
} ec_master_state_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Redundant link state.
|
|
*
|
|
* This is used for the output parameter of ecrt_master_link_state().
|
|
*
|
|
* \see ecrt_master_link_state().
|
|
*/
|
|
typedef struct {
|
|
unsigned int slaves_responding; /**< Sum of responding slaves on the given
|
|
link. */
|
|
unsigned int al_states : 4; /**< Application-layer states of the slaves on
|
|
the given link. The states are coded in the
|
|
lower 4 bits. If a bit is set, it means
|
|
that at least one slave in the network is in
|
|
the corresponding state:
|
|
- Bit 0: \a INIT
|
|
- Bit 1: \a PREOP
|
|
- Bit 2: \a SAFEOP
|
|
- Bit 3: \a OP */
|
|
unsigned int link_up : 1; /**< \a true, if the given Ethernet link is up.
|
|
*/
|
|
} ec_master_link_state_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Slave configuration state.
|
|
*
|
|
* This is used as an output parameter of ecrt_slave_config_state().
|
|
*
|
|
* \see ecrt_slave_config_state().
|
|
*/
|
|
typedef struct {
|
|
unsigned int online : 1; /**< The slave is online. */
|
|
unsigned int operational : 1; /**< The slave was brought into \a OP state
|
|
using the specified configuration. */
|
|
unsigned int al_state : 4; /**< The application-layer state of the slave.
|
|
- 1: \a INIT
|
|
- 2: \a PREOP
|
|
- 4: \a SAFEOP
|
|
- 8: \a OP
|
|
|
|
Note that each state is coded in a different
|
|
bit! */
|
|
} ec_slave_config_state_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Master information.
|
|
*
|
|
* This is used as an output parameter of ecrt_master().
|
|
*
|
|
* \see ecrt_master().
|
|
*/
|
|
typedef struct {
|
|
unsigned int slave_count; /**< Number of slaves in the network. */
|
|
unsigned int link_up : 1; /**< \a true, if the network link is up. */
|
|
uint8_t scan_busy; /**< \a true, while the master is scanning the network.
|
|
*/
|
|
uint64_t app_time; /**< Application time. */
|
|
} ec_master_info_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Master scan progress information.
|
|
*
|
|
* This is used as an output parameter of ecrt_master_scan_progress().
|
|
*
|
|
* \see ecrt_master_scan_progress().
|
|
*/
|
|
typedef struct {
|
|
unsigned int slave_count; /**< Number of slaves detected. */
|
|
unsigned int scan_index; /**< Index of the slave that is currently
|
|
scanned. If it is less than the \a
|
|
slave_count, the network scan is in progress.
|
|
*/
|
|
} ec_master_scan_progress_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** EtherCAT slave port descriptor.
|
|
*/
|
|
typedef enum {
|
|
EC_PORT_NOT_IMPLEMENTED, /**< Port is not implemented. */
|
|
EC_PORT_NOT_CONFIGURED, /**< Port is not configured. */
|
|
EC_PORT_EBUS, /**< Port is an E-Bus. */
|
|
EC_PORT_MII /**< Port is a MII. */
|
|
} ec_slave_port_desc_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** EtherCAT slave port information.
|
|
*/
|
|
typedef struct {
|
|
uint8_t link_up; /**< Link detected. */
|
|
uint8_t loop_closed; /**< Loop closed. */
|
|
uint8_t signal_detected; /**< Detected signal on RX port. */
|
|
} ec_slave_port_link_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Slave information.
|
|
*
|
|
* This is used as an output parameter of ecrt_master_get_slave().
|
|
*
|
|
* \see ecrt_master_get_slave().
|
|
*/
|
|
typedef struct {
|
|
uint16_t position; /**< Offset of the slave in the ring. */
|
|
uint32_t vendor_id; /**< Vendor-ID stored on the slave. */
|
|
uint32_t product_code; /**< Product-Code stored on the slave. */
|
|
uint32_t revision_number; /**< Revision-Number stored on the slave. */
|
|
uint32_t serial_number; /**< Serial-Number stored on the slave. */
|
|
uint16_t alias; /**< The slaves alias if not equal to 0. */
|
|
int16_t current_on_ebus; /**< Used current in mA. */
|
|
struct {
|
|
ec_slave_port_desc_t desc; /**< Physical port type. */
|
|
ec_slave_port_link_t link; /**< Port link state. */
|
|
uint32_t receive_time; /**< Receive time on DC transmission delay
|
|
measurement. */
|
|
uint16_t next_slave; /**< Ring position of next DC slave on that
|
|
port. */
|
|
uint32_t delay_to_next_dc; /**< Delay [ns] to next DC slave. */
|
|
} ports[EC_MAX_PORTS]; /**< Port information. */
|
|
uint8_t al_state; /**< Current state of the slave. */
|
|
uint8_t error_flag; /**< Error flag for that slave. */
|
|
uint8_t sync_count; /**< Number of sync managers. */
|
|
uint16_t sdo_count; /**< Number of SDOs. */
|
|
char name[EC_MAX_STRING_LENGTH]; /**< Name of the slave. */
|
|
} ec_slave_info_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Domain working counter interpretation.
|
|
*
|
|
* This is used in ec_domain_state_t.
|
|
*/
|
|
typedef enum {
|
|
EC_WC_ZERO = 0, /**< No registered process data were exchanged. */
|
|
EC_WC_INCOMPLETE, /**< Some of the registered process data were
|
|
exchanged. */
|
|
EC_WC_COMPLETE /**< All registered process data were exchanged. */
|
|
} ec_wc_state_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Domain state.
|
|
*
|
|
* This is used for the output parameter of ecrt_domain_state().
|
|
*/
|
|
typedef struct {
|
|
unsigned int working_counter; /**< Value of the last working counter. */
|
|
ec_wc_state_t wc_state; /**< Working counter interpretation. */
|
|
unsigned int redundancy_active; /**< Redundant link is in use. */
|
|
} ec_domain_state_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Direction type for PDO assignment functions.
|
|
*/
|
|
typedef enum {
|
|
EC_DIR_INVALID, /**< Invalid direction. Do not use this value. */
|
|
EC_DIR_OUTPUT, /**< Values written by the master. */
|
|
EC_DIR_INPUT, /**< Values read by the master. */
|
|
EC_DIR_COUNT /**< Number of directions. For internal use only. */
|
|
} ec_direction_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Watchdog mode for sync manager configuration.
|
|
*
|
|
* Used to specify, if a sync manager's watchdog is to be enabled.
|
|
*/
|
|
typedef enum {
|
|
EC_WD_DEFAULT, /**< Use the default setting of the sync manager. */
|
|
EC_WD_ENABLE, /**< Enable the watchdog. */
|
|
EC_WD_DISABLE, /**< Disable the watchdog. */
|
|
} ec_watchdog_mode_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** PDO entry configuration information.
|
|
*
|
|
* This is the data type of the \a entries field in ec_pdo_info_t.
|
|
*
|
|
* \see ecrt_slave_config_pdos().
|
|
*/
|
|
typedef struct {
|
|
uint16_t index; /**< PDO entry index. */
|
|
uint8_t subindex; /**< PDO entry subindex. */
|
|
uint8_t bit_length; /**< Size of the PDO entry in bit. */
|
|
} ec_pdo_entry_info_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** PDO configuration information.
|
|
*
|
|
* This is the data type of the \a pdos field in ec_sync_info_t.
|
|
*
|
|
* \see ecrt_slave_config_pdos().
|
|
*/
|
|
typedef struct {
|
|
uint16_t index; /**< PDO index. */
|
|
unsigned int n_entries; /**< Number of PDO entries in \a entries to map.
|
|
Zero means, that the default mapping shall be
|
|
used (this can only be done if the slave is
|
|
present at configuration time). */
|
|
ec_pdo_entry_info_t const *entries; /**< Array of PDO entries to map. Can
|
|
either be \a NULL, or must contain
|
|
at least \a n_entries values. */
|
|
} ec_pdo_info_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Sync manager configuration information.
|
|
*
|
|
* This can be use to configure multiple sync managers including the PDO
|
|
* assignment and PDO mapping. It is used as an input parameter type in
|
|
* ecrt_slave_config_pdos().
|
|
*/
|
|
typedef struct {
|
|
uint8_t index; /**< Sync manager index. Must be less
|
|
than #EC_MAX_SYNC_MANAGERS for a valid sync manager,
|
|
but can also be \a 0xff to mark the end of the list. */
|
|
ec_direction_t dir; /**< Sync manager direction. */
|
|
unsigned int n_pdos; /**< Number of PDOs in \a pdos. */
|
|
ec_pdo_info_t const *pdos; /**< Array with PDOs to assign. This must
|
|
contain at least \a n_pdos PDOs. */
|
|
ec_watchdog_mode_t watchdog_mode; /**< Watchdog mode. */
|
|
} ec_sync_info_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** List record type for PDO entry mass-registration.
|
|
*
|
|
* This type is used for the array parameter of the
|
|
* ecrt_domain_reg_pdo_entry_list()
|
|
*/
|
|
typedef struct {
|
|
uint16_t alias; /**< Slave alias address. */
|
|
uint16_t position; /**< Slave position. */
|
|
uint32_t vendor_id; /**< Slave vendor ID. */
|
|
uint32_t product_code; /**< Slave product code. */
|
|
uint16_t index; /**< PDO entry index. */
|
|
uint8_t subindex; /**< PDO entry subindex. */
|
|
unsigned int *offset; /**< Pointer to a variable to store the PDO entry's
|
|
(byte-)offset in the process data. */
|
|
unsigned int *bit_position; /**< Pointer to a variable to store a bit
|
|
position (0-7) within the \a offset. Can be
|
|
NULL, in which case an error is raised if
|
|
the PDO entry does not byte-align. */
|
|
} ec_pdo_entry_reg_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Request state.
|
|
*
|
|
* This is used as return type for ecrt_sdo_request_state() and
|
|
* ecrt_voe_handler_state().
|
|
*/
|
|
typedef enum {
|
|
EC_REQUEST_UNUSED, /**< Not requested. */
|
|
EC_REQUEST_BUSY, /**< Request is being processed. */
|
|
EC_REQUEST_SUCCESS, /**< Request was processed successfully. */
|
|
EC_REQUEST_ERROR, /**< Request processing failed. */
|
|
} ec_request_state_t;
|
|
|
|
/****************************************************************************/
|
|
|
|
/** Application-layer state.
|
|
*/
|
|
typedef enum {
|
|
EC_AL_STATE_INIT = 1, /**< Init. */
|
|
EC_AL_STATE_PREOP = 2, /**< Pre-operational. */
|
|
EC_AL_STATE_SAFEOP = 4, /**< Safe-operational. */
|
|
EC_AL_STATE_OP = 8, /**< Operational. */
|
|
} ec_al_state_t;
|
|
|
|
/*****************************************************************************
|
|
* Global functions
|
|
****************************************************************************/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** Returns the version magic of the realtime interface.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return Value of ECRT_VERSION_MAGIC() at EtherCAT master compile time.
|
|
*/
|
|
EC_PUBLIC_API unsigned int ecrt_version_magic(void);
|
|
|
|
/** Requests an EtherCAT master for realtime operation.
|
|
*
|
|
* Before an application can access an EtherCAT master, it has to reserve one
|
|
* for exclusive use.
|
|
*
|
|
* In userspace, this is a convenience function for ecrt_open_master() and
|
|
* ecrt_master_reserve().
|
|
*
|
|
* This function has to be the first function an application has to call to
|
|
* use EtherCAT. The function takes the index of the master as its argument.
|
|
* The first master has index 0, the n-th master has index n - 1. The number
|
|
* of masters has to be specified when loading the master module.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return Pointer to the reserved master, otherwise \a NULL.
|
|
*/
|
|
EC_PUBLIC_API ec_master_t *ecrt_request_master(
|
|
unsigned int master_index /**< Index of the master to request. */
|
|
);
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
/** Opens an EtherCAT master for userspace access.
|
|
*
|
|
* This function has to be the first function an application has to call to
|
|
* use EtherCAT. The function takes the index of the master as its argument.
|
|
* The first master has index 0, the n-th master has index n - 1. The number
|
|
* of masters has to be specified when loading the master module.
|
|
*
|
|
* For convenience, the function ecrt_request_master() can be used.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return Pointer to the opened master, otherwise \a NULL.
|
|
*/
|
|
EC_PUBLIC_API ec_master_t *ecrt_open_master(
|
|
unsigned int master_index /**< Index of the master to request. */
|
|
);
|
|
|
|
#endif // #ifndef __KERNEL__
|
|
|
|
/** Releases a requested EtherCAT master.
|
|
*
|
|
* After use, a master it has to be released to make it available for other
|
|
* applications.
|
|
*
|
|
* This method frees all created data structures. It should not be called in
|
|
* realtime context.
|
|
*
|
|
* If the master was activated, ecrt_master_deactivate() is called internally.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*/
|
|
EC_PUBLIC_API void ecrt_release_master(
|
|
ec_master_t *master /**< EtherCAT master */
|
|
);
|
|
|
|
/*****************************************************************************
|
|
* Master methods
|
|
****************************************************************************/
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
/** Reserves an EtherCAT master for realtime operation.
|
|
*
|
|
* Before an application can use PDO/domain registration functions or SDO
|
|
* request functions on the master, it has to reserve one for exclusive use.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return 0 in case of success, else < 0
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_reserve(
|
|
ec_master_t *master /**< EtherCAT master */
|
|
);
|
|
|
|
#endif // #ifndef __KERNEL__
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
/** Sets the locking callbacks.
|
|
*
|
|
* For concurrent master access, i. e. if other instances than the application
|
|
* want to send and receive datagrams on the network, the application has to
|
|
* provide a callback mechanism. This method takes two function pointers as
|
|
* its parameters. Asynchronous master access (like EoE processing) is only
|
|
* possible if the callbacks have been set.
|
|
*
|
|
* The task of the send callback (\a send_cb) is to decide, if the network
|
|
* hardware is currently accessible and whether or not to call the
|
|
* ecrt_master_send_ext() method.
|
|
*
|
|
* The task of the receive callback (\a receive_cb) is to decide, if a call to
|
|
* ecrt_master_receive() is allowed and to execute it respectively.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \attention This method has to be called before ecrt_master_activate().
|
|
*/
|
|
void ecrt_master_callbacks(
|
|
ec_master_t *master, /**< EtherCAT master */
|
|
void (*send_cb)(void *), /**< Datagram sending callback. */
|
|
void (*receive_cb)(void *), /**< Receive callback. */
|
|
void *cb_data /**< Arbitrary pointer passed to the callback functions.
|
|
*/
|
|
);
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
/** Creates a new process data domain.
|
|
*
|
|
* For process data exchange, at least one process data domain is needed.
|
|
* This method creates a new process data domain and returns a pointer to the
|
|
* new domain object. This object can be used for registering PDOs and
|
|
* exchanging them in cyclic operation.
|
|
*
|
|
* This method allocates memory and should be called in non-realtime context
|
|
* before ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return Pointer to the new domain on success, else NULL.
|
|
*/
|
|
EC_PUBLIC_API ec_domain_t *ecrt_master_create_domain(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/** Obtains a slave configuration.
|
|
*
|
|
* Creates a slave configuration object for the given \a alias and \a position
|
|
* tuple and returns it. If a configuration with the same \a alias and \a
|
|
* position already exists, it will be re-used. In the latter case, the given
|
|
* vendor ID and product code are compared to the stored ones. On mismatch, an
|
|
* error message is raised and the function returns \a NULL.
|
|
*
|
|
* Slaves are addressed with the \a alias and \a position parameters.
|
|
* - If \a alias is zero, \a position is interpreted as the desired slave's
|
|
* ring position.
|
|
* - If \a alias is non-zero, it matches a slave with the given alias. In this
|
|
* case, \a position is interpreted as ring offset, starting from the
|
|
* aliased slave, so a position of zero means the aliased slave itself and a
|
|
* positive value matches the n-th slave behind the aliased one.
|
|
*
|
|
* If the slave with the given address is found during the configuration,
|
|
* its vendor ID and product code are matched against the given value. On
|
|
* mismatch, the slave is not configured and an error message is raised.
|
|
*
|
|
* If different slave configurations are pointing to the same slave during
|
|
* configuration, a warning is raised and only the first configuration is
|
|
* applied.
|
|
*
|
|
* This method allocates memory and should be called in non-realtime context
|
|
* before ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval >0 Pointer to the slave configuration structure.
|
|
* \retval NULL in the error case.
|
|
*/
|
|
EC_PUBLIC_API ec_slave_config_t *ecrt_master_slave_config(
|
|
ec_master_t *master, /**< EtherCAT master */
|
|
uint16_t alias, /**< Slave alias. */
|
|
uint16_t position, /**< Slave position. */
|
|
uint32_t vendor_id, /**< Expected vendor ID. */
|
|
uint32_t product_code /**< Expected product code. */
|
|
);
|
|
|
|
/** Selects the reference clock for distributed clocks.
|
|
*
|
|
* If this method is not called for a certain master, or if the slave
|
|
* configuration pointer is NULL, then the first slave with DC functionality
|
|
* will provide the reference clock.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_select_reference_clock(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
ec_slave_config_t *sc /**< Slave config of the slave to use as the
|
|
* reference slave (or NULL). */
|
|
);
|
|
|
|
/** Obtains master information.
|
|
*
|
|
* No memory is allocated on the heap in this function.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \attention The pointer to this structure must point to a valid variable.
|
|
*
|
|
* \return 0 in case of success, else < 0
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master(
|
|
ec_master_t *master, /**< EtherCAT master */
|
|
ec_master_info_t *master_info /**< Structure that will output the
|
|
information */
|
|
);
|
|
|
|
/** Obtains network scan progress information.
|
|
*
|
|
* No memory is allocated on the heap in this function.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \attention The pointer to this structure must point to a valid variable.
|
|
*
|
|
* \return 0 in case of success, else < 0
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_scan_progress(
|
|
ec_master_t *master, /**< EtherCAT master */
|
|
ec_master_scan_progress_t *progress /**< Structure that will output
|
|
the progress information. */
|
|
);
|
|
|
|
/** Obtains slave information.
|
|
*
|
|
* Tries to find the slave with the given ring position. The obtained
|
|
* information is stored in a structure. No memory is allocated on the heap in
|
|
* this function.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \attention The pointer to this structure must point to a valid variable.
|
|
*
|
|
* \return 0 in case of success, else < 0
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_get_slave(
|
|
ec_master_t *master, /**< EtherCAT master */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
ec_slave_info_t *slave_info /**< Structure that will output the
|
|
information */
|
|
);
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
/** Returns the proposed configuration of a slave's sync manager.
|
|
*
|
|
* Fills a given ec_sync_info_t structure with the attributes of a sync
|
|
* manager. The \a pdos field of the return value is left empty. Use
|
|
* ecrt_master_get_pdo() to get the PDO information.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \return zero on success, else non-zero
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_get_sync_manager(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
uint8_t sync_index, /**< Sync manager index. Must be less
|
|
than #EC_MAX_SYNC_MANAGERS. */
|
|
ec_sync_info_t *sync /**< Pointer to output structure. */
|
|
);
|
|
|
|
/** Returns information about a currently assigned PDO.
|
|
*
|
|
* Fills a given ec_pdo_info_t structure with the attributes of a currently
|
|
* assigned PDO of the given sync manager. The \a entries field of the return
|
|
* value is left empty. Use ecrt_master_get_pdo_entry() to get the PDO
|
|
* entry information.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \retval zero on success, else non-zero
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_get_pdo(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
uint8_t sync_index, /**< Sync manager index. Must be less
|
|
than #EC_MAX_SYNC_MANAGERS. */
|
|
uint16_t pos, /**< Zero-based PDO position. */
|
|
ec_pdo_info_t *pdo /**< Pointer to output structure. */
|
|
);
|
|
|
|
/** Returns information about a currently mapped PDO entry.
|
|
*
|
|
* Fills a given ec_pdo_entry_info_t structure with the attributes of a
|
|
* currently mapped PDO entry of the given PDO.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \retval zero on success, else non-zero
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_get_pdo_entry(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
uint8_t sync_index, /**< Sync manager index. Must be less
|
|
than #EC_MAX_SYNC_MANAGERS. */
|
|
uint16_t pdo_pos, /**< Zero-based PDO position. */
|
|
uint16_t entry_pos, /**< Zero-based PDO entry position. */
|
|
ec_pdo_entry_info_t *entry /**< Pointer to output structure. */
|
|
);
|
|
|
|
#endif /* #ifndef __KERNEL__ */
|
|
|
|
/** Executes an SDO download request to write data to a slave.
|
|
*
|
|
* This request is processed by the master state machine. This method blocks,
|
|
* until the request has been processed and may not be called in realtime
|
|
* context.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_sdo_download(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
uint16_t index, /**< Index of the SDO. */
|
|
uint8_t subindex, /**< Subindex of the SDO. */
|
|
const uint8_t *data, /**< Data buffer to download. */
|
|
size_t data_size, /**< Size of the data buffer. */
|
|
uint32_t *abort_code /**< Abort code of the SDO download. */
|
|
);
|
|
|
|
/** Executes an SDO download request to write data to a slave via complete
|
|
* access.
|
|
*
|
|
* This request is processed by the master state machine. This method blocks,
|
|
* until the request has been processed and may not be called in realtime
|
|
* context.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_sdo_download_complete(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
uint16_t index, /**< Index of the SDO. */
|
|
const uint8_t *data, /**< Data buffer to download. */
|
|
size_t data_size, /**< Size of the data buffer. */
|
|
uint32_t *abort_code /**< Abort code of the SDO download. */
|
|
);
|
|
|
|
/** Executes an SDO upload request to read data from a slave.
|
|
*
|
|
* This request is processed by the master state machine. This method blocks,
|
|
* until the request has been processed and may not be called in realtime
|
|
* context.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_sdo_upload(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
uint16_t index, /**< Index of the SDO. */
|
|
uint8_t subindex, /**< Subindex of the SDO. */
|
|
uint8_t *target, /**< Target buffer for the upload. */
|
|
size_t target_size, /**< Size of the target buffer. */
|
|
size_t *result_size, /**< Uploaded data size. */
|
|
uint32_t *abort_code /**< Abort code of the SDO upload. */
|
|
);
|
|
|
|
/** Executes an SoE write request.
|
|
*
|
|
* Starts writing an IDN and blocks until the request was processed, or an
|
|
* error occurred.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_write_idn(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
uint8_t drive_no, /**< Drive number. */
|
|
uint16_t idn, /**< SoE IDN (see ecrt_slave_config_idn()). */
|
|
const uint8_t *data, /**< Pointer to data to write. */
|
|
size_t data_size, /**< Size of data to write. */
|
|
uint16_t *error_code /**< Pointer to variable, where an SoE error code
|
|
can be stored. */
|
|
);
|
|
|
|
/** Executes an SoE read request.
|
|
*
|
|
* Starts reading an IDN and blocks until the request was processed, or an
|
|
* error occurred.
|
|
*
|
|
* \apiusage{master_any,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_read_idn(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint16_t slave_position, /**< Slave position. */
|
|
uint8_t drive_no, /**< Drive number. */
|
|
uint16_t idn, /**< SoE IDN (see ecrt_slave_config_idn()). */
|
|
uint8_t *target, /**< Pointer to memory where the read data can be
|
|
stored. */
|
|
size_t target_size, /**< Size of the memory \a target points to. */
|
|
size_t *result_size, /**< Actual size of the received data. */
|
|
uint16_t *error_code /**< Pointer to variable, where an SoE error code
|
|
can be stored. */
|
|
);
|
|
|
|
/** Finishes the configuration phase and prepares for cyclic operation.
|
|
*
|
|
* This function tells the master that the configuration phase is finished and
|
|
* the realtime operation will begin. The function allocates internal memory
|
|
* for the domains and calculates the logical FMMU addresses for domain
|
|
* members. It tells the master state machine that the configuration is
|
|
* now to be applied to the network.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \attention After this function has been called, the realtime application is
|
|
* in charge of cyclically calling ecrt_master_send() and
|
|
* ecrt_master_receive() to ensure network communication. Before calling this
|
|
* function, the master thread is responsible for that, so these functions may
|
|
* not be called! The method itself allocates memory and should not be called
|
|
* in realtime context.
|
|
*
|
|
* \return 0 in case of success, else < 0
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_activate(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/** Deactivates the master.
|
|
*
|
|
* Removes the master configuration. All objects created by
|
|
* ecrt_master_create_domain(), ecrt_master_slave_config(), ecrt_domain_data()
|
|
* ecrt_slave_config_create_sdo_request() and
|
|
* ecrt_slave_config_create_voe_handler() are freed, so pointers to them
|
|
* become invalid.
|
|
*
|
|
* \apiusage{master_op,blocking}
|
|
*
|
|
* This method should not be called in realtime context.
|
|
* \return 0 on success, otherwise negative error code.
|
|
* \retval 0 Success.
|
|
* \retval -EINVAL Master has not been activated before.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_deactivate(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/** Set interval between calls to ecrt_master_send().
|
|
*
|
|
* This information helps the master to decide, how much data can be appended
|
|
* to a frame by the master state machine. When the master is configured with
|
|
* --enable-hrtimers, this is used to calculate the scheduling of the master
|
|
* thread.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 on success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_set_send_interval(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
size_t send_interval /**< Send interval in us */
|
|
);
|
|
|
|
/** Sends all datagrams in the queue.
|
|
*
|
|
* This method takes all datagrams, that have been queued for transmission,
|
|
* puts them into frames, and passes them to the Ethernet device for sending.
|
|
*
|
|
* Has to be called cyclically by the application after ecrt_master_activate()
|
|
* has returned.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_send(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/** Fetches received frames from the hardware and processes the datagrams.
|
|
*
|
|
* Queries the network device for received frames by calling the interrupt
|
|
* service routine. Extracts received datagrams and dispatches the results to
|
|
* the datagram objects in the queue. Received datagrams, and the ones that
|
|
* timed out, will be marked, and dequeued.
|
|
*
|
|
* Has to be called cyclically by the realtime application after
|
|
* ecrt_master_activate() has returned.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_receive(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
#ifdef __KERNEL__
|
|
/** Sends non-application datagrams.
|
|
*
|
|
* This method has to be called in the send callback function passed via
|
|
* ecrt_master_callbacks() to allow the sending of non-application datagrams.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise negative error code.
|
|
* \retval -EAGAIN Lock could not be acquired, try again later.
|
|
*/
|
|
int ecrt_master_send_ext(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
#endif
|
|
|
|
/** Reads the current master state.
|
|
*
|
|
* Stores the master state information in the given \a state structure.
|
|
*
|
|
* This method returns a global state. For the link-specific states in a
|
|
* redundant network topology, use the ecrt_master_link_state() method.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_state(
|
|
const ec_master_t *master, /**< EtherCAT master. */
|
|
ec_master_state_t *state /**< Structure to store the information. */
|
|
);
|
|
|
|
/** Reads the current state of a redundant link.
|
|
*
|
|
* Stores the link state information in the given \a state structure.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_link_state(
|
|
const ec_master_t *master, /**< EtherCAT master. */
|
|
unsigned int dev_idx, /**< Index of the device (0 = main device, 1 =
|
|
first backup device, ...). */
|
|
ec_master_link_state_t *state /**< Structure to store the information.
|
|
*/
|
|
);
|
|
|
|
/** Sets the application time.
|
|
*
|
|
* The master has to know the application's time when operating slaves with
|
|
* distributed clocks. The time is not incremented by the master itself, so
|
|
* this method has to be called cyclically.
|
|
*
|
|
* \attention The time passed to this method is used to calculate the phase of
|
|
* the slaves' SYNC0/1 interrupts. It should be called constantly at the same
|
|
* point of the realtime cycle. So it is recommended to call it at the start
|
|
* of the calculations to avoid deviancies due to changing execution times.
|
|
* Avoid calling this method before the realtime cycle is established.
|
|
*
|
|
* The time is used when setting the slaves' <tt>System Time Offset</tt> and
|
|
* <tt>Cyclic Operation Start Time</tt> registers and when synchronizing the
|
|
* DC reference clock to the application time via
|
|
* ecrt_master_sync_reference_clock().
|
|
*
|
|
* The time is defined as nanoseconds from 2000-01-01 00:00. Converting an
|
|
* epoch time can be done with the EC_TIMEVAL2NANO() macro, but is not
|
|
* necessary, since the absolute value is not of any interest.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_application_time(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint64_t app_time /**< Application time. */
|
|
);
|
|
|
|
/** Queues the DC reference clock drift compensation datagram for sending.
|
|
*
|
|
* The reference clock will by synchronized to the application time provided
|
|
* by the last call off ecrt_master_application_time().
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise negative error code.
|
|
* \retval 0 Success.
|
|
* \retval -ENXIO No reference clock found.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_sync_reference_clock(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/** Queues the DC reference clock drift compensation datagram for sending.
|
|
*
|
|
* The reference clock will by synchronized to the time passed in the
|
|
* sync_time parameter.
|
|
*
|
|
* Has to be called by the application after ecrt_master_activate()
|
|
* has returned.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise negative error code.
|
|
* \retval 0 Success.
|
|
* \retval -ENXIO No reference clock found.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_sync_reference_clock_to(
|
|
ec_master_t *master, /**< EtherCAT master. */
|
|
uint64_t sync_time /**< Sync reference clock to this time. */
|
|
);
|
|
|
|
/** Queues the DC clock drift compensation datagram for sending.
|
|
*
|
|
* All slave clocks synchronized to the reference clock.
|
|
*
|
|
* Has to be called by the application after ecrt_master_activate()
|
|
* has returned.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
* \retval 0 Success.
|
|
* \retval -ENXIO No reference clock found.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_sync_slave_clocks(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/** Get the lower 32 bit of the reference clock system time.
|
|
*
|
|
* This method can be used to synchronize the master to the reference clock.
|
|
*
|
|
* The reference clock system time is queried via the
|
|
* ecrt_master_sync_slave_clocks() method, that reads the system time of the
|
|
* reference clock and writes it to the slave clocks (so be sure to call it
|
|
* cyclically to get valid data).
|
|
*
|
|
* \attention The returned time is the system time of the reference clock
|
|
* minus the transmission delay of the reference clock.
|
|
*
|
|
* Calling this method makes only sense in realtime context (after master
|
|
* activation), when the ecrt_master_sync_slave_clocks() method is called
|
|
* cyclically.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \retval 0 success, system time was written into \a time.
|
|
* \retval -ENXIO No reference clock found.
|
|
* \retval -EIO Slave synchronization datagram was not received.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_reference_clock_time(
|
|
const ec_master_t *master, /**< EtherCAT master. */
|
|
uint32_t *time /**< Pointer to store the queried system time. */
|
|
);
|
|
|
|
/** Queues the DC synchrony monitoring datagram for sending.
|
|
*
|
|
* The datagram broadcast-reads all "System time difference" registers (\a
|
|
* 0x092c) to get an upper estimation of the DC synchrony. The result can be
|
|
* checked with the ecrt_master_sync_monitor_process() method.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Zero on success, otherwise a negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_sync_monitor_queue(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/** Processes the DC synchrony monitoring datagram.
|
|
*
|
|
* If the sync monitoring datagram was sent before with
|
|
* ecrt_master_sync_monitor_queue(), the result can be queried with this
|
|
* method.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Upper estimation of the maximum time difference in ns, -1 on error.
|
|
* \retval (uint32_t)-1 Error.
|
|
*/
|
|
EC_PUBLIC_API uint32_t ecrt_master_sync_monitor_process(
|
|
const ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/** Retry configuring slaves.
|
|
*
|
|
* Via this method, the application can tell the master to bring all slaves to
|
|
* OP state. In general, this is not necessary, because it is automatically
|
|
* done by the master. But with special slaves, that can be reconfigured by
|
|
* the vendor during runtime, it can be useful.
|
|
*
|
|
* Calling this method only makes sense in realtime context (after
|
|
* activation), because slaves will not be configured before.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_master_reset(
|
|
ec_master_t *master /**< EtherCAT master. */
|
|
);
|
|
|
|
/*****************************************************************************
|
|
* Slave configuration methods
|
|
****************************************************************************/
|
|
|
|
/** Configure a sync manager.
|
|
*
|
|
* Sets the direction of a sync manager. This overrides the direction bits
|
|
* from the default control register from SII.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return zero on success, else non-zero
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_sync_manager(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint8_t sync_index, /**< Sync manager index. Must be less
|
|
than #EC_MAX_SYNC_MANAGERS. */
|
|
ec_direction_t direction, /**< Input/Output. */
|
|
ec_watchdog_mode_t watchdog_mode /** Watchdog mode. */
|
|
);
|
|
|
|
/** Configure a slave's watchdog times.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_watchdog(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint16_t watchdog_divider, /**< Number of 40 ns intervals (register
|
|
0x0400). Used as a base unit for all
|
|
slave watchdogs^. If set to zero, the
|
|
value is not written, so the default is
|
|
used. */
|
|
uint16_t watchdog_intervals /**< Number of base intervals for sync
|
|
manager watchdog (register 0x0420). If
|
|
set to zero, the value is not written,
|
|
so the default is used. */
|
|
);
|
|
|
|
/** Add a PDO to a sync manager's PDO assignment.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \see ecrt_slave_config_pdos()
|
|
* \return zero on success, else non-zero
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_pdo_assign_add(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint8_t sync_index, /**< Sync manager index. Must be less
|
|
than #EC_MAX_SYNC_MANAGERS. */
|
|
uint16_t index /**< Index of the PDO to assign. */
|
|
);
|
|
|
|
/** Clear a sync manager's PDO assignment.
|
|
*
|
|
* This can be called before assigning PDOs via
|
|
* ecrt_slave_config_pdo_assign_add(), to clear the default assignment of a
|
|
* sync manager.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \see ecrt_slave_config_pdos()
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_pdo_assign_clear(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint8_t sync_index /**< Sync manager index. Must be less
|
|
than #EC_MAX_SYNC_MANAGERS. */
|
|
);
|
|
|
|
/** Add a PDO entry to the given PDO's mapping.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \see ecrt_slave_config_pdos()
|
|
* \return zero on success, else non-zero
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_pdo_mapping_add(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint16_t pdo_index, /**< Index of the PDO. */
|
|
uint16_t entry_index, /**< Index of the PDO entry to add to the PDO's
|
|
mapping. */
|
|
uint8_t entry_subindex, /**< Subindex of the PDO entry to add to the
|
|
PDO's mapping. */
|
|
uint8_t entry_bit_length /**< Size of the PDO entry in bit. */
|
|
);
|
|
|
|
/** Clear the mapping of a given PDO.
|
|
*
|
|
* This can be called before mapping PDO entries via
|
|
* ecrt_slave_config_pdo_mapping_add(), to clear the default mapping.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \see ecrt_slave_config_pdos()
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_pdo_mapping_clear(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint16_t pdo_index /**< Index of the PDO. */
|
|
);
|
|
|
|
/** Specify a complete PDO configuration.
|
|
*
|
|
* This function is a convenience wrapper for the functions
|
|
* ecrt_slave_config_sync_manager(), ecrt_slave_config_pdo_assign_clear(),
|
|
* ecrt_slave_config_pdo_assign_add(), ecrt_slave_config_pdo_mapping_clear()
|
|
* and ecrt_slave_config_pdo_mapping_add(), that are better suitable for
|
|
* automatic code generation.
|
|
*
|
|
* The following example shows, how to specify a complete configuration,
|
|
* including the PDO mappings. With this information, the master is able to
|
|
* reserve the complete process data, even if the slave is not present at
|
|
* configuration time:
|
|
*
|
|
* \code
|
|
* ec_pdo_entry_info_t el3162_channel1[] = {
|
|
* {0x3101, 1, 8}, // status
|
|
* {0x3101, 2, 16} // value
|
|
* };
|
|
*
|
|
* ec_pdo_entry_info_t el3162_channel2[] = {
|
|
* {0x3102, 1, 8}, // status
|
|
* {0x3102, 2, 16} // value
|
|
* };
|
|
*
|
|
* ec_pdo_info_t el3162_pdos[] = {
|
|
* {0x1A00, 2, el3162_channel1},
|
|
* {0x1A01, 2, el3162_channel2}
|
|
* };
|
|
*
|
|
* ec_sync_info_t el3162_syncs[] = {
|
|
* {2, EC_DIR_OUTPUT},
|
|
* {3, EC_DIR_INPUT, 2, el3162_pdos},
|
|
* {0xff}
|
|
* };
|
|
*
|
|
* if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3162_syncs)) {
|
|
* // handle error
|
|
* }
|
|
* \endcode
|
|
*
|
|
* The next example shows, how to configure the PDO assignment only. The
|
|
* entries for each assigned PDO are taken from the PDO's default mapping.
|
|
* Please note, that PDO entry registration will fail, if the PDO
|
|
* configuration is left empty and the slave is offline.
|
|
*
|
|
* \code
|
|
* ec_pdo_info_t pdos[] = {
|
|
* {0x1600}, // Channel 1
|
|
* {0x1601} // Channel 2
|
|
* };
|
|
*
|
|
* ec_sync_info_t syncs[] = {
|
|
* {3, EC_DIR_INPUT, 2, pdos},
|
|
* };
|
|
*
|
|
* if (ecrt_slave_config_pdos(slave_config_ana_in, 1, syncs)) {
|
|
* // handle error
|
|
* }
|
|
* \endcode
|
|
*
|
|
* Processing of \a syncs will stop, if
|
|
* - the number of processed items reaches \a n_syncs, or
|
|
* - the \a index member of an ec_sync_info_t item is 0xff. In this case,
|
|
* \a n_syncs should set to a number greater than the number of list items;
|
|
* using EC_END is recommended.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return zero on success, else non-zero
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_pdos(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
unsigned int n_syncs, /**< Number of sync manager configurations in
|
|
\a syncs. */
|
|
const ec_sync_info_t syncs[] /**< Array of sync manager
|
|
configurations. */
|
|
);
|
|
|
|
/** Registers a PDO entry for process data exchange in a domain.
|
|
*
|
|
* Searches the assigned PDOs for the given PDO entry. An error is raised, if
|
|
* the given entry is not mapped. Otherwise, the corresponding sync manager
|
|
* and FMMU configurations are provided for slave configuration and the
|
|
* respective sync manager's assigned PDOs are appended to the given domain,
|
|
* if not already done. The offset of the requested PDO entry's data inside
|
|
* the domain's process data is returned. Optionally, the PDO entry bit
|
|
* position (0-7) can be retrieved via the \a bit_position output parameter.
|
|
* This pointer may be \a NULL, in this case an error is raised if the PDO
|
|
* entry does not byte-align.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval >=0 Success: Offset of the PDO entry's process data.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_reg_pdo_entry(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint16_t entry_index, /**< Index of the PDO entry to register. */
|
|
uint8_t entry_subindex, /**< Subindex of the PDO entry to register. */
|
|
ec_domain_t *domain, /**< Domain. */
|
|
unsigned int *bit_position /**< Optional address if bit addressing
|
|
is desired */
|
|
);
|
|
|
|
/** Registers a PDO entry using its position.
|
|
*
|
|
* Similar to ecrt_slave_config_reg_pdo_entry(), but not using PDO indices but
|
|
* offsets in the PDO mapping, because PDO entry indices may not be unique
|
|
* inside a slave's PDO mapping. An error is raised, if
|
|
* one of the given positions is out of range.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval >=0 Success: Offset of the PDO entry's process data.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_reg_pdo_entry_pos(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint8_t sync_index, /**< Sync manager index. */
|
|
unsigned int pdo_pos, /**< Position of the PDO inside the SM. */
|
|
unsigned int entry_pos, /**< Position of the entry inside the PDO. */
|
|
ec_domain_t *domain, /**< Domain. */
|
|
unsigned int *bit_position /**< Optional address if bit addressing
|
|
is desired */
|
|
);
|
|
|
|
/** Configure distributed clocks.
|
|
*
|
|
* Sets the AssignActivate word and the cycle and shift times for the sync
|
|
* signals.
|
|
*
|
|
* The AssignActivate word is vendor-specific and can be taken from the XML
|
|
* device description file (Device -> Dc -> AssignActivate). Set this to zero,
|
|
* if the slave shall be operated without distributed clocks (default).
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \attention The \a sync1_shift time is ignored.
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_dc(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint16_t assign_activate, /**< AssignActivate word. */
|
|
uint32_t sync0_cycle, /**< SYNC0 cycle time [ns]. */
|
|
int32_t sync0_shift, /**< SYNC0 shift time [ns]. */
|
|
uint32_t sync1_cycle, /**< SYNC1 cycle time [ns]. */
|
|
int32_t sync1_shift /**< SYNC1 shift time [ns]. */
|
|
);
|
|
|
|
/** Add an SDO configuration.
|
|
*
|
|
* An SDO configuration is stored in the slave configuration object and is
|
|
* downloaded to the slave whenever the slave is being configured by the
|
|
* master. This usually happens once on master activation, but can be repeated
|
|
* subsequently, for example after the slave's power supply failed.
|
|
*
|
|
* \attention The SDOs for PDO assignment (\p 0x1C10 - \p 0x1C2F) and PDO
|
|
* mapping (\p 0x1600 - \p 0x17FF and \p 0x1A00 - \p 0x1BFF) should not be
|
|
* configured with this function, because they are part of the slave
|
|
* configuration done by the master. Please use ecrt_slave_config_pdos() and
|
|
* friends instead.
|
|
*
|
|
* This is the generic function for adding an SDO configuration. Please note
|
|
* that the this function does not do any endianness correction. If
|
|
* datatype-specific functions are needed (that automatically correct the
|
|
* endianness), have a look at ecrt_slave_config_sdo8(),
|
|
* ecrt_slave_config_sdo16() and ecrt_slave_config_sdo32().
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_sdo(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint16_t index, /**< Index of the SDO to configure. */
|
|
uint8_t subindex, /**< Subindex of the SDO to configure. */
|
|
const uint8_t *data, /**< Pointer to the data. */
|
|
size_t size /**< Size of the \a data. */
|
|
);
|
|
|
|
/** Add a configuration value for an 8-bit SDO.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \see ecrt_slave_config_sdo().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_sdo8(
|
|
ec_slave_config_t *sc, /**< Slave configuration */
|
|
uint16_t sdo_index, /**< Index of the SDO to configure. */
|
|
uint8_t sdo_subindex, /**< Subindex of the SDO to configure. */
|
|
uint8_t value /**< Value to set. */
|
|
);
|
|
|
|
/** Add a configuration value for a 16-bit SDO.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \see ecrt_slave_config_sdo().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_sdo16(
|
|
ec_slave_config_t *sc, /**< Slave configuration */
|
|
uint16_t sdo_index, /**< Index of the SDO to configure. */
|
|
uint8_t sdo_subindex, /**< Subindex of the SDO to configure. */
|
|
uint16_t value /**< Value to set. */
|
|
);
|
|
|
|
/** Add a configuration value for a 32-bit SDO.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \see ecrt_slave_config_sdo().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_sdo32(
|
|
ec_slave_config_t *sc, /**< Slave configuration */
|
|
uint16_t sdo_index, /**< Index of the SDO to configure. */
|
|
uint8_t sdo_subindex, /**< Subindex of the SDO to configure. */
|
|
uint32_t value /**< Value to set. */
|
|
);
|
|
|
|
/** Add configuration data for a complete SDO.
|
|
*
|
|
* The SDO data are transferred via CompleteAccess. Data for the first
|
|
* subindex (0) have to be included.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \see ecrt_slave_config_sdo().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_complete_sdo(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint16_t index, /**< Index of the SDO to configure. */
|
|
const uint8_t *data, /**< Pointer to the data. */
|
|
size_t size /**< Size of the \a data. */
|
|
);
|
|
|
|
/** Set the size of the CoE emergency ring buffer.
|
|
*
|
|
* The initial size is zero, so all messages will be dropped. This method can
|
|
* be called even after master activation, but it will clear the ring buffer!
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return 0 on success, or negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_emerg_size(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
size_t elements /**< Number of records of the CoE emergency ring. */
|
|
);
|
|
|
|
/** Read and remove one record from the CoE emergency ring buffer.
|
|
*
|
|
* A record consists of 8 bytes:
|
|
*
|
|
* Byte 0-1: Error code (little endian)
|
|
* Byte 2: Error register
|
|
* Byte 3-7: Data
|
|
*
|
|
* Calling this method makes only sense in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \return 0 on success (record popped), or negative error code (i. e.
|
|
* -ENOENT, if ring is empty).
|
|
*
|
|
* \apiusage{master_op,any_context}
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_emerg_pop(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint8_t *target /**< Pointer to target memory (at least
|
|
EC_COE_EMERGENCY_MSG_SIZE bytes). */
|
|
);
|
|
|
|
/** Clears CoE emergency ring buffer and the overrun counter.
|
|
*
|
|
* Calling this method makes only sense in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,any_context}
|
|
*
|
|
* \return 0 on success, or negative error code.
|
|
*
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_emerg_clear(
|
|
ec_slave_config_t *sc /**< Slave configuration. */
|
|
);
|
|
|
|
/** Read the number of CoE emergency overruns.
|
|
*
|
|
* The overrun counter will be incremented when a CoE emergency message could
|
|
* not be stored in the ring buffer and had to be dropped. Call
|
|
* ecrt_slave_config_emerg_clear() to reset the counter.
|
|
*
|
|
* Calling this method makes only sense in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,any_context}
|
|
*
|
|
* \return Number of overruns since last clear, or negative error code.
|
|
*
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_emerg_overruns(
|
|
const ec_slave_config_t *sc /**< Slave configuration. */
|
|
);
|
|
|
|
/** Create an SDO request to exchange SDOs during realtime operation.
|
|
*
|
|
* The created SDO request object is freed automatically when the master is
|
|
* released.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return New SDO request, or NULL on error.
|
|
*/
|
|
EC_PUBLIC_API ec_sdo_request_t *ecrt_slave_config_create_sdo_request(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint16_t index, /**< SDO index. */
|
|
uint8_t subindex, /**< SDO subindex. */
|
|
size_t size /**< Data size to reserve. */
|
|
);
|
|
|
|
/** Create an SoE request to exchange SoE IDNs during realtime operation.
|
|
*
|
|
* The created SoE request object is freed automatically when the master is
|
|
* released.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return New SoE request, or NULL on error.
|
|
*/
|
|
EC_PUBLIC_API ec_soe_request_t *ecrt_slave_config_create_soe_request(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint8_t drive_no, /**< Drive number. */
|
|
uint16_t idn, /**< Sercos ID-Number. */
|
|
size_t size /**< Data size to reserve. */
|
|
);
|
|
|
|
/** Create an VoE handler to exchange vendor-specific data during realtime
|
|
* operation.
|
|
*
|
|
* The number of VoE handlers per slave configuration is not limited, but
|
|
* usually it is enough to create one for sending and one for receiving, if
|
|
* both can be done simultaneously.
|
|
*
|
|
* The created VoE handler object is freed automatically when the master is
|
|
* released.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return New VoE handler, or NULL on error.
|
|
*/
|
|
EC_PUBLIC_API ec_voe_handler_t *ecrt_slave_config_create_voe_handler(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
size_t size /**< Data size to reserve. */
|
|
);
|
|
|
|
/** Create a register request to exchange EtherCAT register contents during
|
|
* realtime operation.
|
|
*
|
|
* This interface should not be used to take over master functionality,
|
|
* instead it is intended for debugging and monitoring reasons.
|
|
*
|
|
* The created register request object is freed automatically when the master
|
|
* is released.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return New register request, or NULL on error.
|
|
*/
|
|
EC_PUBLIC_API ec_reg_request_t *ecrt_slave_config_create_reg_request(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
size_t size /**< Data size to reserve. */
|
|
);
|
|
|
|
/** Outputs the state of the slave configuration.
|
|
*
|
|
* Stores the state information in the given \a state structure. The state
|
|
* information is updated by the master state machine, so it may take a few
|
|
* cycles, until it changes.
|
|
*
|
|
* \attention If the state of process data exchange shall be monitored in
|
|
* realtime, ecrt_domain_state() should be used.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_state(
|
|
const ec_slave_config_t *sc, /**< Slave configuration */
|
|
ec_slave_config_state_t *state /**< State object to write to. */
|
|
);
|
|
|
|
/** Add an SoE IDN configuration.
|
|
*
|
|
* A configuration for a Sercos-over-EtherCAT IDN is stored in the slave
|
|
* configuration object and is written to the slave whenever the slave is
|
|
* being configured by the master. This usually happens once on master
|
|
* activation, but can be repeated subsequently, for example after the slave's
|
|
* power supply failed.
|
|
*
|
|
* The \a idn parameter can be separated into several sections:
|
|
* - Bit 15: Standard data (0) or Product data (1)
|
|
* - Bit 14 - 12: Parameter set (0 - 7)
|
|
* - Bit 11 - 0: Data block number (0 - 4095)
|
|
*
|
|
* Please note that the this function does not do any endianness correction.
|
|
* Multi-byte data have to be passed in EtherCAT endianness (little-endian).
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_idn(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
uint8_t drive_no, /**< Drive number. */
|
|
uint16_t idn, /**< SoE IDN. */
|
|
ec_al_state_t state, /**< AL state in which to write the IDN (PREOP or
|
|
SAFEOP). */
|
|
const uint8_t *data, /**< Pointer to the data. */
|
|
size_t size /**< Size of the \a data. */
|
|
);
|
|
|
|
/** Adds a feature flag to a slave configuration.
|
|
*
|
|
* Feature flags are a generic way to configure slave-specific behavior.
|
|
*
|
|
* Multiple calls with the same slave configuration and key will overwrite the
|
|
* configuration.
|
|
*
|
|
* The following flags may be available:
|
|
* - AssignToPdi: Zero (default) keeps the slave information interface (SII)
|
|
* assigned to EtherCAT (except during transition to PREOP). Non-zero
|
|
* assigns the SII to the slave controller side before going to PREOP and
|
|
* leaves it there until a write command happens.
|
|
* - WaitBeforeSAFEOPms: Number of milliseconds to wait before commanding the
|
|
* transition from PREOP to SAFEOP. This can be used as a workaround for
|
|
* slaves that need a little time to initialize.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_flag(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
const char *key, /**< Key as null-terminated ASCII string. */
|
|
int32_t value /**< Value to store. */
|
|
);
|
|
|
|
/** Sets the link/MAC address for Ethernet-over-EtherCAT (EoE) operation.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* The MAC address is stored in the slave configuration object and will be
|
|
* written to the slave during the configuration process.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_eoe_mac_address(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
const unsigned char *mac_address /**< MAC address. */
|
|
);
|
|
|
|
/** Sets the IP address for Ethernet-over-EtherCAT (EoE) operation.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* The IP address is stored in the slave configuration object and will be
|
|
* written to the slave during the configuration process.
|
|
*
|
|
* The IP address is passed by-value as a `struct in_addr`. This structure
|
|
* contains the 32-bit IPv4 address in network byte order (big endian).
|
|
*
|
|
* A string-represented IPv4 address can be converted to a `struct in_addr`
|
|
* for example via the POSIX function `inet_pton()` (see man 3 inet_pton):
|
|
*
|
|
* \code{.c}
|
|
* #include <arpa/inet.h>
|
|
* struct in_addr addr;
|
|
* if (inet_aton("192.168.0.1", &addr) == 0) {
|
|
* fprintf(stderr, "Failed to convert IP address.\n");
|
|
* return -1;
|
|
* }
|
|
* if (ecrt_slave_config_eoe_ip_address(sc, addr)) {
|
|
* fprintf(stderr, "Failed to set IP address.\n");
|
|
* return -1;
|
|
* }
|
|
* \endcode
|
|
*
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_eoe_ip_address(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
struct in_addr ip_address /**< IPv4 address. */
|
|
);
|
|
|
|
/** Sets the subnet mask for Ethernet-over-EtherCAT (EoE) operation.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* The subnet mask is stored in the slave configuration object and will be
|
|
* written to the slave during the configuration process.
|
|
*
|
|
* The subnet mask is passed by-value as a `struct in_addr`. This structure
|
|
* contains the 32-bit mask in network byte order (big endian).
|
|
*
|
|
* See ecrt_slave_config_eoe_ip_address() on how to convert string-coded masks
|
|
* to `struct in_addr`.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_eoe_subnet_mask(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
struct in_addr subnet_mask /**< IPv4 subnet mask. */
|
|
);
|
|
|
|
/** Sets the gateway address for Ethernet-over-EtherCAT (EoE) operation.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* The gateway address is stored in the slave configuration object and will be
|
|
* written to the slave during the configuration process.
|
|
*
|
|
* The address is passed by-value as a `struct in_addr`. This structure
|
|
* contains the 32-bit IPv4 address in network byte order (big endian).
|
|
*
|
|
* See ecrt_slave_config_eoe_ip_address() on how to convert string-coded IPv4
|
|
* addresses to `struct in_addr`.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_eoe_default_gateway(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
struct in_addr gateway_address /**< Gateway's IPv4 address. */
|
|
);
|
|
|
|
/** Sets the IPv4 address of the DNS server for Ethernet-over-EtherCAT (EoE)
|
|
* operation.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* The DNS server address is stored in the slave configuration object and will
|
|
* be written to the slave during the configuration process.
|
|
*
|
|
* The address is passed by-value as a `struct in_addr`. This structure
|
|
* contains the 32-bit IPv4 address in network byte order (big endian).
|
|
*
|
|
* See ecrt_slave_config_eoe_ip_address() on how to convert string-coded IPv4
|
|
* addresses to `struct in_addr`.
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_eoe_dns_address(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
struct in_addr dns_address /**< IPv4 address of the DNS server. */
|
|
);
|
|
|
|
/** Sets the host name for Ethernet-over-EtherCAT (EoE) operation.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* The host name is stored in the slave configuration object and will
|
|
* be written to the slave during the configuration process.
|
|
*
|
|
* The maximum size of the host name is 32 bytes (including the zero
|
|
* terminator).
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_eoe_hostname(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
const char *name /**< Zero-terminated host name. */
|
|
);
|
|
|
|
/** Sets the application-layer state transition timeout in ms.
|
|
*
|
|
* Change the maximum allowed time for a slave to make an application-layer
|
|
* state transition for the given state transition (for example from PREOP to
|
|
* SAFEOP). The default values are defined in ETG.2000.
|
|
*
|
|
* A timeout value of zero ms will restore the default value.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \retval 0 Success.
|
|
* \retval <0 Error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_slave_config_state_timeout(
|
|
ec_slave_config_t *sc, /**< Slave configuration. */
|
|
ec_al_state_t from_state, /**< Initial state. */
|
|
ec_al_state_t to_state, /**< Target state. */
|
|
unsigned int timeout_ms /**< Timeout in [ms]. */
|
|
);
|
|
|
|
/*****************************************************************************
|
|
* Domain methods
|
|
****************************************************************************/
|
|
|
|
/** Registers a bunch of PDO entries for a domain.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \see ecrt_slave_config_reg_pdo_entry()
|
|
*
|
|
* \attention The registration array has to be terminated with an empty
|
|
* structure, or one with the \a index field set to zero!
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*
|
|
* \return 0 on success, else non-zero.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_domain_reg_pdo_entry_list(
|
|
ec_domain_t *domain, /**< Domain. */
|
|
const ec_pdo_entry_reg_t *pdo_entry_regs /**< Array of PDO
|
|
registrations. */
|
|
);
|
|
|
|
/** Returns the current size of the domain's process data.
|
|
*
|
|
* The domain size is calculated after master activation.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Size of the process data image, or a negative error code.
|
|
*/
|
|
EC_PUBLIC_API size_t ecrt_domain_size(
|
|
const ec_domain_t *domain /**< Domain. */
|
|
);
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
/** Provide external memory to store the domain's process data.
|
|
*
|
|
* Call this after all PDO entries have been registered and before activating
|
|
* the master.
|
|
*
|
|
* The size of the allocated memory must be at least ecrt_domain_size(), after
|
|
* all PDO entries have been registered.
|
|
*
|
|
* This method has to be called in non-realtime context before
|
|
* ecrt_master_activate().
|
|
*
|
|
* \apiusage{master_idle,blocking}
|
|
*/
|
|
void ecrt_domain_external_memory(
|
|
ec_domain_t *domain, /**< Domain. */
|
|
uint8_t *memory /**< Address of the memory to store the process
|
|
data in. */
|
|
);
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
/** Returns the domain's process data.
|
|
*
|
|
* - In kernel context: If external memory was provided with
|
|
* ecrt_domain_external_memory(), the returned pointer will contain the
|
|
* address of that memory. Otherwise it will point to the internally allocated
|
|
* memory. In the latter case, this method may not be called before
|
|
* ecrt_master_activate().
|
|
*
|
|
* - In userspace context: This method has to be called after
|
|
* ecrt_master_activate() to get the mapped domain process data memory.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Pointer to the process data memory.
|
|
*/
|
|
EC_PUBLIC_API uint8_t *ecrt_domain_data(
|
|
const ec_domain_t *domain /**< Domain. */
|
|
);
|
|
|
|
/** Determines the states of the domain's datagrams.
|
|
*
|
|
* Evaluates the working counters of the received datagrams and outputs
|
|
* statistics, if necessary. This must be called after ecrt_master_receive()
|
|
* is expected to receive the domain datagrams in order to make
|
|
* ecrt_domain_state() return the result of the last process data exchange.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_domain_process(
|
|
ec_domain_t *domain /**< Domain. */
|
|
);
|
|
|
|
/** (Re-)queues all domain datagrams in the master's datagram queue.
|
|
*
|
|
* Call this function to mark the domain's datagrams for exchanging at the
|
|
* next call of ecrt_master_send().
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_domain_queue(
|
|
ec_domain_t *domain /**< Domain. */
|
|
);
|
|
|
|
/** Reads the state of a domain.
|
|
*
|
|
* Stores the domain state in the given \a state structure.
|
|
*
|
|
* Using this method, the process data exchange can be monitored in realtime.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_domain_state(
|
|
const ec_domain_t *domain, /**< Domain. */
|
|
ec_domain_state_t *state /**< Pointer to a state object to store the
|
|
information. */
|
|
);
|
|
|
|
/*****************************************************************************
|
|
* SDO request methods.
|
|
****************************************************************************/
|
|
|
|
/** Set the SDO index and subindex.
|
|
*
|
|
* \attention If the SDO index and/or subindex is changed while
|
|
* ecrt_sdo_request_state() returns EC_REQUEST_BUSY, this may lead to
|
|
* unexpected results.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation). To initialize the SDO request, the index and subindex can be
|
|
* set via ecrt_slave_config_create_sdo_request().
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_sdo_request_index(
|
|
ec_sdo_request_t *req, /**< SDO request. */
|
|
uint16_t index, /**< SDO index. */
|
|
uint8_t subindex /**< SDO subindex. */
|
|
);
|
|
|
|
/** Set the timeout for an SDO request.
|
|
*
|
|
* If the request cannot be processed in the specified time, if will be marked
|
|
* as failed.
|
|
*
|
|
* The timeout is permanently stored in the request object and is valid until
|
|
* the next call of this method.
|
|
*
|
|
* The timeout should be defined in non-realtime context, but can also be
|
|
* changed afterwards.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_sdo_request_timeout(
|
|
ec_sdo_request_t *req, /**< SDO request. */
|
|
uint32_t timeout /**< Timeout in milliseconds. Zero means no
|
|
timeout. */
|
|
);
|
|
|
|
/** Access to the SDO request's data.
|
|
*
|
|
* This function returns a pointer to the request's internal SDO data memory.
|
|
*
|
|
* - After a read operation was successful, integer data can be evaluated
|
|
* using the EC_READ_*() macros as usual. Example:
|
|
* \code
|
|
* uint16_t value = EC_READ_U16(ecrt_sdo_request_data(sdo)));
|
|
* \endcode
|
|
* - If a write operation shall be triggered, the data have to be written to
|
|
* the internal memory. Use the EC_WRITE_*() macros, if you are writing
|
|
* integer data. Be sure, that the data fit into the memory. The memory size
|
|
* is a parameter of ecrt_slave_config_create_sdo_request().
|
|
* \code
|
|
* EC_WRITE_U16(ecrt_sdo_request_data(sdo), 0xFFFF);
|
|
* \endcode
|
|
*
|
|
* \attention The return value can be invalid during a read operation, because
|
|
* the internal SDO data memory could be re-allocated if the read SDO data do
|
|
* not fit inside.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation), but can also be used to initialize data before.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return Pointer to the internal SDO data memory.
|
|
*
|
|
*/
|
|
EC_PUBLIC_API uint8_t *ecrt_sdo_request_data(
|
|
const ec_sdo_request_t *req /**< SDO request. */
|
|
);
|
|
|
|
/** Returns the current SDO data size.
|
|
*
|
|
* When the SDO request is created, the data size is set to the size of the
|
|
* reserved memory. After a read operation the size is set to the size of the
|
|
* read data. The size is not modified in any other situation.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return SDO data size in bytes.
|
|
*
|
|
*/
|
|
EC_PUBLIC_API size_t ecrt_sdo_request_data_size(
|
|
const ec_sdo_request_t *req /**< SDO request. */
|
|
);
|
|
|
|
/** Get the current state of the SDO request.
|
|
*
|
|
* The user-space implementation fetches incoming data and stores the received
|
|
* data size in the request object, so the request is not const.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Request state.
|
|
*
|
|
*/
|
|
EC_PUBLIC_API ec_request_state_t ecrt_sdo_request_state(
|
|
#ifdef __KERNEL__
|
|
const
|
|
#endif
|
|
ec_sdo_request_t *req /**< SDO request. */
|
|
);
|
|
|
|
/** Schedule an SDO write operation.
|
|
*
|
|
* \attention This method may not be called while ecrt_sdo_request_state()
|
|
* returns EC_REQUEST_BUSY.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
* \retval -EINVAL Invalid input data, e.g. data size == 0.
|
|
* \retval -ENOBUFS Reserved memory in ecrt_slave_config_create_sdo_request()
|
|
* too small.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_sdo_request_write(
|
|
ec_sdo_request_t *req /**< SDO request. */
|
|
);
|
|
|
|
/** Schedule an SDO read operation.
|
|
*
|
|
* \attention This method may not be called while ecrt_sdo_request_state()
|
|
* returns EC_REQUEST_BUSY.
|
|
*
|
|
* \attention After calling this function, the return value of
|
|
* ecrt_sdo_request_data() must be considered as invalid while
|
|
* ecrt_sdo_request_state() returns EC_REQUEST_BUSY.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_sdo_request_read(
|
|
ec_sdo_request_t *req /**< SDO request. */
|
|
);
|
|
|
|
/*****************************************************************************
|
|
* SoE request methods.
|
|
****************************************************************************/
|
|
|
|
/** Set the request's drive and Sercos ID numbers.
|
|
*
|
|
* \attention If the drive number and/or IDN is changed while
|
|
* ecrt_soe_request_state() returns EC_REQUEST_BUSY, this may lead to
|
|
* unexpected results.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation). To initialize the SoE request, the drive_no and IDN can be
|
|
* set via ecrt_slave_config_create_soe_request().
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_soe_request_idn(
|
|
ec_soe_request_t *req, /**< IDN request. */
|
|
uint8_t drive_no, /**< SDO index. */
|
|
uint16_t idn /**< SoE IDN. */
|
|
);
|
|
|
|
/** Set the timeout for an SoE request.
|
|
*
|
|
* If the request cannot be processed in the specified time, if will be marked
|
|
* as failed.
|
|
*
|
|
* The timeout is permanently stored in the request object and is valid until
|
|
* the next call of this method.
|
|
*
|
|
* The timeout should be defined in non-realtime context, but can also be
|
|
* changed afterwards.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_soe_request_timeout(
|
|
ec_soe_request_t *req, /**< SoE request. */
|
|
uint32_t timeout /**< Timeout in milliseconds. Zero means no
|
|
timeout. */
|
|
);
|
|
|
|
/** Access to the SoE request's data.
|
|
*
|
|
* This function returns a pointer to the request's internal IDN data memory.
|
|
*
|
|
* - After a read operation was successful, integer data can be evaluated
|
|
* using the EC_READ_*() macros as usual. Example:
|
|
* \code
|
|
* uint16_t value = EC_READ_U16(ecrt_soe_request_data(idn_req)));
|
|
* \endcode
|
|
* - If a write operation shall be triggered, the data have to be written to
|
|
* the internal memory. Use the EC_WRITE_*() macros, if you are writing
|
|
* integer data. Be sure, that the data fit into the memory. The memory size
|
|
* is a parameter of ecrt_slave_config_create_soe_request().
|
|
* \code
|
|
* EC_WRITE_U16(ecrt_soe_request_data(idn_req), 0xFFFF);
|
|
* \endcode
|
|
*
|
|
* \attention The return value can be invalidated during a read operation,
|
|
* because the internal IDN data memory could be re-allocated if the read IDN
|
|
* data do not fit inside.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation), but can also be used to initialize data before.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return Pointer to the internal IDN data memory.
|
|
*
|
|
*/
|
|
EC_PUBLIC_API uint8_t *ecrt_soe_request_data(
|
|
const ec_soe_request_t *req /**< SoE request. */
|
|
);
|
|
|
|
/** Returns the current IDN data size.
|
|
*
|
|
* When the SoE request is created, the data size is set to the size of the
|
|
* reserved memory. After a read operation the size is set to the size of the
|
|
* read data. The size is not modified in any other situation.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return IDN data size in bytes.
|
|
*/
|
|
EC_PUBLIC_API size_t ecrt_soe_request_data_size(
|
|
const ec_soe_request_t *req /**< SoE request. */
|
|
);
|
|
|
|
/** Get the current state of the SoE request.
|
|
*
|
|
* \return Request state.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* In the user-space implementation, the method fetches the size of the
|
|
* incoming data, so the request object is not const.
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*/
|
|
EC_PUBLIC_API ec_request_state_t ecrt_soe_request_state(
|
|
#ifdef __KERNEL__
|
|
const
|
|
#endif
|
|
ec_soe_request_t *req /**< SoE request. */
|
|
);
|
|
|
|
/** Schedule an SoE IDN write operation.
|
|
*
|
|
* \attention This method may not be called while ecrt_soe_request_state()
|
|
* returns EC_REQUEST_BUSY.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
* \retval -EINVAL Invalid input data, e.g. data size == 0.
|
|
* \retval -ENOBUFS Reserved memory in ecrt_slave_config_create_soe_request()
|
|
* too small.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_soe_request_write(
|
|
ec_soe_request_t *req /**< SoE request. */
|
|
);
|
|
|
|
/** Schedule an SoE IDN read operation.
|
|
*
|
|
* \attention This method may not be called while ecrt_soe_request_state()
|
|
* returns EC_REQUEST_BUSY.
|
|
*
|
|
* \attention After calling this function, the return value of
|
|
* ecrt_soe_request_data() must be considered as invalid while
|
|
* ecrt_soe_request_state() returns EC_REQUEST_BUSY.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_soe_request_read(
|
|
ec_soe_request_t *req /**< SoE request. */
|
|
);
|
|
|
|
/*****************************************************************************
|
|
* VoE handler methods.
|
|
****************************************************************************/
|
|
|
|
/** Sets the VoE header for future send operations.
|
|
*
|
|
* A VoE message shall contain a 4-byte vendor ID, followed by a 2-byte vendor
|
|
* type at as header. These numbers can be set with this function. The values
|
|
* are valid and will be used for future send operations until the next call
|
|
* of this method.
|
|
*
|
|
* This method is meant to be called in non-realtime context (before master
|
|
* activation) to initialize the header data, but it is also safe to
|
|
* change the header later on in realtime context.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_voe_handler_send_header(
|
|
ec_voe_handler_t *voe, /**< VoE handler. */
|
|
uint32_t vendor_id, /**< Vendor ID. */
|
|
uint16_t vendor_type /**< Vendor-specific type. */
|
|
);
|
|
|
|
/** Reads the header data of a received VoE message.
|
|
*
|
|
* This method can be used to get the received VoE header information after a
|
|
* read operation has succeeded.
|
|
*
|
|
* The header information is stored at the memory given by the pointer
|
|
* parameters.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_voe_handler_received_header(
|
|
const ec_voe_handler_t *voe, /**< VoE handler. */
|
|
uint32_t *vendor_id, /**< Vendor ID. */
|
|
uint16_t *vendor_type /**< Vendor-specific type. */
|
|
);
|
|
|
|
/** Access to the VoE handler's data.
|
|
*
|
|
* This function returns a pointer to the VoE handler's internal memory, that
|
|
* points to the actual VoE data right after the VoE header (see
|
|
* ecrt_voe_handler_send_header()).
|
|
*
|
|
* - After a read operation was successful, the memory contains the received
|
|
* data. The size of the received data can be determined via
|
|
* ecrt_voe_handler_data_size().
|
|
* - Before a write operation is triggered, the data have to be written to the
|
|
* internal memory. Be sure, that the data fit into the memory. The reserved
|
|
* memory size is a parameter of ecrt_slave_config_create_voe_handler().
|
|
*
|
|
* \attention The returned pointer is not necessarily persistent: After a read
|
|
* operation, the internal memory may have been reallocated. This can be
|
|
* avoided by reserving enough memory via the \a size parameter of
|
|
* ecrt_slave_config_create_voe_handler().
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return Pointer to the internal memory.
|
|
*/
|
|
EC_PUBLIC_API uint8_t *ecrt_voe_handler_data(
|
|
const ec_voe_handler_t *voe /**< VoE handler. */
|
|
);
|
|
|
|
/** Returns the current data size.
|
|
*
|
|
* The data size is the size of the VoE data without the header (see
|
|
* ecrt_voe_handler_send_header()).
|
|
*
|
|
* When the VoE handler is created, the data size is set to the size of the
|
|
* reserved memory. At a write operation, the data size is set to the number
|
|
* of bytes to write. After a read operation the size is set to the size of
|
|
* the read data. The size is not modified in any other situation.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return Data size in bytes.
|
|
*/
|
|
EC_PUBLIC_API size_t ecrt_voe_handler_data_size(
|
|
const ec_voe_handler_t *voe /**< VoE handler. */
|
|
);
|
|
|
|
/** Start a VoE write operation.
|
|
*
|
|
* After this function has been called, the ecrt_voe_handler_execute() method
|
|
* must be called in every realtime cycle as long as it returns
|
|
* EC_REQUEST_BUSY. No other operation may be started while the handler is
|
|
* busy.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
* \retval -ENOBUFS Reserved memory in ecrt_slave_config_create_voe_handler
|
|
* too small.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_voe_handler_write(
|
|
ec_voe_handler_t *voe, /**< VoE handler. */
|
|
size_t size /**< Number of bytes to write (without the VoE header). */
|
|
);
|
|
|
|
/** Start a VoE read operation.
|
|
*
|
|
* After this function has been called, the ecrt_voe_handler_execute() method
|
|
* must be called in every realtime cycle as long as it returns
|
|
* EC_REQUEST_BUSY. No other operation may be started while the handler is
|
|
* busy.
|
|
*
|
|
* The state machine queries the slave's send mailbox for new data to be send
|
|
* to the master. If no data appear within the EC_VOE_RESPONSE_TIMEOUT
|
|
* (defined in master/voe_handler.c), the operation fails.
|
|
*
|
|
* On success, the size of the read data can be determined via
|
|
* ecrt_voe_handler_data_size(), while the VoE header of the received data
|
|
* can be retrieved with ecrt_voe_handler_received_header().
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_voe_handler_read(
|
|
ec_voe_handler_t *voe /**< VoE handler. */
|
|
);
|
|
|
|
/** Start a VoE read operation without querying the sync manager status.
|
|
*
|
|
* After this function has been called, the ecrt_voe_handler_execute() method
|
|
* must be called in every realtime cycle as long as it returns
|
|
* EC_REQUEST_BUSY. No other operation may be started while the handler is
|
|
* busy.
|
|
*
|
|
* The state machine queries the slave by sending an empty mailbox. The slave
|
|
* fills its data to the master in this mailbox. If no data appear within the
|
|
* EC_VOE_RESPONSE_TIMEOUT (defined in master/voe_handler.c), the operation
|
|
* fails.
|
|
*
|
|
* On success, the size of the read data can be determined via
|
|
* ecrt_voe_handler_data_size(), while the VoE header of the received data
|
|
* can be retrieved with ecrt_voe_handler_received_header().
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_voe_handler_read_nosync(
|
|
ec_voe_handler_t *voe /**< VoE handler. */
|
|
);
|
|
|
|
/** Execute the handler.
|
|
*
|
|
* This method executes the VoE handler. It has to be called in every realtime
|
|
* cycle as long as it returns EC_REQUEST_BUSY.
|
|
*
|
|
* \return Handler state.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
*/
|
|
EC_PUBLIC_API ec_request_state_t ecrt_voe_handler_execute(
|
|
ec_voe_handler_t *voe /**< VoE handler. */
|
|
);
|
|
|
|
/*****************************************************************************
|
|
* Register request methods.
|
|
****************************************************************************/
|
|
|
|
/** Access to the register request's data.
|
|
*
|
|
* This function returns a pointer to the request's internal memory.
|
|
*
|
|
* - After a read operation was successful, integer data can be evaluated
|
|
* using the EC_READ_*() macros as usual. Example:
|
|
* \code
|
|
* uint16_t value = EC_READ_U16(ecrt_reg_request_data(reg_request)));
|
|
* \endcode
|
|
* - If a write operation shall be triggered, the data have to be written to
|
|
* the internal memory. Use the EC_WRITE_*() macros, if you are writing
|
|
* integer data. Be sure, that the data fit into the memory. The memory size
|
|
* is a parameter of ecrt_slave_config_create_reg_request().
|
|
* \code
|
|
* EC_WRITE_U16(ecrt_reg_request_data(reg_request), 0xFFFF);
|
|
* \endcode
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation), but can also be used to initialize data before.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \return Pointer to the internal memory.
|
|
*
|
|
*/
|
|
EC_PUBLIC_API uint8_t *ecrt_reg_request_data(
|
|
const ec_reg_request_t *req /**< Register request. */
|
|
);
|
|
|
|
/** Get the current state of the register request.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return Request state.
|
|
*
|
|
*/
|
|
EC_PUBLIC_API ec_request_state_t ecrt_reg_request_state(
|
|
const ec_reg_request_t *req /**< Register request. */
|
|
);
|
|
|
|
/** Schedule an register write operation.
|
|
*
|
|
* \attention This method may not be called while ecrt_reg_request_state()
|
|
* returns EC_REQUEST_BUSY.
|
|
*
|
|
* \attention The \a size parameter is truncated to the size given at request
|
|
* creation.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
* \retval -ENOBUFS Reserved memory in ecrt_slave_config_create_reg_request
|
|
* too small.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_reg_request_write(
|
|
ec_reg_request_t *req, /**< Register request. */
|
|
uint16_t address, /**< Register address. */
|
|
size_t size /**< Size to write. */
|
|
);
|
|
|
|
/** Schedule a register read operation.
|
|
*
|
|
* \attention This method may not be called while ecrt_reg_request_state()
|
|
* returns EC_REQUEST_BUSY.
|
|
*
|
|
* \attention The \a size parameter is truncated to the size given at request
|
|
* creation.
|
|
*
|
|
* This method is meant to be called in realtime context (after master
|
|
* activation).
|
|
*
|
|
* \apiusage{master_op,rt_safe}
|
|
*
|
|
* \return 0 on success, otherwise negative error code.
|
|
* \retval -ENOBUFS Reserved memory in ecrt_slave_config_create_reg_request
|
|
* too small.
|
|
*/
|
|
EC_PUBLIC_API int ecrt_reg_request_read(
|
|
ec_reg_request_t *req, /**< Register request. */
|
|
uint16_t address, /**< Register address. */
|
|
size_t size /**< Size to write. */
|
|
);
|
|
|
|
/*****************************************************************************
|
|
* Bitwise read/write macros
|
|
****************************************************************************/
|
|
|
|
/** Read a certain bit of an EtherCAT data byte.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param POS bit position
|
|
*/
|
|
#define EC_READ_BIT(DATA, POS) ((*((uint8_t *) (DATA)) >> (POS)) & 0x01)
|
|
|
|
/** Write a certain bit of an EtherCAT data byte.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param POS bit position
|
|
* \param VAL new bit value
|
|
*/
|
|
#define EC_WRITE_BIT(DATA, POS, VAL) \
|
|
do { \
|
|
if (VAL) *((uint8_t *) (DATA)) |= (1 << (POS)); \
|
|
else *((uint8_t *) (DATA)) &= ~(1 << (POS)); \
|
|
} while (0)
|
|
|
|
/*****************************************************************************
|
|
* Byte-swapping functions for user space
|
|
****************************************************************************/
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
|
#define le16_to_cpu(x) x
|
|
#define le32_to_cpu(x) x
|
|
#define le64_to_cpu(x) x
|
|
|
|
#define cpu_to_le16(x) x
|
|
#define cpu_to_le32(x) x
|
|
#define cpu_to_le64(x) x
|
|
|
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
|
|
#define swap16(x) \
|
|
((uint16_t)( \
|
|
(((uint16_t)(x) & 0x00ffU) << 8) | \
|
|
(((uint16_t)(x) & 0xff00U) >> 8) ))
|
|
#define swap32(x) \
|
|
((uint32_t)( \
|
|
(((uint32_t)(x) & 0x000000ffUL) << 24) | \
|
|
(((uint32_t)(x) & 0x0000ff00UL) << 8) | \
|
|
(((uint32_t)(x) & 0x00ff0000UL) >> 8) | \
|
|
(((uint32_t)(x) & 0xff000000UL) >> 24) ))
|
|
#define swap64(x) \
|
|
((uint64_t)( \
|
|
(((uint64_t)(x) & 0x00000000000000ffULL) << 56) | \
|
|
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
|
|
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
|
|
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
|
|
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
|
|
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
|
|
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
|
|
(((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ))
|
|
|
|
#define le16_to_cpu(x) swap16(x)
|
|
#define le32_to_cpu(x) swap32(x)
|
|
#define le64_to_cpu(x) swap64(x)
|
|
|
|
#define cpu_to_le16(x) swap16(x)
|
|
#define cpu_to_le32(x) swap32(x)
|
|
#define cpu_to_le64(x) swap64(x)
|
|
|
|
#endif
|
|
|
|
#define le16_to_cpup(x) le16_to_cpu(*((uint16_t *)(x)))
|
|
#define le32_to_cpup(x) le32_to_cpu(*((uint32_t *)(x)))
|
|
#define le64_to_cpup(x) le64_to_cpu(*((uint64_t *)(x)))
|
|
|
|
#endif /* ifndef __KERNEL__ */
|
|
|
|
/*****************************************************************************
|
|
* Read macros
|
|
****************************************************************************/
|
|
|
|
/** Read an 8-bit unsigned value from EtherCAT data.
|
|
*
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_U8(DATA) \
|
|
((uint8_t) *((uint8_t *) (DATA)))
|
|
|
|
/** Read an 8-bit signed value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_S8(DATA) \
|
|
((int8_t) *((uint8_t *) (DATA)))
|
|
|
|
/** Read a 16-bit unsigned value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_U16(DATA) \
|
|
((uint16_t) le16_to_cpup((void *) (DATA)))
|
|
|
|
/** Read a 16-bit signed value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_S16(DATA) \
|
|
((int16_t) le16_to_cpup((void *) (DATA)))
|
|
|
|
/** Read a 32-bit unsigned value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_U32(DATA) \
|
|
((uint32_t) le32_to_cpup((void *) (DATA)))
|
|
|
|
/** Read a 32-bit signed value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_S32(DATA) \
|
|
((int32_t) le32_to_cpup((void *) (DATA)))
|
|
|
|
/** Read a 64-bit unsigned value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_U64(DATA) \
|
|
((uint64_t) le64_to_cpup((void *) (DATA)))
|
|
|
|
/** Read a 64-bit signed value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_S64(DATA) \
|
|
((int64_t) le64_to_cpup((void *) (DATA)))
|
|
|
|
/*****************************************************************************
|
|
* Floating-point read functions and macros (userspace only)
|
|
****************************************************************************/
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
/** Read a 32-bit floating-point value from EtherCAT data.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \param data EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
EC_PUBLIC_API float ecrt_read_real(const void *data);
|
|
|
|
/** Read a 32-bit floating-point value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_REAL(DATA) ecrt_read_real(DATA)
|
|
|
|
/** Read a 64-bit floating-point value from EtherCAT data.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \param data EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
EC_PUBLIC_API double ecrt_read_lreal(const void *data);
|
|
|
|
/** Read a 64-bit floating-point value from EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \return EtherCAT data value
|
|
*/
|
|
#define EC_READ_LREAL(DATA) ecrt_read_lreal(DATA)
|
|
|
|
#endif // ifndef __KERNEL__
|
|
|
|
/*****************************************************************************
|
|
* Write macros
|
|
****************************************************************************/
|
|
|
|
/** Write an 8-bit unsigned value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_U8(DATA, VAL) \
|
|
do { \
|
|
*((uint8_t *)(DATA)) = ((uint8_t) (VAL)); \
|
|
} while (0)
|
|
|
|
/** Write an 8-bit signed value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_S8(DATA, VAL) EC_WRITE_U8(DATA, VAL)
|
|
|
|
/** Write a 16-bit unsigned value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_U16(DATA, VAL) \
|
|
do { \
|
|
*((uint16_t *) (DATA)) = cpu_to_le16((uint16_t) (VAL)); \
|
|
} while (0)
|
|
|
|
/** Write a 16-bit signed value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_S16(DATA, VAL) EC_WRITE_U16(DATA, VAL)
|
|
|
|
/** Write a 32-bit unsigned value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_U32(DATA, VAL) \
|
|
do { \
|
|
*((uint32_t *) (DATA)) = cpu_to_le32((uint32_t) (VAL)); \
|
|
} while (0)
|
|
|
|
/** Write a 32-bit signed value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_S32(DATA, VAL) EC_WRITE_U32(DATA, VAL)
|
|
|
|
/** Write a 64-bit unsigned value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_U64(DATA, VAL) \
|
|
do { \
|
|
*((uint64_t *) (DATA)) = cpu_to_le64((uint64_t) (VAL)); \
|
|
} while (0)
|
|
|
|
/** Write a 64-bit signed value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_S64(DATA, VAL) EC_WRITE_U64(DATA, VAL)
|
|
|
|
/*****************************************************************************
|
|
* Floating-point write functions and macros (userspace only)
|
|
****************************************************************************/
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
/** Write a 32-bit floating-point value to EtherCAT data.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \param data EtherCAT data pointer
|
|
* \param value new value
|
|
*/
|
|
EC_PUBLIC_API void ecrt_write_real(void *data, float value);
|
|
|
|
/** Write a 32-bit floating-point value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_REAL(DATA, VAL) ecrt_write_real(DATA, VAL)
|
|
|
|
/** Write a 64-bit floating-point value to EtherCAT data.
|
|
*
|
|
* \apiusage{master_any,rt_safe}
|
|
*
|
|
* \param data EtherCAT data pointer
|
|
* \param value new value
|
|
*/
|
|
EC_PUBLIC_API void ecrt_write_lreal(void *data, double value);
|
|
|
|
/** Write a 64-bit floating-point value to EtherCAT data.
|
|
*
|
|
* \param DATA EtherCAT data pointer
|
|
* \param VAL new value
|
|
*/
|
|
#define EC_WRITE_LREAL(DATA, VAL) ecrt_write_lreal(DATA, VAL)
|
|
|
|
#endif // ifndef __KERNEL__
|
|
|
|
/****************************************************************************/
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************/
|
|
|
|
/** @} */
|
|
|
|
#endif
|