Integrate skeleton of allow_overlapping_pdos from af21f0bdc7c9
authorDave Page <dave.page@gleeble.com>
Thu, 26 Mar 2015 15:16:21 -0400
changeset 2609 777d1a8b3a27
parent 2608 ec0b5d9a2ff1
child 2610 f0fdcce9874b
Integrate skeleton of allow_overlapping_pdos from af21f0bdc7c9
Overlapping PDO API added, but not active/working.
No more changes than required to build.
EC_IOCTL_VERSION_MAGIC now 30
include/ecrt.h
lib/slave_config.c
master/ioctl.c
master/ioctl.h
master/slave_config.c
master/slave_config.h
--- a/include/ecrt.h	Mon Mar 16 14:18:55 2015 -0400
+++ b/include/ecrt.h	Thu Mar 26 15:16:21 2015 -0400
@@ -1145,6 +1145,17 @@
                                      */
         );
 
+/** Configure whether a slave allows overlapping PDOs.
+ *
+ * Overlapping PDOs allows inputs to use the same space as outputs on the frame.
+ * This reduces the frame length.
+ */
+void ecrt_slave_config_overlapping_pdos(
+        ec_slave_config_t *sc, /**< Slave configuration. */
+        uint8_t allow_overlapping_pdos /**< Allow overlapping PDOs */
+        );
+
+
 /** Add a PDO to a sync manager's PDO assignment.
  *
  * This method has to be called in non-realtime context before
--- a/lib/slave_config.c	Mon Mar 16 14:18:55 2015 -0400
+++ b/lib/slave_config.c	Thu Mar 26 15:16:21 2015 -0400
@@ -120,6 +120,23 @@
 
 /*****************************************************************************/
 
+void ecrt_slave_config_overlapping_pdos(ec_slave_config_t *sc,
+        uint8_t allow_overlapping_pdos)
+{
+    ec_ioctl_config_t data;
+
+    memset(&data, 0, sizeof(ec_ioctl_config_t));
+    data.config_index = sc->index;
+    data.allow_overlapping_pdos = allow_overlapping_pdos;
+
+    if (ioctl(sc->master->fd, EC_IOCTL_SC_OVERLAPPING_IO, &data) == -1) {
+        fprintf(stderr, "Failed to config overlapping PDOs: %s\n",
+                strerror(errno));
+    }
+}
+
+/*****************************************************************************/
+
 int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
         uint8_t sync_index, uint16_t pdo_index)
 {
--- a/master/ioctl.c	Mon Mar 16 14:18:55 2015 -0400
+++ b/master/ioctl.c	Thu Mar 26 15:16:21 2015 -0400
@@ -2254,6 +2254,48 @@
 
 /*****************************************************************************/
 
+/** Configure wether a slave allows overlapping PDOs.
+ */
+static ATTRIBUTES int ec_ioctl_sc_allow_overlapping_pdos(
+        ec_master_t *master, /**< EtherCAT master. */
+        void *arg, /**< ioctl() argument. */
+        ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
+        )
+{
+    ec_ioctl_config_t data;
+    ec_slave_config_t *sc;
+    int ret = 0;
+
+    if (unlikely(!ctx->requested)) {
+        ret = -EPERM;
+        goto out_return;
+    }
+
+    if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
+        ret = -EFAULT;
+        goto out_return;
+    }
+
+    if (down_interruptible(&master->master_sem)) {
+        ret = -EINTR;
+        goto out_return;
+    }
+
+    if (!(sc = ec_master_get_config(master, data.config_index))) {
+        ret = -ENOENT;
+        goto out_up;
+    }
+
+    ecrt_slave_config_overlapping_pdos(sc,
+            data.allow_overlapping_pdos);
+
+out_up:
+    up(&master->master_sem);
+out_return:
+    return ret;
+}
+/*****************************************************************************/
+
 /** Add a PDO to the assignment.
  *
  * \return Zero on success, otherwise a negative error code.
@@ -4447,6 +4489,13 @@
             }
             ret = ec_ioctl_sc_watchdog(master, arg, ctx);
             break;
+        case EC_IOCTL_SC_OVERLAPPING_IO:
+            if (!ctx->writable) {
+                ret = -EPERM;
+                break;
+            }
+            ret = ec_ioctl_sc_allow_overlapping_pdos(master, arg, ctx);
+            break;
         case EC_IOCTL_SC_ADD_PDO:
             if (!ctx->writable) {
                 ret = -EPERM;
--- a/master/ioctl.h	Mon Mar 16 14:18:55 2015 -0400
+++ b/master/ioctl.h	Thu Mar 26 15:16:21 2015 -0400
@@ -56,7 +56,7 @@
  *
  * Increment this when changing the ioctl interface!
  */
