Added ecrt_slave_config_reg_so_entry_pos() to register non-unique entries.
This commit is contained in:
parent
23c725a79c
commit
ebf9c296f3
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue