Added ecrt_slave_config_reg_so_entry_pos() to register non-unique entries.

This commit is contained in:
Florian Pose 2013-02-05 16:45:34 +01:00
parent 23c725a79c
commit ebf9c296f3
5 changed files with 238 additions and 35 deletions

View File

@ -66,6 +66,9 @@
* clock to the reference clock.
* - Changed the datatypes of the shift times in ecrt_slave_config_dc() to
* int32_t to correctly display negative shift times.
* - Added ecrt_slave_config_reg_pdo_entry_pos() and the feature flag
* EC_HAVE_REG_BY_POS for registering PDO entries with non-unique indices
* via their positions in the mapping.
*
* Changes in version 1.5:
*
@ -180,6 +183,10 @@
*/
#define EC_HAVE_REF_CLOCK_TIME
/* Defined if the method ecrt_slave_config_reg_pdo_entry_pos() is available.
*/
#define EC_HAVE_REG_BY_POS
/*****************************************************************************/
/** End of list marker.
@ -1260,6 +1267,26 @@ int ecrt_slave_config_reg_pdo_entry(
is desired */
);
/** Registers a PDO entry using its position.
*
* Similar to ecrt_slave_config_reg_pdo_entry(), but not using PDO indices but
* offsets in the PDO mapping, because PDO entry indices may not be unique
* inside a slave's PDO mapping. An error is raised, if
* one of the given positions is out of range.
*
* \retval >=0 Success: Offset of the PDO entry's process data.
* \retval <0 Error code.
*/
int ecrt_slave_config_reg_pdo_entry_pos(
ec_slave_config_t *sc, /**< Slave configuration. */
uint8_t sync_index, /**< Sync manager index. */
unsigned int pdo_pos, /**< Position of the PDO inside the SM. */
unsigned int entry_pos, /**< Position of the entry inside the PDO. */
ec_domain_t *domain, /**< Domain. */
unsigned int *bit_position /**< Optional address if bit addressing
is desired */
);
/** Configure distributed clocks.
*
* Sets the AssignActivate word and the cycle and shift times for the sync

View File

@ -305,6 +305,47 @@ int ecrt_slave_config_reg_pdo_entry(
/*****************************************************************************/
int ecrt_slave_config_reg_pdo_entry_pos(
ec_slave_config_t *sc,
uint8_t sync_index,
unsigned int pdo_pos,
unsigned int entry_pos,
ec_domain_t *domain,
unsigned int *bit_position
)
{
ec_ioctl_reg_pdo_pos_t io;
int ret;
io.config_index = sc->index;
io.sync_index = sync_index;
io.pdo_pos = pdo_pos;
io.entry_pos = entry_pos;
io.domain_index = domain->index;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_REG_PDO_POS, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to register PDO entry: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
if (bit_position) {
*bit_position = io.bit_position;
} else {
if (io.bit_position) {
fprintf(stderr, "PDO entry %u/%u/%u does not byte-align "
"in config %u:%u.\n", sync_index, pdo_pos, entry_pos,
sc->alias, sc->position);
return -EFAULT;
}
}
return ret;
}
/*****************************************************************************/
void ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate,
uint32_t sync0_cycle_time, int32_t sync0_shift_time,
uint32_t sync1_cycle_time, int32_t sync1_shift_time)

View File

