--- a/NEWS Thu Mar 08 18:15:25 2007 +0000
+++ b/NEWS Fri Mar 09 10:24:50 2007 +0000
@@ -17,6 +17,12 @@
* Realtime interface changes:
- ecrt_master_run() became obsolete, because the master state machine is now
run in process context.
+ - Parameter changes in PDO registration functions ecrt_domain_register_pdo()
+ and ecrt_register_pdo_range(): Replaced slave_address, vendor ID and
+ product code arguments with a slave pointer, which has to be optained with
+ a prior call to ecrt_master_get_slave().
+ - ecrt_master_get_slave() got additional parameters to check for vendor ID
+ and product code.
- Added ecrt_master_get_status() to get information about the bus.
- Added functions to set up an alternative PDO mapping, i. e.
ec_slave_pdo_mapping_clear(), ec_slave_pdo_mapping_add() and
--- a/TODO Thu Mar 08 18:15:25 2007 +0000
+++ b/TODO Fri Mar 09 10:24:50 2007 +0000
@@ -9,8 +9,6 @@
* Release 1.3:
- Remove addressing scheme "X:Y".
- Remove ugly ec_slave_is_coupler().
- - Replace Vendor ID and product code arguments of ec_domain_register_pdo()
- by slave pointer.
- Reset topology_change_pending on successful validation.
- Dynamic creation of EoE handlers.
--- a/include/ecdb.h Thu Mar 08 18:15:25 2007 +0000
+++ b/include/ecdb.h Fri Mar 09 10:24:50 2007 +0000
@@ -47,46 +47,87 @@
#define Beckhoff_BK1120 0x00000002, 0x04602C22
-#define Beckhoff_EL1004_Inputs 0x00000002, 0x03EC3052, 0x3101, 1
+#define Beckhoff_EL1004 0x00000002, 0x03EC3052
+#define Beckhoff_EL1004_PDO_Inputs 0x3101, 1
+#define Beckhoff_EL1004_Inputs Beckhoff_EL1004, Beckhoff_EL1004_PDO_Inputs
-#define Beckhoff_EL1014_Inputs 0x00000002, 0x03F63052, 0x3101, 1
+#define Beckhoff_EL1014 0x00000002, 0x03F63052
+#define Beckhoff_EL1014_PDO_Inputs 0x3101, 1
+#define Beckhoff_EL1014_Inputs Beckhoff_EL1014, Beckhoff_EL1014_PDO_Inputs
-#define Beckhoff_EL2004_Outputs 0x00000002, 0x07D43052, 0x3001, 1
+#define Beckhoff_EL2004 0x00000002, 0x07D43052
+#define Beckhoff_EL2004_PDO_Outputs 0x3001, 1
+#define Beckhoff_EL2004_Outputs Beckhoff_EL2004, Beckhoff_EL2004_PDO_Outputs
-#define Beckhoff_EL2032_Outputs 0x00000002, 0x07F03052, 0x3001, 1
+#define Beckhoff_EL2032 0x00000002, 0x07F03052
+#define Beckhoff_EL2032_PDO_Outputs 0x3001, 1
+#define Beckhoff_EL2032_Outputs Beckhoff_EL2032, Beckhoff_EL2032_PDO_Outputs
-#define Beckhoff_EL3102_Status1 0x00000002, 0x0C1E3052, 0x3101, 1
-#define Beckhoff_EL3102_Input1 0x00000002, 0x0C1E3052, 0x3101, 2
-#define Beckhoff_EL3102_Status2 0x00000002, 0x0C1E3052, 0x3102, 1
-#define Beckhoff_EL3102_Input2 0x00000002, 0x0C1E3052, 0x3102, 2
+#define Beckhoff_EL3102 0x00000002, 0x0C1E3052
+#define Beckhoff_EL3102_PDO_Status1 0x3101, 1
+#define Beckhoff_EL3102_PDO_Input1 0x3101, 2
+#define Beckhoff_EL3102_PDO_Status2 0x3102, 1
+#define Beckhoff_EL3102_PDO_Input2 0x3102, 2
+#define Beckhoff_EL3102_Status1 Beckhoff_EL3102, Beckhoff_EL3102_PDO_Status1
+#define Beckhoff_EL3102_Input1 Beckhoff_EL3102, Beckhoff_EL3102_PDO_Input1
+#define Beckhoff_EL3102_Status2 Beckhoff_EL3102, Beckhoff_EL3102_PDO_Status2
+#define Beckhoff_EL3102_Input2 Beckhoff_EL3102, Beckhoff_EL3102_PDO_Input2
-#define Beckhoff_EL3152_Status1 0x00000002, 0x0C503052, 0x3101, 1
-#define Beckhoff_EL3152_Input1 0x00000002, 0x0C503052, 0x3101, 2
-#define Beckhoff_EL3152_Status2 0x00000002, 0x0C503052, 0x3102, 1
-#define Beckhoff_EL3152_Input2 0x00000002, 0x0C503052, 0x3102, 2
+#define Beckhoff_EL3152 0x00000002, 0x0C503052
+#define Beckhoff_EL3152_PDO_Status1 0x3101, 1
+#define Beckhoff_EL3152_PDO_Input1 0x3101, 2
+#define Beckhoff_EL3152_PDO_Status2 0x3102, 1
+#define Beckhoff_EL3152_PDO_Input2 0x3102, 2
+#define Beckhoff_EL3152_Status1 Beckhoff_EL3152, Beckhoff_EL3152_PDO_Status1
+#define Beckhoff_EL3152_Input1 Beckhoff_EL3152, Beckhoff_EL3152_PDO_Input1
+#define Beckhoff_EL3152_Status2 Beckhoff_EL3152, Beckhoff_EL3152_PDO_Status2
+#define Beckhoff_EL3152_Input2 Beckhoff_EL3152, Beckhoff_EL3152_PDO_Input2
-#define Beckhoff_EL3162_Status1 0x00000002, 0x0C5A3052, 0x3101, 1
-#define Beckhoff_EL3162_Input1 0x00000002, 0x0C5A3052, 0x3101, 2
-#define Beckhoff_EL3162_Status2 0x00000002, 0x0C5A3052, 0x3102, 1
-#define Beckhoff_EL3162_Input2 0x00000002, 0x0C5A3052, 0x3102, 2
+#define Beckhoff_EL3162 0x00000002, 0x0C5A3052
+#define Beckhoff_EL3162_PDO_Status1 0x3101, 1
+#define Beckhoff_EL3162_PDO_Input1 0x3101, 2
+#define Beckhoff_EL3162_PDO_Status2 0x3102, 1
+#define Beckhoff_EL3162_PDO_Input2 0x3102, 2
+#define Beckhoff_EL3162_Status1 Beckhoff_EL3162, Beckhoff_EL3162_PDO_Status1
+#define Beckhoff_EL3162_Input1 Beckhoff_EL3162, Beckhoff_EL3162_PDO_Input1
+#define Beckhoff_EL3162_Status2 Beckhoff_EL3162, Beckhoff_EL3162_PDO_Status2
+#define Beckhoff_EL3162_Input2 Beckhoff_EL3162, Beckhoff_EL3162_PDO_Input2
-#define Beckhoff_EL4102_Output1 0x00000002, 0x10063052, 0x6411, 1
-#define Beckhoff_EL4102_Output2 0x00000002, 0x10063052, 0x6411, 2
+#define Beckhoff_EL4102 0x00000002, 0x10063052
+#define Beckhoff_EL4102_PDO_Output1 0x6411, 1
+#define Beckhoff_EL4102_PDO_Output2 0x6411, 2
+#define Beckhoff_EL4102_Output1 Beckhoff_EL4102, Beckhoff_EL4102_PDO_Output1
+#define Beckhoff_EL4102_Output2 Beckhoff_EL4102, Beckhoff_EL4102_PDO_Output2
-#define Beckhoff_EL4132_Output1 0x00000002, 0x10243052, 0x6411, 1
-#define Beckhoff_EL4132_Output2 0x00000002, 0x10243052, 0x6411, 2
+#define Beckhoff_EL4132 0x00000002, 0x10243052
+#define Beckhoff_EL4132_PDO_Output1 0x6411, 1
+#define Beckhoff_EL4132_PDO_Output2 0x6411, 2
+#define Beckhoff_EL4132_Output1 Beckhoff_EL4132, Beckhoff_EL4132_PDO_Output1
+#define Beckhoff_EL4132_Output2 Beckhoff_EL4132, Beckhoff_EL4132_PDO_Output2
-#define Beckhoff_EL5001_Status 0x00000002, 0x13893052, 0x3101, 1
-#define Beckhoff_EL5001_Value 0x00000002, 0x13893052, 0x3101, 2
+#define Beckhoff_EL5001 0x00000002, 0x13893052
+#define Beckhoff_EL5001_PDO_Status 0x3101, 1
+#define Beckhoff_EL5001_PDO_Value 0x3101, 2
+#define Beckhoff_EL5001_Status Beckhoff_EL5001, Beckhoff_EL5001_PDO_Status
+#define Beckhoff_EL5001_Value Beckhoff_EL5001, Beckhoff_EL5001_PDO_Value
-#define Beckhoff_EL5101_Status 0x00000002, 0x13ED3052, 0x6000, 1
-#define Beckhoff_EL5101_Value 0x00000002, 0x13ED3052, 0x6000, 2
-#define Beckhoff_EL5101_Latch 0x00000002, 0x13ED3052, 0x6000, 3
-#define Beckhoff_EL5101_Frequency 0x00000002, 0x13ED3052, 0x6000, 4
-#define Beckhoff_EL5101_Period 0x00000002, 0x13ED3052, 0x6000, 5
-#define Beckhoff_EL5101_Window 0x00000002, 0x13ED3052, 0x6000, 6
-#define Beckhoff_EL5101_Ctrl 0x00000002, 0x13ED3052, 0x7000, 1
-#define Beckhoff_EL5101_OutputValue 0x00000002, 0x13ED3052, 0x7000, 2
+#define Beckhoff_EL5101 0x00000002, 0x13ED3052
+#define Beckhoff_EL5101_PDO_Status 0x6000, 1
+#define Beckhoff_EL5101_PDO_Value 0x6000, 2
+#define Beckhoff_EL5101_PDO_Latch 0x6000, 3
+#define Beckhoff_EL5101_PDO_Frequency 0x6000, 4
+#define Beckhoff_EL5101_PDO_Period 0x6000, 5
+#define Beckhoff_EL5101_PDO_Window 0x6000, 6
+#define Beckhoff_EL5101_PDO_Ctrl 0x7000, 1
+#define Beckhoff_EL5101_PDO_OutputValue 0x7000, 2
+#define Beckhoff_EL5101_Status Beckhoff_EL5101, Beckhoff_EL5101_PDO_Status
+#define Beckhoff_EL5101_Value Beckhoff_EL5101, Beckhoff_EL5101_PDO_Value
+#define Beckhoff_EL5101_Latch Beckhoff_EL5101, Beckhoff_EL5101_PDO_Latch
+#define Beckhoff_EL5101_Frequency Beckhoff_EL5101, Beckhoff_EL5101_PDO_Frequency
+#define Beckhoff_EL5101_Period Beckhoff_EL5101, Beckhoff_EL5101_PDO_Period
+#define Beckhoff_EL5101_Window Beckhoff_EL5101, Beckhoff_EL5101_PDO_Window
+#define Beckhoff_EL5101_Ctrl Beckhoff_EL5101, Beckhoff_EL5101_PDO_Ctrl
+#define Beckhoff_EL5101_OutputValue Beckhoff_EL5101, Beckhoff_EL5101_PDO_OutputValue
/** \endcond */
--- a/include/ecrt.h Thu Mar 08 18:15:25 2007 +0000
+++ b/include/ecrt.h Fri Mar 09 10:24:50 2007 +0000
@@ -81,9 +81,10 @@
*/
typedef enum {
- EC_BUS_FAILURE, // some slaves offline
- EC_BUS_OK, // all slaves online
- EC_BUS_REDUNDANCY // bus interrupted, but redundancy active
+ EC_BUS_FAILURE = -1, /**< At least one slave with process data exchange
+ is offline. */
+ EC_BUS_OK /**< All slaves with process data exchange are
+ online. */
}
ec_bus_status_t;
@@ -93,22 +94,21 @@
*/
typedef struct {
- ec_bus_status_t bus_status;
- unsigned int bus_tainted;
- unsigned int slaves_responding;
+ ec_bus_status_t bus_status; /**< \see ec_bus_status_t */
+ unsigned int bus_tainted; /**< non-zero, if the bus topology is invalid */
+ unsigned int slaves_responding; /**< number of responging slaves */
}
ec_master_status_t;
/**
- Initialization type for PDO registrations.
- This type is used as a parameter for the ecrt_domain_register_pdo_list()
- function.
-*/
-
-typedef struct
-{
- const char *slave_address; /**< slave address string (see
- ecrt_master_get_slave()) */
+ * List entry for domain PDO registrations.
+ * This type is used as a parameter for the ecrt_domain_register_pdo_list()
+ * convenience function.
+ */
+
+typedef struct {
+ const char *slave_address; /**< slave address string
+ \see ec_master_parse_slave_address() */
uint32_t vendor_id; /**< vendor ID */
uint32_t product_code; /**< product code */
uint16_t pdo_entry_index; /**< PDO entry index */
@@ -118,17 +118,17 @@
ec_pdo_reg_t;
/**
- Direction type for ecrt_domain_register_pdo_range()
-*/
+ * Direction type for PDO mapping and range registration functions.
+ */
typedef enum {
- EC_DIR_OUTPUT,
- EC_DIR_INPUT
+ EC_DIR_OUTPUT, /**< values written by master */
+ EC_DIR_INPUT /**< values read by master */
}
ec_direction_t;
/******************************************************************************
- * Master request functions
+ * Global functions
*****************************************************************************/
ec_master_t *ecrt_request_master(unsigned int master_index);
@@ -145,41 +145,33 @@
ec_domain_t *ecrt_master_create_domain(ec_master_t *master);
+ec_slave_t *ecrt_master_get_slave(const ec_master_t *, const char *,
+ uint32_t vendor_id, uint32_t product_code);
+
int ecrt_master_activate(ec_master_t *master);
void ecrt_master_send(ec_master_t *master);
void ecrt_master_receive(ec_master_t *master);
-ec_slave_t *ecrt_master_get_slave(const ec_master_t *, const char *);
-
void ecrt_master_get_status(const ec_master_t *master, ec_master_status_t *);
/******************************************************************************
* Domain Methods
*****************************************************************************/
-ec_slave_t *ecrt_domain_register_pdo(ec_domain_t *domain,
- const char *address,
- uint32_t vendor_id,
- uint32_t product_code,
- uint16_t pdo_index,
- uint8_t pdo_subindex,
- void **data_ptr);
+int ecrt_domain_register_pdo(ec_domain_t *domain, ec_slave_t *slave,
+ uint16_t pdo_index, uint8_t pdo_subindex, void **data_ptr);
+
+int ecrt_domain_register_pdo_range(ec_domain_t *domain, ec_slave_t *slave,
+ ec_direction_t direction, uint16_t offset, uint16_t length,
+ void **data_ptr);
int ecrt_domain_register_pdo_list(ec_domain_t *domain,
- const ec_pdo_reg_t *pdos);
-
-ec_slave_t *ecrt_domain_register_pdo_range(ec_domain_t *domain,
- const char *address,
- uint32_t vendor_id,
- uint32_t product_code,
- ec_direction_t direction,
- uint16_t offset,
- uint16_t length,
- void **data_ptr);
+ const ec_pdo_reg_t *pdos);
void ecrt_domain_process(ec_domain_t *domain);
void ecrt_domain_queue(ec_domain_t *domain);
+
int ecrt_domain_state(const ec_domain_t *domain);
/******************************************************************************
@@ -202,19 +194,19 @@
*****************************************************************************/
/**
- Read a certain bit of an EtherCAT data byte.
- \param DATA EtherCAT data pointer
- \param POS bit position
-*/
+ * 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
-*/
+ * 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 { \
@@ -227,68 +219,67 @@
*****************************************************************************/
/**
- Read an 8-bit unsigned value from EtherCAT data.
- \return EtherCAT data value
-*/
+ * 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
-*/
+ * 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
-*/
+ * 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
-*/
+ * 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
-*/
+ * 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
-*/
+ * 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)))
-
/******************************************************************************
* Write macros
*****************************************************************************/
/**
- Write an 8-bit unsigned value to EtherCAT data.
- \param DATA EtherCAT data pointer
- \param VAL new value
-*/
+ * 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 { \
@@ -296,18 +287,18 @@
} while (0)
/**
- Write an 8-bit signed value to EtherCAT data.
- \param DATA EtherCAT data pointer
- \param VAL new value
-*/
+ * 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
-*/
+ * 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 { \
@@ -316,18 +307,18 @@
} while (0)
/**
- Write a 16-bit signed value to EtherCAT data.
- \param DATA EtherCAT data pointer
- \param VAL new value
-*/
+ * 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
-*/
+ * 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 { \
@@ -336,10 +327,10 @@
} while (0)
/**
- Write a 32-bit signed value to EtherCAT data.
- \param DATA EtherCAT data pointer
- \param VAL new value
-*/
+ * 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)
--- a/master/domain.c Thu Mar 08 18:15:25 2007 +0000
+++ b/master/domain.c Fri Mar 09 10:24:50 2007 +0000
@@ -236,64 +236,6 @@
/*****************************************************************************/
/**
- Registeres a PDO range.
- \return 0 in case of success, else < 0
-*/
-
-int ec_domain_reg_pdo_range(ec_domain_t *domain, /**< EtherCAT domain */
- ec_slave_t *slave, /**< slave */
- ec_direction_t dir, /**< data direction */
- uint16_t offset, /**< offset */
- uint16_t length, /**< length */
- void **data_ptr /**< pointer to the process data
- pointer */
- )
-{
- ec_data_reg_t *data_reg;
- ec_sync_t *sync;
- uint16_t sync_length;
-
- if (!(sync = ec_slave_get_pdo_sync(slave, dir))) {
- EC_ERR("No sync manager found for PDO range.\n");
- return -1;
- }
-
- // Allocate memory for data registration object
- if (!(data_reg =
- (ec_data_reg_t *) kmalloc(sizeof(ec_data_reg_t), GFP_KERNEL))) {
- EC_ERR("Failed to allocate data registration.\n");
- return -1;
- }
-
- if (ec_slave_prepare_fmmu(slave, domain, sync)) {
- EC_ERR("FMMU configuration failed.\n");
- kfree(data_reg);
- return -1;
- }
-
- data_reg->slave = slave;
- data_reg->sync = sync;
- data_reg->sync_offset = offset;
- data_reg->data_ptr = data_ptr;
-
- // estimate sync manager length
- sync_length = offset + length;
- if (sync->est_length < sync_length) {
- sync->est_length = sync_length;
- if (domain->master->debug_level) {
- EC_DBG("Estimating length of sync manager %i of slave %i to %i.\n",
- sync->index, slave->ring_position, sync_length);
- }
- }
-
- list_add_tail(&data_reg->list, &domain->data_regs);
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/**
Clears the list of the data registrations.
*/
@@ -460,53 +402,44 @@
/**
* Registers a PDO for a domain.
- * \return pointer to the slave on success, else NULL
+ * \return 0 on success, else non-zero
* \ingroup RealtimeInterface
*/
-ec_slave_t *ecrt_domain_register_pdo(
+int ecrt_domain_register_pdo(
ec_domain_t *domain, /**< EtherCAT domain */
- const char *address, /**< ASCII address of the slave,
- see ecrt_master_get_slave() */
- uint32_t vendor_id, /**< vendor ID */
- uint32_t product_code, /**< product code */
- uint16_t entry_index, /**< PDO entry index */
- uint8_t entry_subindex, /**< PDO entry subindex */
+ ec_slave_t *slave, /**< EtherCAT slave */
+ uint16_t pdo_entry_index, /**< PDO entry index */
+ uint8_t pdo_entry_subindex, /**< PDO entry subindex */
void **data_ptr /**< address of the process data pointer */
)
{
- ec_slave_t *slave;
- ec_master_t *master;
ec_sync_t *sync;
const ec_pdo_t *pdo;
const ec_pdo_entry_t *entry;
unsigned int i;
- master = domain->master;
-
- // translate address and validate slave
- if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
- if (ec_slave_validate(slave, vendor_id, product_code)) return NULL;
-
+ // search for PDO entry
for (i = 0; i < slave->sii_sync_count; i++) {
sync = &slave->sii_syncs[i];
list_for_each_entry(pdo, &sync->pdos, list) {
list_for_each_entry(entry, &pdo->entries, list) {
- if (entry->index != entry_index ||
- entry->subindex != entry_subindex) continue;
-
+ if (entry->index != pdo_entry_index ||
+ entry->subindex != pdo_entry_subindex) continue;
+
+ // PDO entry found
if (ec_domain_reg_pdo_entry(domain, sync, entry, data_ptr)) {
- return NULL;
+ return -1;
}
- return slave;
+ return 0;
}
}
}
EC_ERR("PDO entry 0x%04X:%u is not mapped in slave %u.\n",
- entry_index, entry_subindex, slave->ring_position);
- return NULL;
+ pdo_entry_index, pdo_entry_subindex, slave->ring_position);
+ return -1;
}
/*****************************************************************************/
@@ -520,64 +453,82 @@
int ecrt_domain_register_pdo_list(
ec_domain_t *domain, /**< EtherCAT domain */
- const ec_pdo_reg_t *pdos /**< array of PDO registrations */
+ const ec_pdo_reg_t *pdo_regs /**< array of PDO registrations */
)
{
- const ec_pdo_reg_t *pdo;
-
- for (pdo = pdos; pdo->slave_address; pdo++)
- if (!ecrt_domain_register_pdo(domain, pdo->slave_address,
- pdo->vendor_id, pdo->product_code,
- pdo->pdo_entry_index, pdo->pdo_entry_subindex,
- pdo->data_ptr))
+ const ec_pdo_reg_t *reg;
+ ec_slave_t *slave;
+
+ for (reg = pdo_regs; reg->slave_address; reg++) {
+ if (!(slave = ecrt_master_get_slave(domain->master,
+ reg->slave_address, reg->vendor_id,
+ reg->product_code)))
return -1;
+ if (ecrt_domain_register_pdo(domain, slave, reg->pdo_entry_index,
+ reg->pdo_entry_subindex, reg->data_ptr))
+ return -1;
+ }
+
return 0;
}
/*****************************************************************************/
/**
- Registers a PDO range in a domain.
- \return pointer to the slave on success, else NULL
- \ingroup RealtimeInterface
-*/
-
-ec_slave_t *ecrt_domain_register_pdo_range(ec_domain_t *domain,
- /**< EtherCAT domain */
- const char *address,
- /**< ASCII address of the slave,
- see ecrt_master_get_slave() */
- uint32_t vendor_id,
- /**< vendor ID */
- uint32_t product_code,
- /**< product code */
- ec_direction_t direction,
- /**< data direction */
- uint16_t offset,
- /**< offset in slave's PDO range */
- uint16_t length,
- /**< length of this range */
- void **data_ptr
- /**< address of the process data
- pointer */
- )
-{
- ec_slave_t *slave;
- ec_master_t *master;
-
- master = domain->master;
-
- // translate address and validate slave
- if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
- if (ec_slave_validate(slave, vendor_id, product_code)) return NULL;
-
- if (ec_domain_reg_pdo_range(domain, slave,
- direction, offset, length, data_ptr)) {
- return NULL;
- }
-
- return slave;
+ * Registers a PDO range in a domain.
+ * \return 0 on success, else non-zero
+ * \ingroup RealtimeInterface
+ */
+
+int ecrt_domain_register_pdo_range(
+ ec_domain_t *domain, /**< EtherCAT domain */
+ ec_slave_t *slave, /**< EtherCAT slave */
+ ec_direction_t dir, /**< data direction */
+ uint16_t offset, /**< offset in slave's PDO range */
+ uint16_t length, /**< length of this range */
+ void **data_ptr /**< address of the process data pointer */
+ )
+{
+ ec_data_reg_t *data_reg;
+ ec_sync_t *sync;
+ uint16_t sync_length;
+
+ if (!(sync = ec_slave_get_pdo_sync(slave, dir))) {
+ EC_ERR("No sync manager found for PDO range.\n");
+ return -1;
+ }
+
+ // Allocate memory for data registration object
+ if (!(data_reg =
+ (ec_data_reg_t *) kmalloc(sizeof(ec_data_reg_t), GFP_KERNEL))) {
+ EC_ERR("Failed to allocate data registration.\n");
+ return -1;
+ }
+
+ if (ec_slave_prepare_fmmu(slave, domain, sync)) {
+ EC_ERR("FMMU configuration failed.\n");
+ kfree(data_reg);
+ return -1;
+ }
+
+ data_reg->slave = slave;
+ data_reg->sync = sync;
+ data_reg->sync_offset = offset;
+ data_reg->data_ptr = data_ptr;
+
+ // estimate sync manager length
+ sync_length = offset + length;
+ if (sync->est_length < sync_length) {
+ sync->est_length = sync_length;
+ if (domain->master->debug_level) {
+ EC_DBG("Estimating length of sync manager %i of slave %i to %i.\n",
+ sync->index, slave->ring_position, sync_length);
+ }
+ }
+
+ list_add_tail(&data_reg->list, &domain->data_regs);
+ return 0;
}
/*****************************************************************************/
--- a/master/master.c Thu Mar 08 18:15:25 2007 +0000
+++ b/master/master.c Fri Mar 09 10:24:50 2007 +0000
@@ -1384,215 +1384,24 @@
}
}
-/******************************************************************************
- * Realtime interface
- *****************************************************************************/
-
-/**
- Creates a domain.
- \return pointer to new domain on success, else NULL
- \ingroup RealtimeInterface
-*/
-
-ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */)
-{
- ec_domain_t *domain, *last_domain;
- unsigned int index;
-
- if (!(domain = (ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) {
- EC_ERR("Error allocating domain memory!\n");
- return NULL;
- }
-
- if (list_empty(&master->domains)) index = 0;
- else {
- last_domain = list_entry(master->domains.prev, ec_domain_t, list);
- index = last_domain->index + 1;
- }
-
- if (ec_domain_init(domain, master, index)) {
- EC_ERR("Failed to init domain.\n");
- return NULL;
- }
-
- list_add_tail(&domain->list, &master->domains);
-
- return domain;
-}
-
-/*****************************************************************************/
-
-/**
- Configures all slaves and leads them to the OP state.
- Does the complete configuration and activation for all slaves. Sets sync
- managers and FMMUs, and does the appropriate transitions, until the slave
- is operational.
- \return 0 in case of success, else < 0
- \ingroup RealtimeInterface
-*/
-
-int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
-{
- uint32_t domain_offset;
- ec_domain_t *domain;
- ec_fsm_slave_t fsm_slave;
- ec_slave_t *slave;
-
- // allocate all domains
- domain_offset = 0;
- list_for_each_entry(domain, &master->domains, list) {
- if (ec_domain_alloc(domain, domain_offset)) {
- EC_ERR("Failed to allocate domain %X!\n", (u32) domain);
- return -1;
- }
- domain_offset += domain->data_size;
- }
-
- ec_fsm_slave_init(&fsm_slave, &master->fsm_datagram);
-
- // configure all slaves
- list_for_each_entry(slave, &master->slaves, list) {
- ec_fsm_slave_start_conf(&fsm_slave, slave);
- while (ec_fsm_slave_exec(&fsm_slave)) {
- ec_master_queue_datagram(master, &master->fsm_datagram);
- ec_master_sync_io(master);
- }
-
- if (!ec_fsm_slave_success(&fsm_slave)) {
- ec_fsm_slave_clear(&fsm_slave);
- EC_ERR("Failed to configure slave %i!\n", slave->ring_position);
- return -1;
- }
- }
-
- ec_fsm_slave_clear(&fsm_slave);
- ec_master_prepare(master); // prepare asynchronous IO
-
- if (master->debug_level)
- EC_DBG("FSM datagram is %x.\n", (unsigned int) &master->fsm_datagram);
-
- if (ec_master_thread_start(master)) {
- EC_ERR("Failed to start master thread!\n");
- return -1;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/**
- Sends queued datagrams and waits for their reception.
-*/
-
-void ec_master_sync_io(ec_master_t *master /**< EtherCAT master */)
-{
- ec_datagram_t *datagram;
- unsigned int datagrams_sent;
-
- // send all datagrams
- ecrt_master_send(master);
-
- while (1) { // active waiting
- schedule(); // schedule other processes while waiting.
- ecrt_master_receive(master); // receive and dequeue datagrams
-
- // count number of datagrams still waiting for response
- datagrams_sent = 0;
- list_for_each_entry(datagram, &master->datagram_queue, queue) {
- // there may be another process that queued commands
- // in the meantime.
- if (datagram->state == EC_DATAGRAM_QUEUED) continue;
- datagrams_sent++;
- }
-
- // abort loop if there are no more datagrams marked as sent.
- if (!datagrams_sent) break;
- }
-}
-
-/*****************************************************************************/
-
-/**
- Asynchronous sending of datagrams.
- \ingroup RealtimeInterface
-*/
-
-void ecrt_master_send(ec_master_t *master /**< EtherCAT master */)
-{
- ec_datagram_t *datagram, *n;
-
- if (master->injection_seq_rt != master->injection_seq_fsm) {
- // inject datagram produced by master FSM
- ec_master_queue_datagram(master, &master->fsm_datagram);
- master->injection_seq_rt = master->injection_seq_fsm;
- }
-
- if (unlikely(!master->main_device.link_state)) {
- // link is down, no datagram can be sent
- list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
- datagram->state = EC_DATAGRAM_ERROR;
- list_del_init(&datagram->queue);
- }
-
- // query link state
- ec_device_poll(&master->main_device);
- return;
- }
-
- // send frames
- ec_master_send_datagrams(master);
-}
-
-/*****************************************************************************/
-
-/**
- Asynchronous receiving of datagrams.
- \ingroup RealtimeInterface
-*/
-
-void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */)
-{
- ec_datagram_t *datagram, *next;
- cycles_t cycles_timeout;
-
- // receive datagrams
- ec_device_poll(&master->main_device);
-
- cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000);
-
- // dequeue all datagrams that timed out
- list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) {
- if (datagram->state != EC_DATAGRAM_SENT) continue;
-
- if (master->main_device.cycles_poll - datagram->cycles_sent
- > cycles_timeout) {
- list_del_init(&datagram->queue);
- datagram->state = EC_DATAGRAM_TIMED_OUT;
- master->stats.timeouts++;
- ec_master_output_stats(master);
- }
- }
-}
-
-/*****************************************************************************/
-
-/**
- Translates an ASCII coded bus-address to a slave pointer.
- These are the valid addressing schemes:
- - \a "X" = the X. slave on the bus,
- - \a "X:Y" = the Y. slave after the X. branch (bus coupler),
- - \a "#X" = the slave with alias X,
- - \a "#X:Y" = the Y. slave after the branch (bus coupler) with alias X.
- X and Y are zero-based indices and may be provided in hexadecimal or octal
- notation (with respective prefix).
- \return pointer to the slave on success, else NULL
- \ingroup RealtimeInterface
-*/
-
-ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */
- const char *address /**< address string */
- )
+/*****************************************************************************/
+
+/**
+ * Translates an ASCII coded bus-address to a slave pointer.
+ * These are the valid addressing schemes:
+ * - \a "X" = the X. slave on the bus (ring position),
+ * - \a "X:Y" = the Y. slave after the X. branch (bus coupler),
+ * - \a "#X" = the slave with alias X,
+ * - \a "#X:Y" = the Y. slave after the branch (bus coupler) with alias X.
+ * X and Y are zero-based indices and may be provided in hexadecimal or octal
+ * notation (with respective prefix).
+ * \return pointer to the slave on success, else NULL
+ */
+
+ec_slave_t *ec_master_parse_slave_address(
+ const ec_master_t *master, /**< EtherCAT master */
+ const char *address /**< address string */
+ )
{
unsigned long first, second;
char *remainder, *remainder2;
@@ -1685,6 +1494,224 @@
return NULL;
}
+
+/******************************************************************************
+ * Realtime interface
+ *****************************************************************************/
+
+/**
+ Creates a domain.
+ \return pointer to new domain on success, else NULL
+ \ingroup RealtimeInterface
+*/
+
+ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */)
+{
+ ec_domain_t *domain, *last_domain;
+ unsigned int index;
+
+ if (!(domain = (ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) {
+ EC_ERR("Error allocating domain memory!\n");
+ return NULL;
+ }
+
+ if (list_empty(&master->domains)) index = 0;
+ else {
+ last_domain = list_entry(master->domains.prev, ec_domain_t, list);
+ index = last_domain->index + 1;
+ }
+
+ if (ec_domain_init(domain, master, index)) {
+ EC_ERR("Failed to init domain.\n");
+ return NULL;
+ }
+
+ list_add_tail(&domain->list, &master->domains);
+
+ return domain;
+}
+
+/*****************************************************************************/
+
+/**
+ Configures all slaves and leads them to the OP state.
+ Does the complete configuration and activation for all slaves. Sets sync
+ managers and FMMUs, and does the appropriate transitions, until the slave
+ is operational.
+ \return 0 in case of success, else < 0
+ \ingroup RealtimeInterface
+*/
+
+int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
+{
+ uint32_t domain_offset;
+ ec_domain_t *domain;
+ ec_fsm_slave_t fsm_slave;
+ ec_slave_t *slave;
+
+ // allocate all domains
+ domain_offset = 0;
+ list_for_each_entry(domain, &master->domains, list) {
+ if (ec_domain_alloc(domain, domain_offset)) {
+ EC_ERR("Failed to allocate domain %X!\n", (u32) domain);
+ return -1;
+ }
+ domain_offset += domain->data_size;
+ }
+
+ ec_fsm_slave_init(&fsm_slave, &master->fsm_datagram);
+
+ // configure all slaves
+ list_for_each_entry(slave, &master->slaves, list) {
+ ec_fsm_slave_start_conf(&fsm_slave, slave);
+ while (ec_fsm_slave_exec(&fsm_slave)) {
+ ec_master_queue_datagram(master, &master->fsm_datagram);
+ ec_master_sync_io(master);
+ }
+
+ if (!ec_fsm_slave_success(&fsm_slave)) {
+ ec_fsm_slave_clear(&fsm_slave);
+ EC_ERR("Failed to configure slave %i!\n", slave->ring_position);
+ return -1;
+ }
+ }
+
+ ec_fsm_slave_clear(&fsm_slave);
+ ec_master_prepare(master); // prepare asynchronous IO
+
+ if (master->debug_level)
+ EC_DBG("FSM datagram is %x.\n", (unsigned int) &master->fsm_datagram);
+
+ if (ec_master_thread_start(master)) {
+ EC_ERR("Failed to start master thread!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+/**
+ Sends queued datagrams and waits for their reception.
+*/
+
+void ec_master_sync_io(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_datagram_t *datagram;
+ unsigned int datagrams_sent;
+
+ // send all datagrams
+ ecrt_master_send(master);
+
+ while (1) { // active waiting
+ schedule(); // schedule other processes while waiting.
+ ecrt_master_receive(master); // receive and dequeue datagrams
+
+ // count number of datagrams still waiting for response
+ datagrams_sent = 0;
+ list_for_each_entry(datagram, &master->datagram_queue, queue) {
+ // there may be another process that queued commands
+ // in the meantime.
+ if (datagram->state == EC_DATAGRAM_QUEUED) continue;
+ datagrams_sent++;
+ }
+
+ // abort loop if there are no more datagrams marked as sent.
+ if (!datagrams_sent) break;
+ }
+}
+
+/*****************************************************************************/
+
+/**
+ Asynchronous sending of datagrams.
+ \ingroup RealtimeInterface
+*/
+
+void ecrt_master_send(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_datagram_t *datagram, *n;
+
+ if (master->injection_seq_rt != master->injection_seq_fsm) {
+ // inject datagram produced by master FSM
+ ec_master_queue_datagram(master, &master->fsm_datagram);
+ master->injection_seq_rt = master->injection_seq_fsm;
+ }
+
+ if (unlikely(!master->main_device.link_state)) {
+ // link is down, no datagram can be sent
+ list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
+ datagram->state = EC_DATAGRAM_ERROR;
+ list_del_init(&datagram->queue);
+ }
+
+ // query link state
+ ec_device_poll(&master->main_device);
+ return;
+ }
+
+ // send frames
+ ec_master_send_datagrams(master);
+}
+
+/*****************************************************************************/
+
+/**
+ Asynchronous receiving of datagrams.
+ \ingroup RealtimeInterface
+*/
+
+void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */)
+{
+ ec_datagram_t *datagram, *next;
+ cycles_t cycles_timeout;
+
+ // receive datagrams
+ ec_device_poll(&master->main_device);
+
+ cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000);
+
+ // dequeue all datagrams that timed out
+ list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) {
+ if (datagram->state != EC_DATAGRAM_SENT) continue;
+
+ if (master->main_device.cycles_poll - datagram->cycles_sent
+ > cycles_timeout) {
+ list_del_init(&datagram->queue);
+ datagram->state = EC_DATAGRAM_TIMED_OUT;
+ master->stats.timeouts++;
+ ec_master_output_stats(master);
+ }
+ }
+}
+
+/*****************************************************************************/
+
+/**
+ * Obtains a slave pointer by its bus address.
+ * A valid slave pointer is only returned, if vendor ID and product code are
+ * matching.
+ * \return pointer to the slave on success, else NULL
+ * \ingroup RealtimeInterface
+ */
+
+ec_slave_t *ecrt_master_get_slave(
+ const ec_master_t *master, /**< EtherCAT master */
+ const char *address, /**< address string
+ \see ec_master_parse_slave_address() */
+ uint32_t vendor_id, /**< vendor ID */
+ uint32_t product_code /**< product code */
+ )
+{
+ ec_slave_t *slave = ec_master_parse_slave_address(master, address);
+
+ if (!slave)
+ return NULL;
+
+ return ec_slave_validate(slave, vendor_id, product_code) ? NULL : slave;
+}
+
/*****************************************************************************/
/**