-#define EC_IOCTL_VERSION_MAGIC 29
+#define EC_IOCTL_VERSION_MAGIC 30
 
 // Command-line tool
 #define EC_IOCTL_MODULE                EC_IOR(0x00, ec_ioctl_module_t)
@@ -153,6 +153,7 @@
 #define EC_IOCTL_VOE_EXEC             EC_IOWR(0x57, ec_ioctl_voe_t)
 #define EC_IOCTL_VOE_DATA             EC_IOWR(0x58, ec_ioctl_voe_t)
 #define EC_IOCTL_SET_SEND_INTERVAL     EC_IOW(0x59, size_t)
+#define EC_IOCTL_SC_OVERLAPPING_IO     EC_IOW(0x5a, ec_ioctl_config_t)
 
 /*****************************************************************************/
 
@@ -495,6 +496,7 @@
     int32_t slave_position;
     uint16_t dc_assign_activate;
     ec_sync_signal_t dc_sync[EC_SYNC_SIGNAL_COUNT];
+    uint8_t allow_overlapping_pdos;
 } ec_ioctl_config_t;
 
 /*****************************************************************************/
--- a/master/slave_config.c	Mon Mar 16 14:18:55 2015 -0400
+++ b/master/slave_config.c	Thu Mar 26 15:16:21 2015 -0400
@@ -70,6 +70,7 @@
     sc->vendor_id = vendor_id;
     sc->product_code = product_code;
     sc->watchdog_divider = 0; // use default
+    sc->allow_overlapping_pdos = 0; // default not allowed
     sc->watchdog_intervals = 0; // use default
 
     sc->slave = NULL;
@@ -189,10 +190,41 @@
         return -EOVERFLOW;
     }
 
-    fmmu = &sc->fmmu_configs[sc->used_fmmus++];
+    fmmu = &sc->fmmu_configs[sc->used_fmmus];
 
     down(&sc->master->master_sem);
     ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir);
+
+#if 0 //TODO overlapping PDOs
+    // Overlapping PDO Support from 4751747d4e6d
+    // FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+    // parent code does not call ec_fmmu_config_domain
+    // FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+    fmmu_logical_start_address = domain->tx_size;
+    tx_size = fmmu->data_size;
+
+    // FIXME is it enough to take only the *previous* FMMU into account?
+
+    // FIXME Need to qualify allow_overlapping_pdos with slave->sii.general_flags.enable_not_lrw
+
+    if (sc->allow_overlapping_pdos && sc->used_fmmus > 0) {
+        prev_fmmu = &sc->fmmu_configs[sc->used_fmmus - 1];
+        if (fmmu->dir != prev_fmmu->dir && prev_fmmu->tx_size != 0) {
+            // prev fmmu has opposite direction
+            // and is not already paired with prev-prev fmmu
+            old_prev_tx_size = prev_fmmu->tx_size;
+            prev_fmmu->tx_size = max(fmmu->data_size, prev_fmmu->data_size);
+            domain->tx_size += prev_fmmu->tx_size - old_prev_tx_size;
+            tx_size = 0;
+            fmmu_logical_start_address = prev_fmmu->logical_start_address;
+        }
+    }
+
+    ec_fmmu_config_domain(fmmu, domain, fmmu_logical_start_address, tx_size);
+    // Overlapping PDO Support from 4751747d4e6d
+#endif
+
+    sc->used_fmmus++;
     up(&sc->master->master_sem);
 
     return fmmu->logical_start_address;
@@ -560,6 +592,17 @@
 
 /*****************************************************************************/
 
+void ecrt_slave_config_overlapping_pdos(ec_slave_config_t *sc,
+        uint8_t allow_overlapping_pdos )
+{
+    EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, allow_overlapping_pdos = %u)\n",
+                __func__, sc, allow_overlapping_pdos);
+
+    sc->allow_overlapping_pdos = allow_overlapping_pdos;
+}
+
+/*****************************************************************************/
+
 int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
         uint8_t sync_index, uint16_t pdo_index)
 {
--- a/master/slave_config.h	Mon Mar 16 14:18:55 2015 -0400
+++ b/master/slave_config.h	Thu Mar 26 15:16:21 2015 -0400
@@ -130,6 +130,8 @@
     uint16_t watchdog_intervals; /**< Process data watchdog intervals (see
                                    spec. reg. 0x0420). */
 
+    uint8_t allow_overlapping_pdos;	/**< Allow input PDOs use the same frame space
+                                      as output PDOs. */
     ec_slave_t *slave; /**< Slave pointer. This is \a NULL, if the slave is
                          offline. */