From b8c5ff836d177d1f8e856fdc46038a5fca717e57 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 26 Mar 2015 15:16:21 -0400 Subject: [PATCH] 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 | 11 ++++++++++ lib/slave_config.c | 17 +++++++++++++++ master/ioctl.c | 49 +++++++++++++++++++++++++++++++++++++++++++ master/ioctl.h | 4 +++- master/slave_config.c | 45 ++++++++++++++++++++++++++++++++++++++- master/slave_config.h | 2 ++ 6 files changed, 126 insertions(+), 2 deletions(-) diff --git a/include/ecrt.h b/include/ecrt.h index 283adf06..cd4e1a3f 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -1145,6 +1145,17 @@ void ecrt_slave_config_watchdog( */ ); +/** 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 diff --git a/lib/slave_config.c b/lib/slave_config.c index 943ca2bb..e7d5095c 100644 --- a/lib/slave_config.c +++ b/lib/slave_config.c @@ -120,6 +120,23 @@ void ecrt_slave_config_watchdog(ec_slave_config_t *sc, /*****************************************************************************/ +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) { diff --git a/master/ioctl.c b/master/ioctl.c index f3789ad2..6a7b8882 100644 --- a/master/ioctl.c +++ b/master/ioctl.c @@ -2254,6 +2254,48 @@ out_return: /*****************************************************************************/ +/** 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 @@ long EC_IOCTL( } 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; diff --git a/master/ioctl.h b/master/ioctl.h index 032e7f8e..8fe55e62 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -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 @@ typedef struct { 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; /*****************************************************************************/ diff --git a/master/slave_config.c b/master/slave_config.c index 38347872..3d53df7e 100644 --- a/master/slave_config.c +++ b/master/slave_config.c @@ -70,6 +70,7 @@ void ec_slave_config_init( 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 @@ int ec_slave_config_prepare_fmmu( 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_watchdog(ec_slave_config_t *sc, /*****************************************************************************/ +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) { diff --git a/master/slave_config.h b/master/slave_config.h index 9fd633dc..a68b79a0 100644 --- a/master/slave_config.h +++ b/master/slave_config.h @@ -130,6 +130,8 @@ struct ec_slave_config { 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. */