@ -2246,6 +2246,54 @@ static ATTRIBUTES int ec_ioctl_sc_reg_pdo_entry(
/*****************************************************************************/
/** Registers a PDO entry by its position.
*/
static ATTRIBUTES int ec_ioctl_sc_reg_pdo_pos(
ec_master_t *master, /**< EtherCAT master. */
void *arg, /**< ioctl() argument. */
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
ec_ioctl_reg_pdo_pos_t io;
ec_slave_config_t *sc;
ec_domain_t *domain;
int ret;
if (unlikely(!ctx->requested)) {
return -EPERM;
}
if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
return -EFAULT;
}
if (down_interruptible(&master->master_sem)) {
return -EINTR;
}
if (!(sc = ec_master_get_config(master, io.config_index))) {
up(&master->master_sem);
return -ENOENT;
}
if (!(domain = ec_master_find_domain(master, io.domain_index))) {
up(&master->master_sem);
return -ENOENT;
}
up(&master->master_sem); /** \fixme sc or domain could be invalidated */
ret = ecrt_slave_config_reg_pdo_entry_pos(sc, io.sync_index,
io.pdo_pos, io.entry_pos, domain, &io.bit_position);
if (copy_to_user((void __user *) arg, &io, sizeof(io)))
return -EFAULT;
return ret;
}
/*****************************************************************************/
/** Sets the DC AssignActivate word and the sync signal times.
*/
static ATTRIBUTES int ec_ioctl_sc_dc(
@ -4149,6 +4197,13 @@ long EC_IOCTL(ec_master_t *master, ec_ioctl_context_t *ctx,
}
ret = ec_ioctl_sc_reg_pdo_entry(master, arg, ctx);
break;
case EC_IOCTL_SC_REG_PDO_POS:
if (!ctx->writable) {
ret = -EPERM;
break;
}
ret = ec_ioctl_sc_reg_pdo_pos(master, arg, ctx);
break;
case EC_IOCTL_SC_DC:
if (!ctx->writable) {
ret = -EPERM;

View File

@ -56,7 +56,7 @@
*
* Increment this when changing the ioctl interface!
*/
#define EC_IOCTL_VERSION_MAGIC 26
#define EC_IOCTL_VERSION_MAGIC 27
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@ -117,40 +117,41 @@
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x33, ec_ioctl_add_pdo_entry_t)
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x34, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x35, ec_ioctl_reg_pdo_entry_t)
#define EC_IOCTL_SC_DC EC_IOW(0x36, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x37, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x38, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x39, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x3a, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x3b, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x3c, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x3d, ec_ioctl_reg_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x3e, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x3f, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x40, ec_ioctl_sc_idn_t)
#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x41)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x42)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x43)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x44)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x45, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x46, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x47, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x48, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x49, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x4a, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x4b, ec_ioctl_sdo_request_t)
#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x4c, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x4d, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x4e, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x4f, ec_ioctl_reg_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x50, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x51, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x52, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x53, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x54, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x55, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x56, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x57, size_t)
#define EC_IOCTL_SC_REG_PDO_POS EC_IOWR(0x36, ec_ioctl_reg_pdo_pos_t)
#define EC_IOCTL_SC_DC EC_IOW(0x37, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x38, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x39, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x3a, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x3b, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x3c, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x3d, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x3e, ec_ioctl_reg_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x3f, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x40, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x41, ec_ioctl_sc_idn_t)
#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x42)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x43)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x44)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x45)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x46, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x47, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x48, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x49, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x4a, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x4b, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x4c, ec_ioctl_sdo_request_t)
#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x4d, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x4e, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x4f, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x50, ec_ioctl_reg_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x51, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x52, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x53, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x54, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x55, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x56, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x57, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x58, size_t)
/*****************************************************************************/
@ -620,6 +621,20 @@ typedef struct {
/*****************************************************************************/
typedef struct {
// inputs
uint32_t config_index;
uint32_t sync_index;
uint32_t pdo_pos;
uint32_t entry_pos;
uint32_t domain_index;
// outputs
unsigned int bit_position;
} ec_ioctl_reg_pdo_pos_t;
/*****************************************************************************/
typedef struct {
// inputs
uint32_t config_index;

View File

@ -781,6 +781,71 @@ int ecrt_slave_config_reg_pdo_entry(
/*****************************************************************************/
int ecrt_slave_config_reg_pdo_entry_pos(
ec_slave_config_t *sc,
uint8_t sync_index,
unsigned int pdo_pos,
unsigned int entry_pos,
ec_domain_t *domain,
unsigned int *bit_position
)
{
const ec_sync_config_t *sync_config;
unsigned int bit_offset, pp, ep;
ec_pdo_t *pdo;
ec_pdo_entry_t *entry;
EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, sync_index = %u, pdo_pos = %u,"
" entry_pos = %u, domain = 0x%p, bit_position = 0x%p)\n",
__func__, sc, sync_index, pdo_pos, entry_pos,
domain, bit_position);
if (sync_index >= EC_MAX_SYNC_MANAGERS) {
EC_CONFIG_ERR(sc, "Invalid syncmanager position %u.\n", sync_index);
return -EINVAL;
}
sync_config = &sc->sync_configs[sync_index];
bit_offset = 0;
pp = 0;
list_for_each_entry(pdo, &sync_config->pdos.list, list) {
ep = 0;
list_for_each_entry(entry, &pdo->entries, list) {
if (pp != pdo_pos || ep != entry_pos) {
bit_offset += entry->bit_length;
} else {
unsigned int bit_pos = bit_offset % 8;
int sync_offset;
if (bit_position) {
*bit_position = bit_pos;
} else if (bit_pos) {
EC_CONFIG_ERR(sc, "PDO entry 0x%04X:%02X does"
" not byte-align.\n",
pdo->index, entry->subindex);
return -EFAULT;
}
sync_offset = ec_slave_config_prepare_fmmu(
sc, domain, sync_index, sync_config->dir);
if (sync_offset < 0)
return sync_offset;
return sync_offset + bit_offset / 8;
}
ep++;
}
pp++;
}
EC_CONFIG_ERR(sc, "PDO entry specification %u/%u/%u out of range.\n",
sync_index, pdo_pos, entry_pos);
return -ENOENT;
}
/*****************************************************************************/
void ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate,
uint32_t sync0_cycle_time, int32_t sync0_shift_time,
uint32_t sync1_cycle_time, int32_t sync1_shift_time)