# HG changeset patch # User Florian Pose # Date 1161177108 0 # Node ID 4f007cd2a79d4cba1311a400ec82ac3c51cebb85 # Parent 0918aa9bfd0bd032dc84753eb7fc749b8825e37f ecrt_domain_register_pdo_range() implemented. diff -r 0918aa9bfd0b -r 4f007cd2a79d examples/mini/mini.c --- a/examples/mini/mini.c Wed Oct 18 13:10:06 2006 +0000 +++ b/examples/mini/mini.c Wed Oct 18 13:11:48 2006 +0000 @@ -56,23 +56,23 @@ spinlock_t master_lock = SPIN_LOCK_UNLOCKED; // data fields -void *r_ana_out; - -// channels -uint32_t k_pos; -uint8_t k_stat; - +void *r_inputs; +void *r_outputs; + +#if 0 ec_pdo_reg_t domain1_pdos[] = { {"2", Beckhoff_EL4132_Output1, &r_ana_out}, {"3", Beckhoff_EL5001_Value, NULL}, {} }; +#endif /*****************************************************************************/ void run(unsigned long data) { static unsigned int counter = 0; + static unsigned int einaus = 0; spin_lock(&master_lock); @@ -82,6 +82,8 @@ // process data //k_pos = EC_READ_U32(r_ssi); + EC_WRITE_U8(r_outputs + 2, einaus ? 0xFF : 0x00); + // send ecrt_master_run(master); @@ -94,10 +96,7 @@ } else { counter = FREQUENCY; - //printk(KERN_INFO "input = "); - //for (i = 0; i < 22; i++) - // printk("%02X ", *((uint8_t *) r_kbus_in + i)); - //printk("\n"); + einaus = !einaus; } // restart timer @@ -124,7 +123,7 @@ int __init init_mini_module(void) { - ec_slave_t *slave; + // ec_slave_t *slave; printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n"); @@ -143,16 +142,30 @@ } printk(KERN_INFO "Registering PDOs...\n"); +#if 0 if (ecrt_domain_register_pdo_list(domain1, domain1_pdos)) { printk(KERN_ERR "PDO registration failed!\n"); goto out_release_master; } - +#endif + if (!ecrt_domain_register_pdo_range(domain1, "0", Beckhoff_BK1120, + EC_DIR_OUTPUT, 0, 4, &r_outputs)) { + printk(KERN_ERR "PDO registration failed!\n"); + goto out_release_master; + } + if (!ecrt_domain_register_pdo_range(domain1, "0", Beckhoff_BK1120, + EC_DIR_INPUT, 0, 4, &r_inputs)) { + printk(KERN_ERR "PDO registration failed!\n"); + goto out_release_master; + } + +#if 0 if (!(slave = ecrt_master_get_slave(master, "3"))) goto out_release_master; if (ecrt_slave_conf_sdo8(slave, 0x4061, 1, 0)) goto out_release_master; +#endif printk(KERN_INFO "Activating master...\n"); if (ecrt_master_activate(master)) { diff -r 0918aa9bfd0b -r 4f007cd2a79d include/ecdb.h --- a/include/ecdb.h Wed Oct 18 13:10:06 2006 +0000 +++ b/include/ecdb.h Wed Oct 18 13:11:48 2006 +0000 @@ -45,6 +45,8 @@ /** \cond */ +#define Beckhoff_BK1120 0x00000002, 0x04602C22 + #define Beckhoff_EL1004_Inputs 0x00000002, 0x03EC3052, 0x3101, 1 #define Beckhoff_EL1014_Inputs 0x00000002, 0x03F63052, 0x3101, 1 diff -r 0918aa9bfd0b -r 4f007cd2a79d include/ecrt.h --- a/include/ecrt.h Wed Oct 18 13:10:06 2006 +0000 +++ b/include/ecrt.h Wed Oct 18 13:11:48 2006 +0000 @@ -86,6 +86,12 @@ } ec_pdo_reg_t; +/** + Direction type for ec_domain_register_pdo_range() +*/ + +typedef enum {EC_DIR_INPUT, EC_DIR_OUTPUT} ec_direction_t; + /****************************************************************************** * Master request functions *****************************************************************************/ @@ -127,9 +133,19 @@ uint16_t pdo_index, uint8_t pdo_subindex, 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); + void ecrt_domain_process(ec_domain_t *domain); int ecrt_domain_state(const ec_domain_t *domain); diff -r 0918aa9bfd0b -r 4f007cd2a79d master/domain.c --- a/master/domain.c Wed Oct 18 13:10:06 2006 +0000 +++ b/master/domain.c Wed Oct 18 13:11:48 2006 +0000 @@ -188,7 +188,7 @@ return -1; } - // Calculate offset for process data pointer + // Calculate offset (in sync manager) for process data pointer bit_offset = 0; byte_offset = 0; list_for_each_entry(other_pdo, &slave->sii_pdos, list) { @@ -228,6 +228,81 @@ /*****************************************************************************/ /** + 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_sii_sync_t *sync; + unsigned int sync_found, sync_index; + uint16_t sync_length; + + switch (dir) { + case EC_DIR_OUTPUT: sync_index = 2; break; + case EC_DIR_INPUT: sync_index = 3; break; + default: + EC_ERR("Invalid direction!\n"); + return -1; + } + + // Find sync manager + sync_found = 0; + list_for_each_entry(sync, &slave->sii_syncs, list) { + if (sync->index == sync_index) { + sync_found = 1; + break; + } + } + + if (!sync_found) { + 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. */ @@ -499,6 +574,58 @@ /*****************************************************************************/ /** + Registers a PDO range in a domain. + - If \a data_ptr is NULL, the slave is only validated. + \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 (!data_ptr) { + // data_ptr is NULL => mark slave as "registered" (do not warn) + slave->registered = 1; + return slave; + } + + if (ec_domain_reg_pdo_range(domain, slave, + direction, offset, length, data_ptr)) { + return NULL; + } + + return slave; +} + +/*****************************************************************************/ + +/** Processes received process data and requeues the domain datagram(s). \ingroup RealtimeInterface */ @@ -561,6 +688,7 @@ EXPORT_SYMBOL(ecrt_domain_register_pdo); EXPORT_SYMBOL(ecrt_domain_register_pdo_list); +EXPORT_SYMBOL(ecrt_domain_register_pdo_range); EXPORT_SYMBOL(ecrt_domain_process); EXPORT_SYMBOL(ecrt_domain_state); diff -r 0918aa9bfd0b -r 4f007cd2a79d master/slave.c --- a/master/slave.c Wed Oct 18 13:10:06 2006 +0000 +++ b/master/slave.c Wed Oct 18 13:11:48 2006 +0000 @@ -327,6 +327,8 @@ sync->control_register = EC_READ_U8 (data + 4); sync->enable = EC_READ_U8 (data + 6); + sync->est_length = 0; + list_add_tail(&sync->list, &slave->sii_syncs); } @@ -825,9 +827,10 @@ { ec_sii_pdo_t *pdo; ec_sii_pdo_entry_t *pdo_entry; - unsigned int bit_size; + unsigned int bit_size, byte_size; if (sync->length) return sync->length; + if (sync->est_length) return sync->est_length; bit_size = 0; list_for_each_entry(pdo, &slave->sii_pdos, list) { @@ -839,9 +842,11 @@ } if (bit_size % 8) // round up to full bytes - return bit_size / 8 + 1; + byte_size = bit_size / 8 + 1; else - return bit_size / 8; + byte_size = bit_size / 8; + + return byte_size; } /*****************************************************************************/ diff -r 0918aa9bfd0b -r 4f007cd2a79d master/slave.h --- a/master/slave.h Wed Oct 18 13:10:06 2006 +0000 +++ b/master/slave.h Wed Oct 18 13:11:48 2006 +0000 @@ -116,6 +116,9 @@ uint16_t length; /**< data length in bytes */ uint8_t control_register; /**< control register value */ uint8_t enable; /**< enable bit */ + uint16_t est_length; /**< Estimated length. This is no field of the SII, + but it is used to calculate the length via + PDO ranges */ } ec_sii_sync_t;