ecrt_domain_register_pdo_range() implemented.
authorFlorian Pose <fp@igh-essen.com>
Wed, 18 Oct 2006 13:11:48 +0000
changeset 416 4f007cd2a79d
parent 415 0918aa9bfd0b
child 417 a4193f7ba5b4
ecrt_domain_register_pdo_range() implemented.
examples/mini/mini.c
include/ecdb.h
include/ecrt.h
master/domain.c
master/slave.c
master/slave.h
--- 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)) {
--- 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
--- 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);
 
--- 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);
 
--- 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;
 }
 
 /*****************************************************************************/
--- 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;