mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-02-06 03:41:52 +08:00
Store sync manager configurations in ec_slave_config_t instead of Pdo
lists for each direction; changed realtime interface to allow sync manager configuration.
This commit is contained in:
129
include/ecrt.h
129
include/ecrt.h
@@ -220,44 +220,63 @@ typedef struct {
|
||||
/** Direction type for Pdo assignment functions.
|
||||
*/
|
||||
typedef enum {
|
||||
EC_DIR_INVALID, /**< Invalid direction. Do not use this value. */
|
||||
EC_DIR_OUTPUT, /**< Values written by the master. */
|
||||
EC_DIR_INPUT /**< Values read by the master. */
|
||||
EC_DIR_INPUT, /**< Values read by the master. */
|
||||
EC_DIR_COUNT /**< Number of directions. For internal use only. */
|
||||
} ec_direction_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Pdo entry information.
|
||||
/** Pdo entry configuration information.
|
||||
*
|
||||
* This can be used to map multiple Pdo entries into a given Pdo using
|
||||
* ecrt_slave_config_pdos().
|
||||
* This is the data type of the \a entries field in ec_pdo_info_t.
|
||||
*
|
||||
* \see ecrt_slave_config_sync_managers().
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t index; /**< Index of the Pdo entry to add to the Pdo
|
||||
mapping. */
|
||||
uint8_t subindex; /**< Subindex of the Pdo entry. */
|
||||
uint16_t index; /**< Pdo entry index. */
|
||||
uint8_t subindex; /**< Pdo entry subindex. */
|
||||
uint8_t bit_length; /**< Size of the Pdo entry in bit. */
|
||||
} ec_pdo_entry_info_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Pdo information.
|
||||
*
|
||||
* This can be use to assign multiple Pdos to a sync manager using
|
||||
* ecrt_slave_config_pdos().
|
||||
/** Pdo configuration information.
|
||||
*
|
||||
* This is the data type of the \a pdos field in ec_sync_info_t.
|
||||
*
|
||||
* \see ecrt_slave_config_sync_managers().
|
||||
*/
|
||||
typedef struct {
|
||||
ec_direction_t dir; /**< Pdo direction (input/output). */
|
||||
uint16_t index; /**< Index of the Pdo to assign. */
|
||||
unsigned int n_entries; /**< Number of Pdo entries in \a entries to map.
|
||||
uint16_t index; /**< Pdo index. */
|
||||
uint8_t n_entries; /**< Number of Pdo entries in \a entries to map.
|
||||
Zero means, that the default mapping shall be
|
||||
used (this can only be done if the slave is
|
||||
present at bus configuration time). */
|
||||
ec_pdo_entry_info_t *entries; /**< Array of Pdo entries to map. This must
|
||||
contain at least \a n_entries values. */
|
||||
ec_pdo_entry_info_t *entries; /**< Array of Pdo entries to map. Can either
|
||||
be \a NULL, or must contain at
|
||||
least \a n_entries values. */
|
||||
} ec_pdo_info_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Sync manager configuration information.
|
||||
*
|
||||
* This can be use to configure multiple sync managers including the Pdo
|
||||
* assignment and Pdo mapping. It is used as an input parameter type in
|
||||
* ecrt_slave_config_sync_managers().
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t index; /**< Sync manager index. */
|
||||
ec_direction_t dir; /**< Sync manager direction. */
|
||||
uint16_t n_pdos; /**< Number of Pdos in \a pdos. */
|
||||
ec_pdo_info_t *pdos; /**< Array with Pdos to assign. This must contain
|
||||
at least \a n_pdos Pdos. */
|
||||
} ec_sync_info_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** List record type for Pdo entry mass-registration.
|
||||
*
|
||||
* This type is used for the array parameter of the
|
||||
@@ -426,30 +445,46 @@ void ecrt_master_state(
|
||||
* Slave configuration methods
|
||||
*****************************************************************************/
|
||||
|
||||
/** Configure a sync manager.
|
||||
*
|
||||
* Sets the direction of a sync manager. The direction bits from the default
|
||||
* control register from SII will be overriden, when this function is called.
|
||||
*
|
||||
* \return zero on success, else non-zero
|
||||
*/
|
||||
int ecrt_slave_config_sync_manager(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
uint8_t sync_index, /**< Sync manager index. */
|
||||
ec_direction_t dir /**< Input/Output. */
|
||||
);
|
||||
|
||||
/** Add a Pdo to a sync manager's Pdo assignment.
|
||||
*
|
||||
* \see ecrt_slave_config_pdos()
|
||||
* \see ecrt_slave_config_sync_managers()
|
||||
* \return zero on success, else non-zero
|
||||
*/
|
||||
int ecrt_slave_config_pdo_assign_add(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
ec_direction_t dir, /**< Sync manager direction (input/output). */
|
||||
uint8_t sync_index, /**< Sync manager index. */
|
||||
uint16_t index /**< Index of the Pdo to assign. */
|
||||
);
|
||||
|
||||
/** Clear a sync manager's Pdo assignment.
|
||||
*
|
||||
* This can be called before assigning Pdos via
|
||||
* ecrt_slave_config_pdo_assign_add(), to clear the default assignment.
|
||||
* ecrt_slave_config_pdo_assign_add(), to clear the default assignment of a
|
||||
* sync manager.
|
||||
*
|
||||
* \see ecrt_slave_config_sync_managers()
|
||||
*/
|
||||
void ecrt_slave_config_pdo_assign_clear(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
ec_direction_t dir /**< Sync manager direction (input/output). */
|
||||
uint8_t sync_index /**< Sync manager index. */
|
||||
);
|
||||
|
||||
/** Add a Pdo entry to the given Pdo's mapping.
|
||||
*
|
||||
* \see ecrt_slave_config_pdos()
|
||||
* \see ecrt_slave_config_sync_managers()
|
||||
* \return zero on success, else non-zero
|
||||
*/
|
||||
int ecrt_slave_config_pdo_mapping_add(
|
||||
@@ -466,21 +501,23 @@ int ecrt_slave_config_pdo_mapping_add(
|
||||
*
|
||||
* This can be called before mapping Pdo entries via
|
||||
* ecrt_slave_config_pdo_mapping_add(), to clear the default mapping.
|
||||
*
|
||||
* \see ecrt_slave_config_sync_managers()
|
||||
*/
|
||||
void ecrt_slave_config_pdo_mapping_clear(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
uint16_t pdo_index /**< Index of the Pdo. */
|
||||
);
|
||||
|
||||
/** Specify the Pdo assignment and (optionally) the Pdo mappings.
|
||||
/** Specify a complete Pdo configuration.
|
||||
*
|
||||
* This function is a convenience wrapper for the functions
|
||||
* ecrt_slave_config_pdo_assign_clear(), ecrt_slave_config_pdo_assign_add(),
|
||||
* ecrt_slave_config_pdo_mapping_clear() and
|
||||
* ecrt_slave_config_pdo_mapping_add(), that are better suitable for automatic
|
||||
* code generation.
|
||||
* ecrt_slave_config_sync_manager(), ecrt_slave_config_pdo_assign_clear(),
|
||||
* ecrt_slave_config_pdo_assign_add(), ecrt_slave_config_pdo_mapping_clear()
|
||||
* and ecrt_slave_config_pdo_mapping_add(), that are better suitable for
|
||||
* automatic code generation.
|
||||
*
|
||||
* The following example shows, how to specify a complete Pdo assignment
|
||||
* The following example shows, how to specify a complete configuration,
|
||||
* including the Pdo mappings. With this information, the master is able to
|
||||
* reserve the complete process data, even if the slave is not present at
|
||||
* configuration time:
|
||||
@@ -497,41 +534,51 @@ void ecrt_slave_config_pdo_mapping_clear(
|
||||
* };
|
||||
*
|
||||
* const ec_pdo_info_t el3162_pdos[] = {
|
||||
* {EC_DIR_INPUT, 0x1A00, 2, el3162_channel1},
|
||||
* {EC_DIR_INPUT, 0x1A01, 2, el3162_channel2},
|
||||
* {0x1A00, 2, el3162_channel1},
|
||||
* {0x1A01, 2, el3162_channel2},
|
||||
* };
|
||||
*
|
||||
* if (ecrt_slave_config_pdos(sc, 2, el3162_pdos))
|
||||
* const ec_pdo_info_t el3162_syncs[] = {
|
||||
* {2, EC_DIR_INPUT, 2, el3162_el3162_pdos},
|
||||
* };
|
||||
*
|
||||
* if (ecrt_slave_config_syncs(sc, 1, el3162_syncs))
|
||||
* return -1; // error
|
||||
* \endcode
|
||||
*
|
||||
* The next example shows, how to configure only the Pdo assignment. The
|
||||
* The next example shows, how to configure the Pdo assignment only. The
|
||||
* entries for each assigned Pdo are taken from the Pdo's default mapping.
|
||||
* Please note, that Pdo entry registration will fail, if the Pdo
|
||||
* configuration is left empty and the slave is offline.
|
||||
*
|
||||
* \code
|
||||
* const ec_pdo_info_t pdos[] = {
|
||||
* {EC_DIR_INPUT, 0x1600}, // Channel 1
|
||||
* {EC_DIR_INPUT, 0x1601} // Channel 2
|
||||
* {0x1600}, // Channel 1
|
||||
* {0x1601} // Channel 2
|
||||
* };
|
||||
*
|
||||
* if (ecrt_slave_config_pdos(slave_config_ana_in, 2, pdos))
|
||||
* const ec_sync_info_t syncs[] = {
|
||||
* {2, EC_DIR_INPUT, 2, pdos},
|
||||
* };
|
||||
*
|
||||
* if (ecrt_slave_config_pdos(slave_config_ana_in, 2, syncs))
|
||||
* return -1; // error
|
||||
* \endcode
|
||||
*
|
||||
* Processing of \a pdo_infos will stop, if
|
||||
* - the number of processed items reaches \a n_infos, or
|
||||
* - the \a dir member of an ec_pdo_info_t item is EC_END. In this case,
|
||||
* \a n_infos should set to a number greater than the number of list items;
|
||||
* Processing of \a syncs will stop, if
|
||||
* - the number of processed items reaches \a n_syncs, or
|
||||
* - the \a index member of an ec_sync_info_t item is 0xff. In this case,
|
||||
* \a n_syncs should set to a number greater than the number of list items;
|
||||
* using EC_END is recommended.
|
||||
*
|
||||
* \return zero on success, else non-zero
|
||||
*/
|
||||
int ecrt_slave_config_pdos(
|
||||
int ecrt_slave_config_sync_managers(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
unsigned int n_infos, /**< Number of Pdo infos in \a pdo_infos. */
|
||||
const ec_pdo_info_t pdo_infos[] /**< List with Pdos. */
|
||||
unsigned int n_syncs, /**< Number of sync manager configurations in
|
||||
\a syncs. */
|
||||
const ec_sync_info_t syncs[] /**< Array of sync manager
|
||||
configurations. */
|
||||
);
|
||||
|
||||
/** Registers a Pdo entry for process data exchange in a domain.
|
||||
|
||||
@@ -61,7 +61,8 @@ ec_master-objs := \
|
||||
sdo_request.o \
|
||||
slave.o \
|
||||
slave_config.o \
|
||||
sync.o
|
||||
sync.o \
|
||||
sync_config.o
|
||||
|
||||
ifeq (@ENABLE_EOE@,1)
|
||||
ec_master-objs += ethernet.o
|
||||
|
||||
@@ -63,7 +63,8 @@ EXTRA_DIST = \
|
||||
sdo_request.c sdo_request.h \
|
||||
slave.c slave.h \
|
||||
slave_config.c slave_config.h \
|
||||
sync.c sync.h
|
||||
sync.c sync.h \
|
||||
sync_config.c sync_config.h
|
||||
|
||||
modules:
|
||||
$(MAKE) -C "@abs_top_srcdir@" modules
|
||||
|
||||
@@ -243,7 +243,7 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
sync = &slave->sii.syncs[data.sync_index];
|
||||
|
||||
data.physical_start_address = sync->physical_start_address;
|
||||
data.default_size = sync->length;
|
||||
data.default_size = sync->default_length;
|
||||
data.control_register = sync->control_register;
|
||||
data.enable = sync->enable;
|
||||
data.assign_source = sync->assign_source;
|
||||
@@ -290,7 +290,6 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
data.dir = pdo->dir;
|
||||
data.index = pdo->index;
|
||||
data.entry_count = ec_pdo_entry_count(pdo);
|
||||
|
||||
@@ -420,7 +419,8 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
|
||||
data.slave_config_alias = fmmu->sc->alias;
|
||||
data.slave_config_position = fmmu->sc->position;
|
||||
data.fmmu_dir = fmmu->dir;
|
||||
data.sync_index = fmmu->sync_index;
|
||||
data.dir = fmmu->dir;
|
||||
data.logical_address = fmmu->logical_start_address;
|
||||
data.data_size = fmmu->data_size;
|
||||
|
||||
@@ -832,6 +832,7 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
ec_ioctl_config_t data;
|
||||
const ec_slave_config_t *sc;
|
||||
uint8_t i;
|
||||
|
||||
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
|
||||
retval = -EFAULT;
|
||||
@@ -850,10 +851,11 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
data.position = sc->position;
|
||||
data.vendor_id = sc->vendor_id;
|
||||
data.product_code = sc->product_code;
|
||||
data.pdo_count[EC_DIR_OUTPUT] =
|
||||
ec_pdo_list_count(&sc->pdos[EC_DIR_OUTPUT]);
|
||||
data.pdo_count[EC_DIR_INPUT] =
|
||||
ec_pdo_list_count(&sc->pdos[EC_DIR_INPUT]);
|
||||
for (i = 0; i < EC_MAX_SYNCS; i++) {
|
||||
data.syncs[i].dir = sc->sync_configs[i].dir;
|
||||
data.syncs[i].pdo_count =
|
||||
ec_pdo_list_count(&sc->sync_configs[i].pdos);
|
||||
}
|
||||
data.sdo_count = ec_slave_config_sdo_count(sc);
|
||||
data.attached = sc->slave != NULL;
|
||||
|
||||
@@ -881,14 +883,16 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (data.direction > EC_DIR_INPUT) {
|
||||
EC_ERR("Invalid direction %u!\n", data.direction);
|
||||
if (data.sync_index >= EC_MAX_SYNCS) {
|
||||
EC_ERR("Invalid sync manager index %u!\n",
|
||||
data.sync_index);
|
||||
retval = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
|
||||
&sc->pdos[data.direction], data.pdo_pos))) {
|
||||
&sc->sync_configs[data.sync_index].pdos,
|
||||
data.pdo_pos))) {
|
||||
EC_ERR("Invalid Pdo position!\n");
|
||||
retval = -EINVAL;
|
||||
break;
|
||||
@@ -929,14 +933,16 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (data.direction > EC_DIR_INPUT) {
|
||||
EC_ERR("Invalid direction %u!\n", data.direction);
|
||||
if (data.sync_index >= EC_MAX_SYNCS) {
|
||||
EC_ERR("Invalid sync manager index %u!\n",
|
||||
data.sync_index);
|
||||
retval = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
|
||||
&sc->pdos[data.direction], data.pdo_pos))) {
|
||||
&sc->sync_configs[data.sync_index].pdos,
|
||||
data.pdo_pos))) {
|
||||
EC_ERR("Invalid Pdo position!\n");
|
||||
retval = -EINVAL;
|
||||
break;
|
||||
|
||||
@@ -201,7 +201,7 @@ int ec_domain_finish(
|
||||
uint32_t datagram_offset;
|
||||
size_t datagram_size;
|
||||
unsigned int datagram_count;
|
||||
unsigned int datagram_used[2];
|
||||
unsigned int datagram_used[EC_DIR_COUNT];
|
||||
ec_fmmu_config_t *fmmu;
|
||||
const ec_datagram_t *datagram;
|
||||
|
||||
|
||||
@@ -55,15 +55,18 @@ void ec_fmmu_config_init(
|
||||
ec_fmmu_config_t *fmmu, /**< EtherCAT FMMU configuration. */
|
||||
ec_slave_config_t *sc, /**< EtherCAT slave configuration. */
|
||||
ec_domain_t *domain, /**< EtherCAT domain. */
|
||||
uint8_t sync_index, /**< Sync manager index to use. */
|
||||
ec_direction_t dir /**< Pdo direction. */
|
||||
)
|
||||
{
|
||||
INIT_LIST_HEAD(&fmmu->list);
|
||||
fmmu->sc = sc;
|
||||
fmmu->sync_index = sync_index;
|
||||
fmmu->dir = dir;
|
||||
|
||||
fmmu->logical_start_address = domain->data_size;
|
||||
fmmu->data_size = ec_pdo_list_total_size(&sc->pdos[dir]);
|
||||
fmmu->data_size = ec_pdo_list_total_size(
|
||||
&sc->sync_configs[sync_index].pdos);
|
||||
|
||||
ec_domain_add_fmmu_config(domain, fmmu);
|
||||
}
|
||||
@@ -81,10 +84,10 @@ void ec_fmmu_config_page(
|
||||
)
|
||||
{
|
||||
if (fmmu->sc->master->debug_level) {
|
||||
EC_DBG("FMMU: LogAddr 0x%08X, Size %3u, PhysAddr 0x%04X, Dir %s\n",
|
||||
fmmu->logical_start_address, fmmu->data_size,
|
||||
sync->physical_start_address,
|
||||
(sync->control_register & 0x04) ? "out" : "in");
|
||||
EC_DBG("FMMU: LogAddr 0x%08X, Size %3u, PhysAddr 0x%04X, SM%u, "
|
||||
"Dir %s\n", fmmu->logical_start_address, fmmu->data_size,
|
||||
sync->physical_start_address, fmmu->sync_index,
|
||||
fmmu->dir == EC_DIR_INPUT ? "in" : "out");
|
||||
}
|
||||
|
||||
EC_WRITE_U32(data, fmmu->logical_start_address);
|
||||
@@ -93,7 +96,7 @@ void ec_fmmu_config_page(
|
||||
EC_WRITE_U8 (data + 7, 0x07); // logical end bit
|
||||
EC_WRITE_U16(data + 8, sync->physical_start_address);
|
||||
EC_WRITE_U8 (data + 10, 0x00); // physical start bit
|
||||
EC_WRITE_U8 (data + 11, (sync->control_register & 0x04) ? 0x02 : 0x01);
|
||||
EC_WRITE_U8 (data + 11, fmmu->dir == EC_DIR_INPUT ? 0x01 : 0x02);
|
||||
EC_WRITE_U16(data + 12, 0x0001); // enable
|
||||
EC_WRITE_U16(data + 14, 0x0000); // reserved
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ typedef struct {
|
||||
struct list_head list; /**< List node used by domain. */
|
||||
const ec_slave_config_t *sc; /**< EtherCAT slave config. */
|
||||
const ec_domain_t *domain; /**< Domain. */
|
||||
ec_direction_t dir; /**< Pdo direction. */
|
||||
|
||||
uint8_t sync_index; /**< Index of sync manager to use. */
|
||||
ec_direction_t dir; /**< FMMU direction. */
|
||||
uint32_t logical_start_address; /**< Logical start address. */
|
||||
unsigned int data_size; /**< Covered Pdo size. */
|
||||
} ec_fmmu_config_t;
|
||||
@@ -62,7 +62,7 @@ typedef struct {
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_fmmu_config_init(ec_fmmu_config_t *, ec_slave_config_t *,
|
||||
ec_domain_t *, ec_direction_t);
|
||||
ec_domain_t *, uint8_t, ec_direction_t);
|
||||
|
||||
void ec_fmmu_config_page(const ec_fmmu_config_t *, const ec_sync_t *,
|
||||
uint8_t *);
|
||||
|
||||
@@ -55,7 +55,7 @@ void ec_fsm_coe_map_state_pdo_entry(ec_fsm_coe_map_t *);
|
||||
void ec_fsm_coe_map_state_end(ec_fsm_coe_map_t *);
|
||||
void ec_fsm_coe_map_state_error(ec_fsm_coe_map_t *);
|
||||
|
||||
void ec_fsm_coe_map_action_next_dir(ec_fsm_coe_map_t *);
|
||||
void ec_fsm_coe_map_action_next_sync(ec_fsm_coe_map_t *);
|
||||
void ec_fsm_coe_map_action_next_pdo(ec_fsm_coe_map_t *);
|
||||
void ec_fsm_coe_map_action_next_pdo_entry(ec_fsm_coe_map_t *);
|
||||
|
||||
@@ -134,50 +134,46 @@ int ec_fsm_coe_map_success(ec_fsm_coe_map_t *fsm /**< Finite state machine */)
|
||||
* state functions
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Start reading Pdo assignment.
|
||||
/** Start reading Pdo assignment.
|
||||
*/
|
||||
|
||||
void ec_fsm_coe_map_state_start(
|
||||
ec_fsm_coe_map_t *fsm /**< finite state machine */
|
||||
)
|
||||
{
|
||||
// read Pdo assignment for first direction
|
||||
fsm->dir = (ec_direction_t) -1; // next is EC_DIR_OUTPUT
|
||||
ec_fsm_coe_map_action_next_dir(fsm);
|
||||
// read Pdo assignment for first sync manager
|
||||
fsm->sync_index = 0xff; // next is 0
|
||||
ec_fsm_coe_map_action_next_sync(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Read Pdo assignment of next direction manager.
|
||||
/** Read Pdo assignment of next sync manager.
|
||||
*/
|
||||
|
||||
void ec_fsm_coe_map_action_next_dir(
|
||||
ec_fsm_coe_map_t *fsm /**< finite state machine */
|
||||
void ec_fsm_coe_map_action_next_sync(
|
||||
ec_fsm_coe_map_t *fsm /**< Finite state machine */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
fsm->dir++;
|
||||
fsm->sync_index++;
|
||||
|
||||
if (slave->master->debug_level)
|
||||
EC_DBG("Processing dir %u of slave %u.\n",
|
||||
fsm->dir, slave->ring_position);
|
||||
EC_DBG("Processing SM%u of slave %u.\n",
|
||||
fsm->sync_index, slave->ring_position);
|
||||
|
||||
for (; fsm->dir <= EC_DIR_INPUT; fsm->dir++) {
|
||||
|
||||
if (!(fsm->sync = ec_slave_get_pdo_sync(slave, fsm->dir))) {
|
||||
for (; fsm->sync_index < EC_MAX_SYNCS; fsm->sync_index++) {
|
||||
if (!(fsm->sync = ec_slave_get_sync(slave, fsm->sync_index))) {
|
||||
if (slave->master->debug_level)
|
||||
EC_DBG("No sync manager for direction %u!\n", fsm->dir);
|
||||
EC_DBG("Slave %u does not provide a configuration for "
|
||||
"SM%u!\n", fsm->slave->ring_position, fsm->sync_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
fsm->sync_sdo_index = 0x1C10 + fsm->sync->index;
|
||||
fsm->sync_sdo_index = 0x1C10 + fsm->sync_index;
|
||||
|
||||
if (slave->master->debug_level)
|
||||
EC_DBG("Reading Pdo assignment of sync manager %u of slave %u.\n",
|
||||
fsm->sync->index, slave->ring_position);
|
||||
EC_DBG("Reading Pdo assignment of SM%u of slave %u.\n",
|
||||
fsm->sync_index, slave->ring_position);
|
||||
|
||||
ec_pdo_list_clear_pdos(&fsm->pdos);
|
||||
|
||||
@@ -226,7 +222,7 @@ void ec_fsm_coe_map_state_pdo_count(
|
||||
fsm->sync_subindices = EC_READ_U8(fsm->request.data);
|
||||
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG(" %u Pdos assigned.\n", fsm->sync_subindices);
|
||||
EC_DBG("%u Pdos assigned.\n", fsm->sync_subindices);
|
||||
|
||||
// read first Pdo
|
||||
fsm->sync_subindex = 1;
|
||||
@@ -263,8 +259,8 @@ void ec_fsm_coe_map_action_next_pdo(
|
||||
fsm->sync->assign_source = EC_ASSIGN_COE;
|
||||
ec_pdo_list_clear_pdos(&fsm->pdos);
|
||||
|
||||
// next direction
|
||||
ec_fsm_coe_map_action_next_dir(fsm);
|
||||
// next sync manager
|
||||
ec_fsm_coe_map_action_next_sync(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -304,10 +300,10 @@ void ec_fsm_coe_map_state_pdo(
|
||||
|
||||
ec_pdo_init(fsm->pdo);
|
||||
fsm->pdo->index = EC_READ_U16(fsm->request.data);
|
||||
fsm->pdo->dir = ec_sync_direction(fsm->sync);
|
||||
fsm->pdo->sync_index = fsm->sync_index;
|
||||
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG(" Pdo 0x%04X.\n", fsm->pdo->index);
|
||||
EC_DBG("Pdo 0x%04X.\n", fsm->pdo->index);
|
||||
|
||||
list_add_tail(&fsm->pdo->list, &fsm->pdos.list);
|
||||
|
||||
@@ -348,7 +344,7 @@ void ec_fsm_coe_map_state_pdo_entry_count(
|
||||
fsm->pdo_subindices = EC_READ_U8(fsm->request.data);
|
||||
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG(" %u Pdo entries mapped.\n", fsm->pdo_subindices);
|
||||
EC_DBG("%u Pdo entries mapped.\n", fsm->pdo_subindices);
|
||||
|
||||
// read first Pdo entry
|
||||
fsm->pdo_subindex = 1;
|
||||
@@ -432,7 +428,7 @@ void ec_fsm_coe_map_state_pdo_entry(
|
||||
}
|
||||
|
||||
if (fsm->slave->master->debug_level) {
|
||||
EC_DBG(" Pdo entry 0x%04X:%02X, %u bit, \"%s\".\n",
|
||||
EC_DBG("Pdo entry 0x%04X:%02X, %u bit, \"%s\".\n",
|
||||
pdo_entry->index, pdo_entry->subindex,
|
||||
pdo_entry->bit_length,
|
||||
pdo_entry->name ? pdo_entry->name : "???");
|
||||
|
||||
@@ -61,7 +61,7 @@ struct ec_fsm_coe_map
|
||||
ec_slave_t *slave; /**< EtherCAT slave */
|
||||
ec_sdo_request_t request; /**< Sdo request */
|
||||
|
||||
ec_direction_t dir; /**< index of the current sync manager */
|
||||
uint8_t sync_index; /**< Index of the current sync manager. */
|
||||
ec_sync_t *sync; /**< Pdo sync manager. */
|
||||
uint16_t sync_sdo_index; /**< Index of the mapping Sdo. */
|
||||
uint8_t sync_subindices; /**< number of mapped Pdos */
|
||||
|
||||
@@ -53,7 +53,7 @@ void ec_fsm_pdo_assign_state_pdo_count(ec_fsm_pdo_assign_t *);
|
||||
void ec_fsm_pdo_assign_state_end(ec_fsm_pdo_assign_t *);
|
||||
void ec_fsm_pdo_assign_state_error(ec_fsm_pdo_assign_t *);
|
||||
|
||||
void ec_fsm_pdo_assign_next_dir(ec_fsm_pdo_assign_t *);
|
||||
void ec_fsm_pdo_assign_next_sync(ec_fsm_pdo_assign_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -151,46 +151,50 @@ void ec_fsm_pdo_assign_state_start(
|
||||
return;
|
||||
}
|
||||
|
||||
fsm->dir = (ec_direction_t) -1; // next is EC_DIR_OUTPUT
|
||||
fsm->num_configured_dirs = 0;
|
||||
ec_fsm_pdo_assign_next_dir(fsm);
|
||||
fsm->sync_index = 0xff; // next is zero
|
||||
fsm->num_configured_syncs = 0;
|
||||
ec_fsm_pdo_assign_next_sync(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Process Pdo assignment of next direction.
|
||||
/** Process Pdo assignment of next sync manager.
|
||||
*/
|
||||
void ec_fsm_pdo_assign_next_dir(
|
||||
void ec_fsm_pdo_assign_next_sync(
|
||||
ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
|
||||
)
|
||||
{
|
||||
fsm->dir++;
|
||||
fsm->sync_index++;
|
||||
|
||||
for (; fsm->dir <= EC_DIR_INPUT; fsm->dir++) {
|
||||
fsm->pdos = &fsm->slave->config->pdos[fsm->dir];
|
||||
for (; fsm->sync_index < EC_MAX_SYNCS; fsm->sync_index++) {
|
||||
fsm->pdos = &fsm->slave->config->sync_configs[fsm->sync_index].pdos;
|
||||
|
||||
if (!(fsm->sync = ec_slave_get_pdo_sync(fsm->slave, fsm->dir))) {
|
||||
if (!(fsm->sync = ec_slave_get_sync(fsm->slave, fsm->sync_index))) {
|
||||
if (!list_empty(&fsm->pdos->list)) {
|
||||
EC_ERR("No sync manager for direction %u!\n", fsm->dir);
|
||||
EC_ERR("Slave %u does not provide a configuration for sync "
|
||||
"manager %u!\n", fsm->slave->ring_position,
|
||||
fsm->sync_index);
|
||||
fsm->state = ec_fsm_pdo_assign_state_end;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fsm->slave->master->debug_level) {
|
||||
EC_DBG("Sync Pdos: ");
|
||||
ec_pdo_list_print(&fsm->sync->pdos);
|
||||
printk("\n");
|
||||
EC_DBG("Config Pdos: ");
|
||||
ec_pdo_list_print(fsm->pdos);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
// check if assignment has to be altered
|
||||
if (ec_pdo_list_equal(&fsm->sync->pdos, fsm->pdos))
|
||||
continue;
|
||||
|
||||
if (fsm->slave->master->debug_level) {
|
||||
EC_DBG("Pdo assignment of SM%u differs in slave %u:\n",
|
||||
fsm->sync_index, fsm->slave->ring_position);
|
||||
EC_DBG("Currently assigned Pdos: ");
|
||||
ec_pdo_list_print(&fsm->sync->pdos);
|
||||
printk("\n");
|
||||
EC_DBG("Pdos to assign: ");
|
||||
ec_pdo_list_print(fsm->pdos);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
// Pdo assignment has to be changed. Does the slave support this?
|
||||
if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE)
|
||||
|| (fsm->slave->sii.has_general
|
||||
@@ -201,11 +205,11 @@ void ec_fsm_pdo_assign_next_dir(
|
||||
return;
|
||||
}
|
||||
|
||||
fsm->num_configured_dirs++;
|
||||
fsm->num_configured_syncs++;
|
||||
|
||||
if (fsm->slave->master->debug_level) {
|
||||
EC_DBG("Changing Pdo assignment for SM%u of slave %u.\n",
|
||||
fsm->sync->index, fsm->slave->ring_position);
|
||||
fsm->sync_index, fsm->slave->ring_position);
|
||||
}
|
||||
|
||||
if (ec_sdo_request_alloc(&fsm->request, 2)) {
|
||||
@@ -216,10 +220,10 @@ void ec_fsm_pdo_assign_next_dir(
|
||||
// set mapped Pdo count to zero
|
||||
EC_WRITE_U8(fsm->request.data, 0); // zero Pdos mapped
|
||||
fsm->request.data_size = 1;
|
||||
ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync->index, 0);
|
||||
ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0);
|
||||
ecrt_sdo_request_write(&fsm->request);
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG("Setting Pdo count to zero for SM%u.\n", fsm->sync->index);
|
||||
EC_DBG("Setting Pdo count to zero for SM%u.\n", fsm->sync_index);
|
||||
|
||||
fsm->state = ec_fsm_pdo_assign_state_zero_count;
|
||||
ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
|
||||
@@ -227,7 +231,7 @@ void ec_fsm_pdo_assign_next_dir(
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsm->slave->master->debug_level && !fsm->num_configured_dirs)
|
||||
if (fsm->slave->master->debug_level && !fsm->num_configured_syncs)
|
||||
EC_DBG("Pdo assignments of slave %u are already configured"
|
||||
" correctly.\n", fsm->slave->ring_position);
|
||||
fsm->state = ec_fsm_pdo_assign_state_end;
|
||||
@@ -259,7 +263,7 @@ void ec_fsm_pdo_assign_add_pdo(
|
||||
EC_WRITE_U16(fsm->request.data, fsm->pdo->index);
|
||||
fsm->request.data_size = 2;
|
||||
ec_sdo_request_address(&fsm->request,
|
||||
0x1C10 + fsm->sync->index, fsm->pdo_count);
|
||||
0x1C10 + fsm->sync_index, fsm->pdo_count);
|
||||
ecrt_sdo_request_write(&fsm->request);
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG("Assigning Pdo 0x%04X at position %u.\n",
|
||||
@@ -293,8 +297,8 @@ void ec_fsm_pdo_assign_state_zero_count(
|
||||
if (!(fsm->pdo = ec_fsm_pdo_assign_next_pdo(fsm, &fsm->pdos->list))) {
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG("No Pdos to assign for SM%u of slave %u.\n",
|
||||
fsm->sync->index, fsm->slave->ring_position);
|
||||
ec_fsm_pdo_assign_next_dir(fsm);
|
||||
fsm->sync_index, fsm->slave->ring_position);
|
||||
ec_fsm_pdo_assign_next_sync(fsm);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -315,7 +319,7 @@ void ec_fsm_pdo_assign_state_add_pdo(
|
||||
|
||||
if (!ec_fsm_coe_success(fsm->fsm_coe)) {
|
||||
EC_ERR("Failed to map Pdo 0x%04X for SM%u of slave %u.\n",
|
||||
fsm->pdo->index, fsm->sync->index, fsm->slave->ring_position);
|
||||
fsm->pdo->index, fsm->sync_index, fsm->slave->ring_position);
|
||||
fsm->state = ec_fsm_pdo_assign_state_error;
|
||||
return;
|
||||
}
|
||||
@@ -325,7 +329,7 @@ void ec_fsm_pdo_assign_state_add_pdo(
|
||||
// no more Pdos to map. write Pdo count
|
||||
EC_WRITE_U8(fsm->request.data, fsm->pdo_count);
|
||||
fsm->request.data_size = 1;
|
||||
ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync->index, 0);
|
||||
ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0);
|
||||
ecrt_sdo_request_write(&fsm->request);
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG("Setting number of assigned Pdos to %u.\n",
|
||||
@@ -361,10 +365,10 @@ void ec_fsm_pdo_assign_state_pdo_count(
|
||||
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG("Successfully configured Pdo assignment for SM%u of"
|
||||
" slave %u.\n", fsm->sync->index, fsm->slave->ring_position);
|
||||
" slave %u.\n", fsm->sync_index, fsm->slave->ring_position);
|
||||
|
||||
// assignment for this direction finished
|
||||
ec_fsm_pdo_assign_next_dir(fsm);
|
||||
// assignment for this sync manager finished
|
||||
ec_fsm_pdo_assign_next_sync(fsm);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -62,10 +62,11 @@ struct ec_fsm_pdo_assign
|
||||
ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use. */
|
||||
ec_slave_t *slave; /**< Slave the FSM runs on. */
|
||||
|
||||
ec_direction_t dir; /**< Current direction. */
|
||||
uint8_t sync_index; /**< Current sync manager index. */
|
||||
const ec_pdo_list_t *pdos; /**< Target Pdo assignment. */
|
||||
const ec_sync_t *sync; /**< Current sync manager. */
|
||||
unsigned int num_configured_dirs; /**< Number of configured directions. */
|
||||
unsigned int num_configured_syncs; /**< Number of configured
|
||||
assignments. */
|
||||
const ec_pdo_t *pdo; /**< Current Pdo. */
|
||||
|
||||
ec_sdo_request_t request; /**< Sdo request. */
|
||||
|
||||
@@ -161,12 +161,12 @@ void ec_fsm_pdo_mapping_next_pdo(
|
||||
ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
|
||||
)
|
||||
{
|
||||
ec_direction_t dir;
|
||||
uint8_t sync_index;
|
||||
const ec_pdo_list_t *pdos;
|
||||
const ec_pdo_t *pdo, *assigned_pdo;
|
||||
|
||||
for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
|
||||
pdos = &fsm->slave->config->pdos[dir];
|
||||
for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++) {
|
||||
pdos = &fsm->slave->config->sync_configs[sync_index].pdos;
|
||||
|
||||
list_for_each_entry(pdo, &pdos->list, list) {
|
||||
if (fsm->pdo) { // there was a Pdo mapping changed in the last run
|
||||
@@ -251,15 +251,17 @@ void ec_fsm_pdo_mapping_add_entry(
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG("Mapping Pdo entry 0x%04X:%02X (%u bit) at position %u.\n",
|
||||
fsm->entry->index, fsm->entry->subindex,
|
||||
fsm->entry->bit_length, fsm->entry_count);
|
||||
|
||||
value = fsm->entry->index << 16
|
||||
| fsm->entry->subindex << 8 | fsm->entry->bit_length;
|
||||
EC_WRITE_U32(fsm->request.data, value);
|
||||
fsm->request.data_size = 4;
|
||||
ec_sdo_request_address(&fsm->request, fsm->pdo->index, fsm->entry_count);
|
||||
ecrt_sdo_request_write(&fsm->request);
|
||||
if (fsm->slave->master->debug_level)
|
||||
EC_DBG("Configuring Pdo entry %08X at position %u.\n",
|
||||
value, fsm->entry_count);
|
||||
|
||||
fsm->state = ec_fsm_pdo_mapping_state_add_entry;
|
||||
ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
|
||||
|
||||
@@ -301,7 +301,9 @@ void ec_fsm_slave_config_enter_mbox_sync(
|
||||
EC_SYNC_PAGE_SIZE * slave->sii.sync_count);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ec_sync_config(&slave->sii.syncs[i], slave->sii.syncs[i].length,
|
||||
ec_sync_page(&slave->sii.syncs[i], i,
|
||||
slave->sii.syncs[i].default_length,
|
||||
EC_DIR_INVALID, // use default direction
|
||||
datagram->data + EC_SYNC_PAGE_SIZE * i);
|
||||
}
|
||||
} else { // no mailbox sync manager configurations provided
|
||||
@@ -316,19 +318,21 @@ void ec_fsm_slave_config_enter_mbox_sync(
|
||||
EC_SYNC_PAGE_SIZE * 2);
|
||||
memset(datagram->data, 0x00, EC_SYNC_PAGE_SIZE * 2);
|
||||
|
||||
ec_sync_init(&sync, slave, 0);
|
||||
ec_sync_init(&sync, slave);
|
||||
sync.physical_start_address = slave->sii.rx_mailbox_offset;
|
||||
sync.control_register = 0x26;
|
||||
sync.enable = 1;
|
||||
ec_sync_config(&sync, slave->sii.rx_mailbox_size,
|
||||
datagram->data + EC_SYNC_PAGE_SIZE * sync.index);
|
||||
ec_sync_page(&sync, 0, slave->sii.rx_mailbox_size,
|
||||
EC_DIR_INVALID, // use default direction
|
||||
datagram->data);
|
||||
|
||||
ec_sync_init(&sync, slave, 1);
|
||||
ec_sync_init(&sync, slave);
|
||||
sync.physical_start_address = slave->sii.tx_mailbox_offset;
|
||||
sync.control_register = 0x22;
|
||||
sync.enable = 1;
|
||||
ec_sync_config(&sync, slave->sii.tx_mailbox_size,
|
||||
datagram->data + EC_SYNC_PAGE_SIZE * sync.index);
|
||||
ec_sync_page(&sync, 1, slave->sii.tx_mailbox_size,
|
||||
EC_DIR_INVALID, // use default direction
|
||||
datagram->data + EC_SYNC_PAGE_SIZE);
|
||||
}
|
||||
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
@@ -499,8 +503,9 @@ void ec_fsm_slave_config_enter_pdo_sync(
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
unsigned int i, offset, num_pdo_syncs;
|
||||
uint8_t sync_index;
|
||||
const ec_sync_t *sync;
|
||||
ec_direction_t dir;
|
||||
const ec_sync_config_t *sync_config;
|
||||
uint16_t size;
|
||||
|
||||
if (slave->sii.mailbox_protocols) {
|
||||
@@ -524,10 +529,12 @@ void ec_fsm_slave_config_enter_pdo_sync(
|
||||
memset(datagram->data, 0x00, EC_SYNC_PAGE_SIZE * num_pdo_syncs);
|
||||
|
||||
for (i = 0; i < num_pdo_syncs; i++) {
|
||||
sync = &slave->sii.syncs[i + offset];
|
||||
dir = ec_sync_direction(sync);
|
||||
size = ec_pdo_list_total_size(&slave->config->pdos[dir]);
|
||||
ec_sync_config(sync, size, datagram->data + EC_SYNC_PAGE_SIZE * i);
|
||||
sync_index = i + offset;
|
||||
sync = &slave->sii.syncs[sync_index];
|
||||
sync_config = &slave->config->sync_configs[sync_index];
|
||||
size = ec_pdo_list_total_size(&sync_config->pdos);
|
||||
ec_sync_page(sync, sync_index, size, sync_config->dir,
|
||||
datagram->data + EC_SYNC_PAGE_SIZE * i);
|
||||
}
|
||||
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
@@ -654,7 +661,7 @@ void ec_fsm_slave_config_enter_fmmu(ec_fsm_slave_config_t *fsm /**< slave state
|
||||
memset(datagram->data, 0x00, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
|
||||
for (i = 0; i < slave->config->used_fmmus; i++) {
|
||||
fmmu = &slave->config->fmmu_configs[i];
|
||||
if (!(sync = ec_slave_get_pdo_sync(slave, fmmu->dir))) {
|
||||
if (!(sync = ec_slave_get_sync(slave, fmmu->sync_index))) {
|
||||
slave->error_flag = 1;
|
||||
fsm->state = ec_fsm_slave_config_state_error;
|
||||
EC_ERR("Failed to determine Pdo sync manager for FMMU on slave"
|
||||
|
||||
@@ -338,7 +338,7 @@ void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *fsm /**< slave state
|
||||
}
|
||||
|
||||
dl_status = EC_READ_U16(datagram->data);
|
||||
for (i = 0; i < EC_SLAVE_MAX_PORTS; i++) {
|
||||
for (i = 0; i < EC_MAX_PORTS; i++) {
|
||||
slave->ports[i].dl_link = dl_status & (1 << (4 + i)) ? 1 : 0;
|
||||
slave->ports[i].dl_loop = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
|
||||
slave->ports[i].dl_signal = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
|
||||
|
||||
@@ -90,6 +90,12 @@
|
||||
/** Word offset of first SII category. */
|
||||
#define EC_FIRST_SII_CATEGORY_OFFSET 0x40
|
||||
|
||||
/** Maximum number of slave ports. */
|
||||
#define EC_MAX_PORTS 4
|
||||
|
||||
/** Maximum number of sync managers per slave. */
|
||||
#define EC_MAX_SYNCS 16
|
||||
|
||||
/** Size of a sync manager configuration page. */
|
||||
#define EC_SYNC_PAGE_SIZE 8
|
||||
|
||||
@@ -99,9 +105,6 @@
|
||||
/** Size of an FMMU configuration page. */
|
||||
#define EC_FMMU_PAGE_SIZE 16
|
||||
|
||||
/** Maximum number of slave ports. */
|
||||
#define EC_SLAVE_MAX_PORTS 4
|
||||
|
||||
/** Slave state mask.
|
||||
*
|
||||
* Apply this mask to a slave state byte to get the slave state without
|
||||
|
||||
@@ -146,7 +146,6 @@ typedef struct {
|
||||
uint32_t pdo_pos;
|
||||
|
||||
// outputs
|
||||
uint8_t dir;
|
||||
uint16_t index;
|
||||
uint8_t entry_count;
|
||||
int8_t name[EC_IOCTL_STRING_SIZE];
|
||||
@@ -192,7 +191,8 @@ typedef struct {
|
||||
// outputs
|
||||
uint16_t slave_config_alias;
|
||||
uint16_t slave_config_position;
|
||||
uint8_t fmmu_dir;
|
||||
uint8_t sync_index;
|
||||
ec_direction_t dir;
|
||||
uint32_t logical_address;
|
||||
uint32_t data_size;
|
||||
} ec_ioctl_domain_fmmu_t;
|
||||
@@ -291,7 +291,10 @@ typedef struct {
|
||||
uint16_t position;
|
||||
uint32_t vendor_id;
|
||||
uint32_t product_code;
|
||||
uint32_t pdo_count[2];
|
||||
struct {
|
||||
ec_direction_t dir;
|
||||
uint32_t pdo_count;
|
||||
} syncs[16];
|
||||
uint32_t sdo_count;
|
||||
uint8_t attached;
|
||||
} ec_ioctl_config_t;
|
||||
@@ -301,8 +304,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint32_t config_index;
|
||||
uint32_t direction;
|
||||
uint32_t pdo_pos;
|
||||
uint8_t sync_index;
|
||||
uint16_t pdo_pos;
|
||||
|
||||
// outputs
|
||||
uint16_t index;
|
||||
@@ -315,9 +318,9 @@ typedef struct {
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint32_t config_index;
|
||||
uint32_t direction;
|
||||
uint32_t pdo_pos;
|
||||
uint32_t entry_pos;
|
||||
uint8_t sync_index;
|
||||
uint16_t pdo_pos;
|
||||
uint8_t entry_pos;
|
||||
|
||||
// outputs
|
||||
uint16_t index;
|
||||
|
||||
@@ -1306,10 +1306,6 @@ ec_slave_config_t *ecrt_master_slave_config(ec_master_t *master,
|
||||
}
|
||||
|
||||
if (found) { // config with same alias/position already existing
|
||||
if (master->debug_level) {
|
||||
EC_INFO("Using existing slave configuration for %u:%u\n",
|
||||
alias, position);
|
||||
}
|
||||
if (sc->vendor_id != vendor_id || sc->product_code != product_code) {
|
||||
EC_ERR("Slave type mismatch. Slave was configured as"
|
||||
" 0x%08X/0x%08X before. Now configuring with"
|
||||
@@ -1318,11 +1314,9 @@ ec_slave_config_t *ecrt_master_slave_config(ec_master_t *master,
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (master->debug_level) {
|
||||
EC_INFO("Creating slave configuration for %u:%u,"
|
||||
" 0x%08X/0x%08X.\n", alias, position, vendor_id,
|
||||
product_code);
|
||||
}
|
||||
if (master->debug_level)
|
||||
EC_DBG("Creating slave configuration for %u:%u, 0x%08X/0x%08X.\n",
|
||||
alias, position, vendor_id, product_code);
|
||||
|
||||
if (!(sc = (ec_slave_config_t *) kmalloc(sizeof(ec_slave_config_t),
|
||||
GFP_KERNEL))) {
|
||||
@@ -1334,8 +1328,8 @@ ec_slave_config_t *ecrt_master_slave_config(ec_master_t *master,
|
||||
alias, position, vendor_id, product_code);
|
||||
|
||||
// try to find the addressed slave
|
||||
if (!ec_slave_config_attach(sc))
|
||||
ec_slave_config_load_default_assignment(sc);
|
||||
ec_slave_config_attach(sc);
|
||||
ec_slave_config_load_default_sync_config(sc);
|
||||
|
||||
list_add_tail(&sc->list, &master->configs);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ void ec_pdo_init(
|
||||
*/
|
||||
int ec_pdo_init_copy(ec_pdo_t *pdo, const ec_pdo_t *other_pdo)
|
||||
{
|
||||
pdo->dir = other_pdo->dir;
|
||||
pdo->index = other_pdo->index;
|
||||
pdo->sync_index = other_pdo->sync_index;
|
||||
pdo->name = NULL;
|
||||
|
||||
@@ -54,9 +54,8 @@
|
||||
*/
|
||||
typedef struct {
|
||||
struct list_head list; /**< List item. */
|
||||
ec_direction_t dir; /**< Pdo direction. */
|
||||
uint16_t index; /**< Pdo index. */
|
||||
int8_t sync_index; /**< Assigned sync manager. */
|
||||
int8_t sync_index; /**< Assigned sync manager. \todo remove? */
|
||||
char *name; /**< Pdo name. */
|
||||
struct list_head entries; /**< List of Pdo entries. */
|
||||
} ec_pdo_t;
|
||||
|
||||
@@ -121,7 +121,6 @@ uint16_t ec_pdo_list_total_size(
|
||||
*/
|
||||
ec_pdo_t *ec_pdo_list_add_pdo(
|
||||
ec_pdo_list_t *pl, /**< Pdo list. */
|
||||
ec_direction_t dir, /**< Direction. */
|
||||
uint16_t index /**< Pdo index. */
|
||||
)
|
||||
{
|
||||
@@ -133,7 +132,6 @@ ec_pdo_t *ec_pdo_list_add_pdo(
|
||||
}
|
||||
|
||||
ec_pdo_init(pdo);
|
||||
pdo->dir = dir;
|
||||
pdo->index = index;
|
||||
list_add_tail(&pdo->list, &pl->list);
|
||||
return pdo;
|
||||
|
||||
@@ -63,8 +63,7 @@ void ec_pdo_list_clear(ec_pdo_list_t *);
|
||||
|
||||
void ec_pdo_list_clear_pdos(ec_pdo_list_t *);
|
||||
|
||||
ec_pdo_t *ec_pdo_list_add_pdo(ec_pdo_list_t *, ec_direction_t,
|
||||
uint16_t);
|
||||
ec_pdo_t *ec_pdo_list_add_pdo(ec_pdo_list_t *, uint16_t);
|
||||
int ec_pdo_list_add_pdo_copy(ec_pdo_list_t *, const ec_pdo_t *);
|
||||
|
||||
int ec_pdo_list_copy(ec_pdo_list_t *, const ec_pdo_list_t *);
|
||||
|
||||
@@ -75,7 +75,7 @@ void ec_sdo_request_init(
|
||||
req->data = NULL;
|
||||
req->mem_size = 0;
|
||||
req->data_size = 0;
|
||||
req->dir = EC_DIR_OUTPUT;
|
||||
req->dir = EC_DIR_INVALID;
|
||||
req->issue_timeout = 0; // no timeout
|
||||
req->response_timeout = EC_SDO_REQUEST_RESPONSE_TIMEOUT;
|
||||
req->state = EC_REQUEST_INIT;
|
||||
|
||||
@@ -87,7 +87,7 @@ void ec_slave_init(
|
||||
slave->base_build = 0;
|
||||
slave->base_fmmu_count = 0;
|
||||
|
||||
for (i = 0; i < EC_SLAVE_MAX_PORTS; i++) {
|
||||
for (i = 0; i < EC_MAX_PORTS; i++) {
|
||||
slave->ports[i].dl_link = 0;
|
||||
slave->ports[i].dl_loop = 0;
|
||||
slave->ports[i].dl_signal = 0;
|
||||
@@ -365,6 +365,10 @@ int ec_slave_fetch_sii_syncs(
|
||||
|
||||
if (count) {
|
||||
total_count = count + slave->sii.sync_count;
|
||||
if (total_count > EC_MAX_SYNCS) {
|
||||
EC_ERR("Exceeded maximum number of sync managers!\n");
|
||||
return -1;
|
||||
}
|
||||
memsize = sizeof(ec_sync_t) * total_count;
|
||||
if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate %u bytes for sync managers.\n",
|
||||
@@ -380,9 +384,9 @@ int ec_slave_fetch_sii_syncs(
|
||||
index = i + slave->sii.sync_count;
|
||||
sync = &syncs[index];
|
||||
|
||||
ec_sync_init(sync, slave, index);
|
||||
ec_sync_init(sync, slave);
|
||||
sync->physical_start_address = EC_READ_U16(data);
|
||||
sync->length = EC_READ_U16(data + 2);
|
||||
sync->default_length = EC_READ_U16(data + 2);
|
||||
sync->control_register = EC_READ_U8(data + 4);
|
||||
sync->enable = EC_READ_U8(data + 6);
|
||||
}
|
||||
@@ -421,7 +425,6 @@ int ec_slave_fetch_sii_pdos(
|
||||
}
|
||||
|
||||
ec_pdo_init(pdo);
|
||||
pdo->dir = dir;
|
||||
pdo->index = EC_READ_U16(data);
|
||||
entry_count = EC_READ_U8(data + 2);
|
||||
pdo->sync_index = EC_READ_U8(data + 3);
|
||||
@@ -462,12 +465,11 @@ int ec_slave_fetch_sii_pdos(
|
||||
if (pdo->sync_index >= 0) {
|
||||
ec_sync_t *sync;
|
||||
|
||||
if (pdo->sync_index >= slave->sii.sync_count) {
|
||||
if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
|
||||
EC_ERR("Invalid SM index %i for Pdo 0x%04X in slave %u.",
|
||||
pdo->sync_index, pdo->index, slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
sync = &slave->sii.syncs[pdo->sync_index];
|
||||
|
||||
if (ec_pdo_list_add_pdo_copy(&sync->pdos, pdo))
|
||||
return -1;
|
||||
@@ -564,37 +566,20 @@ int ec_slave_write_sii(
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Get the sync manager for either Rx- or Tx-Pdos.
|
||||
/** Get the sync manager given an index.
|
||||
*
|
||||
* \todo This seems not to be correct in every case...
|
||||
* \return pointer to sync manager, or NULL.
|
||||
*/
|
||||
ec_sync_t *ec_slave_get_pdo_sync(
|
||||
ec_sync_t *ec_slave_get_sync(
|
||||
ec_slave_t *slave, /**< EtherCAT slave. */
|
||||
ec_direction_t dir /**< Input or output. */
|
||||
uint8_t sync_index /**< Sync manager index. */
|
||||
)
|
||||
{
|
||||
unsigned int sync_index;
|
||||
|
||||
if (dir != EC_DIR_INPUT && dir != EC_DIR_OUTPUT) {
|
||||
EC_ERR("Invalid direction!\n");
|
||||
if (sync_index < slave->sii.sync_count) {
|
||||
return &slave->sii.syncs[sync_index];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (slave->sii.sync_count != 1) {
|
||||
sync_index = (unsigned int) dir;
|
||||
if (slave->sii.mailbox_protocols) sync_index += 2;
|
||||
|
||||
if (sync_index >= slave->sii.sync_count)
|
||||
return NULL;
|
||||
} else { // sync_count == 1
|
||||
// A single sync manager may be used for inputs OR outputs!
|
||||
if (ec_sync_direction(&slave->sii.syncs[0]) != dir)
|
||||
return NULL;
|
||||
sync_index = 0;
|
||||
}
|
||||
|
||||
return &slave->sii.syncs[sync_index];
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -79,7 +79,7 @@ typedef struct {
|
||||
char *image; /**< Image name. */
|
||||
char *order; /**< Order number. */
|
||||
char *name; /**< Slave name. */
|
||||
uint8_t physical_layer[EC_SLAVE_MAX_PORTS]; /**< Port media. */
|
||||
uint8_t physical_layer[EC_MAX_PORTS]; /**< Port media. */
|
||||
ec_sii_coe_details_t coe_details; /**< CoE detail flags. */
|
||||
ec_sii_general_flags_t general_flags; /**< General flags. */
|
||||
int16_t current_on_ebus; /**< Power consumption in mA. */
|
||||
@@ -128,7 +128,7 @@ struct ec_slave
|
||||
uint16_t base_fmmu_count; /**< Number of supported FMMUs. */
|
||||
|
||||
// data link status
|
||||
ec_slave_port_t ports[EC_SLAVE_MAX_PORTS];
|
||||
ec_slave_port_t ports[EC_MAX_PORTS];
|
||||
|
||||
// SII
|
||||
uint16_t *sii_words; /**< Complete SII image. */
|
||||
@@ -161,7 +161,8 @@ int ec_slave_fetch_sii_pdos(ec_slave_t *, const uint8_t *, size_t,
|
||||
ec_direction_t);
|
||||
|
||||
// misc.
|
||||
ec_sync_t *ec_slave_get_pdo_sync(ec_slave_t *, ec_direction_t);
|
||||
ec_sync_t *ec_slave_get_sync(ec_slave_t *, uint8_t);
|
||||
|
||||
void ec_slave_sdo_dict_info(const ec_slave_t *,
|
||||
unsigned int *, unsigned int *);
|
||||
ec_sdo_t *ec_slave_get_sdo(ec_slave_t *, uint16_t);
|
||||
|
||||
@@ -61,7 +61,7 @@ void ec_slave_config_init(
|
||||
uint32_t product_code /**< Expected product code. */
|
||||
)
|
||||
{
|
||||
ec_direction_t dir;
|
||||
unsigned int i;
|
||||
|
||||
sc->master = master;
|
||||
sc->alias = alias;
|
||||
@@ -70,8 +70,8 @@ void ec_slave_config_init(
|
||||
sc->product_code = product_code;
|
||||
sc->slave = NULL;
|
||||
|
||||
for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
|
||||
ec_pdo_list_init(&sc->pdos[dir]);
|
||||
for (i = 0; i < EC_MAX_SYNCS; i++)
|
||||
ec_sync_config_init(&sc->sync_configs[i]);
|
||||
|
||||
INIT_LIST_HEAD(&sc->sdo_configs);
|
||||
INIT_LIST_HEAD(&sc->sdo_requests);
|
||||
@@ -89,14 +89,14 @@ void ec_slave_config_clear(
|
||||
ec_slave_config_t *sc /**< Slave configuration. */
|
||||
)
|
||||
{
|
||||
ec_direction_t dir;
|
||||
unsigned int i;
|
||||
ec_sdo_request_t *req, *next_req;
|
||||
|
||||
ec_slave_config_detach(sc);
|
||||
|
||||
// Free Pdo mappings
|
||||
for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
|
||||
ec_pdo_list_clear(&sc->pdos[dir]);
|
||||
// Free sync managers
|
||||
for (i = 0; i < EC_MAX_SYNCS; i++)
|
||||
ec_sync_config_clear(&sc->sync_configs[i]);
|
||||
|
||||
// free all Sdo configurations
|
||||
list_for_each_entry_safe(req, next_req, &sc->sdo_configs, list) {
|
||||
@@ -130,6 +130,7 @@ void ec_slave_config_clear(
|
||||
int ec_slave_config_prepare_fmmu(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
ec_domain_t *domain, /**< Domain. */
|
||||
uint8_t sync_index, /**< Sync manager index. */
|
||||
ec_direction_t dir /**< Pdo direction. */
|
||||
)
|
||||
{
|
||||
@@ -139,7 +140,7 @@ int ec_slave_config_prepare_fmmu(
|
||||
// FMMU configuration already prepared?
|
||||
for (i = 0; i < sc->used_fmmus; i++) {
|
||||
fmmu = &sc->fmmu_configs[i];
|
||||
if (fmmu->domain == domain && fmmu->dir == dir)
|
||||
if (fmmu->domain == domain && fmmu->sync_index == sync_index)
|
||||
return fmmu->logical_start_address;
|
||||
}
|
||||
|
||||
@@ -150,7 +151,7 @@ int ec_slave_config_prepare_fmmu(
|
||||
}
|
||||
|
||||
fmmu = &sc->fmmu_configs[sc->used_fmmus++];
|
||||
ec_fmmu_config_init(fmmu, sc, domain, dir);
|
||||
ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir);
|
||||
return fmmu->logical_start_address;
|
||||
}
|
||||
|
||||
@@ -228,19 +229,25 @@ void ec_slave_config_detach(
|
||||
|
||||
/** Loads the default Pdo assignment from the slave object.
|
||||
*/
|
||||
void ec_slave_config_load_default_assignment(ec_slave_config_t *sc)
|
||||
void ec_slave_config_load_default_sync_config(ec_slave_config_t *sc)
|
||||
{
|
||||
ec_direction_t dir;
|
||||
ec_pdo_list_t *pdos;
|
||||
ec_sync_t *sync;
|
||||
uint8_t sync_index;
|
||||
ec_sync_config_t *sync_config;
|
||||
const ec_sync_t *sync;
|
||||
|
||||
if (!sc->slave)
|
||||
return;
|
||||
|
||||
for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
|
||||
pdos = &sc->pdos[dir];
|
||||
if ((sync = ec_slave_get_pdo_sync(sc->slave, dir)))
|
||||
ec_pdo_list_copy(pdos, &sync->pdos);
|
||||
|
||||
for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++) {
|
||||
sync_config = &sc->sync_configs[sync_index];
|
||||
if ((sync = ec_slave_get_sync(sc->slave, sync_index))) {
|
||||
sync_config->dir = ec_sync_default_direction(sync);
|
||||
if (sync_config->dir == EC_DIR_INVALID)
|
||||
EC_WARN("SM%u of slave %u has an invalid direction field!\n",
|
||||
sync_index, sc->slave->ring_position);
|
||||
ec_pdo_list_copy(&sync_config->pdos, &sync->pdos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,50 +260,51 @@ void ec_slave_config_load_default_mapping(
|
||||
ec_pdo_t *pdo
|
||||
)
|
||||
{
|
||||
unsigned int i;
|
||||
const ec_sync_t *sync;
|
||||
const ec_pdo_t *default_pdo;
|
||||
|
||||
if (!sc->slave)
|
||||
return;
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("Loading default configuration for Pdo 0x%04X in"
|
||||
" config %u:%u.\n", pdo->index, sc->alias, sc->position);
|
||||
EC_DBG("Loading default mapping for Pdo 0x%04X in config %u:%u.\n",
|
||||
pdo->index, sc->alias, sc->position);
|
||||
|
||||
if (!sc->slave) {
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("Failed to load default Pdo configuration for %u:%u:"
|
||||
" Slave not found.\n", sc->alias, sc->position);
|
||||
return;
|
||||
}
|
||||
// find Pdo in any sync manager (it could be reassigned later)
|
||||
for (i = 0; i < sc->slave->sii.sync_count; i++) {
|
||||
sync = &sc->slave->sii.syncs[i];
|
||||
|
||||
if (!(sync = ec_slave_get_pdo_sync(sc->slave, pdo->dir))) {
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("Slave %u does not provide a default Pdo"
|
||||
" configuration!\n", sc->slave->ring_position);
|
||||
return;
|
||||
}
|
||||
list_for_each_entry(default_pdo, &sync->pdos.list, list) {
|
||||
if (default_pdo->index != pdo->index)
|
||||
continue;
|
||||
|
||||
list_for_each_entry(default_pdo, &sync->pdos.list, list) {
|
||||
if (default_pdo->index != pdo->index)
|
||||
continue;
|
||||
if (default_pdo->name) {
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("Found Pdo name \"%s\".\n", default_pdo->name);
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG(" Found Pdo name \"%s\".\n",
|
||||
default_pdo->name);
|
||||
|
||||
// try to take Pdo name from mapped one
|
||||
ec_pdo_set_name(pdo, default_pdo->name);
|
||||
|
||||
// copy entries (= default Pdo configuration)
|
||||
if (ec_pdo_copy_entries(pdo, default_pdo))
|
||||
return;
|
||||
|
||||
if (sc->master->debug_level) {
|
||||
const ec_pdo_entry_t *entry;
|
||||
list_for_each_entry(entry, &pdo->entries, list) {
|
||||
EC_DBG(" Entry 0x%04X:%02X.\n",
|
||||
entry->index, entry->subindex);
|
||||
// take Pdo name from assigned one
|
||||
ec_pdo_set_name(pdo, default_pdo->name);
|
||||
}
|
||||
|
||||
// copy entries (= default Pdo mapping)
|
||||
if (ec_pdo_copy_entries(pdo, default_pdo))
|
||||
return;
|
||||
|
||||
if (sc->master->debug_level) {
|
||||
const ec_pdo_entry_t *entry;
|
||||
list_for_each_entry(entry, &pdo->entries, list) {
|
||||
EC_DBG("Entry 0x%04X:%02X.\n",
|
||||
entry->index, entry->subindex);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("No default mapping found.\n");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -341,18 +349,49 @@ const ec_sdo_request_t *ec_slave_config_get_sdo_by_pos_const(
|
||||
* Realtime interface
|
||||
*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
||||
ec_direction_t dir, uint16_t index)
|
||||
int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
|
||||
ec_direction_t dir)
|
||||
{
|
||||
ec_pdo_list_t *pl = &sc->pdos[dir];
|
||||
ec_pdo_t *pdo;
|
||||
ec_sync_config_t *sync_config;
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("Adding Pdo 0x%04X to assignment for dir %u, config %u:%u.\n",
|
||||
index, dir, sc->alias, sc->position);
|
||||
EC_DBG("ecrt_slave_config_sync_manager(sc = 0x%x, sync_index = %u, "
|
||||
"dir = %u)\n", (u32) sc, sync_index, dir);
|
||||
|
||||
if (!(pdo = ec_pdo_list_add_pdo(pl, dir, index)))
|
||||
if (sync_index >= EC_MAX_SYNCS) {
|
||||
EC_ERR("Invalid sync manager index %u!\n", sync_index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dir != EC_DIR_OUTPUT && dir != EC_DIR_INPUT) {
|
||||
EC_ERR("Invalid direction %u!\n", (u32) dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sync_config = &sc->sync_configs[sync_index];
|
||||
sync_config->dir = dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
||||
uint8_t sync_index, uint16_t pdo_index)
|
||||
{
|
||||
ec_pdo_t *pdo;
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("ecrt_slave_config_pdo_assign_add(sc = 0x%x, sync_index = %u, "
|
||||
"pdo_index = 0x%04X)\n", (u32) sc, sync_index, pdo_index);
|
||||
|
||||
if (sync_index >= EC_MAX_SYNCS) {
|
||||
EC_ERR("Invalid sync manager index %u!\n", sync_index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, pdo_index)))
|
||||
return -1;
|
||||
pdo->sync_index = sync_index;
|
||||
|
||||
ec_slave_config_load_default_mapping(sc, pdo);
|
||||
return 0;
|
||||
@@ -361,13 +400,18 @@ int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
|
||||
ec_direction_t dir)
|
||||
uint8_t sync_index)
|
||||
{
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("Clearing Pdo assignment for dir %u, config %u:%u.\n",
|
||||
dir, sc->alias, sc->position);
|
||||
EC_DBG("ecrt_slave_config_pdo_assign_clear(sc = 0x%x, "
|
||||
"sync_index = %u)\n", (u32) sc, sync_index);
|
||||
|
||||
ec_pdo_list_clear_pdos(&sc->pdos[dir]);
|
||||
if (sync_index >= EC_MAX_SYNCS) {
|
||||
EC_ERR("Invalid sync manager index %u!\n", sync_index);
|
||||
return;
|
||||
}
|
||||
|
||||
ec_pdo_list_clear_pdos(&sc->sync_configs[sync_index].pdos);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -376,16 +420,19 @@ int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc,
|
||||
uint16_t pdo_index, uint16_t entry_index, uint8_t entry_subindex,
|
||||
uint8_t entry_bit_length)
|
||||
{
|
||||
ec_direction_t dir;
|
||||
ec_pdo_t *pdo;
|
||||
uint8_t sync_index;
|
||||
ec_pdo_t *pdo = NULL;
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("Adding Pdo entry 0x%04X:%02X (%u bit) to mapping of Pdo"
|
||||
" 0x%04X, config %u:%u.\n", entry_index, entry_subindex,
|
||||
entry_bit_length, pdo_index, sc->alias, sc->position);
|
||||
EC_DBG("ecrt_slave_config_pdo_mapping_add(sc = 0x%x, "
|
||||
"pdo_index = 0x%04X, entry_index = 0x%04X, "
|
||||
"entry_subindex = 0x%02X, entry_bit_length = %u)\n",
|
||||
(u32) sc, pdo_index, entry_index, entry_subindex,
|
||||
entry_bit_length);
|
||||
|
||||
for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
|
||||
if ((pdo = ec_pdo_list_find_pdo(&sc->pdos[dir], pdo_index)))
|
||||
for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++)
|
||||
if ((pdo = ec_pdo_list_find_pdo(
|
||||
&sc->sync_configs[sync_index].pdos, pdo_index)))
|
||||
break;
|
||||
|
||||
if (!pdo) {
|
||||
@@ -403,15 +450,16 @@ int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc,
|
||||
void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
|
||||
uint16_t pdo_index)
|
||||
{
|
||||
ec_direction_t dir;
|
||||
ec_pdo_t *pdo;
|
||||
uint8_t sync_index;
|
||||
ec_pdo_t *pdo = NULL;
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("Clearing mapping of Pdo 0x%04X, config %u:%u.\n",
|
||||
pdo_index, sc->alias, sc->position);
|
||||
EC_DBG("ecrt_slave_config_pdo_mapping_clear(sc = 0x%x, "
|
||||
"pdo_index = 0x%04X)\n", (u32) sc, pdo_index);
|
||||
|
||||
for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
|
||||
if ((pdo = ec_pdo_list_find_pdo(&sc->pdos[dir], pdo_index)))
|
||||
for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++)
|
||||
if ((pdo = ec_pdo_list_find_pdo(
|
||||
&sc->sync_configs[sync_index].pdos, pdo_index)))
|
||||
break;
|
||||
|
||||
if (!pdo) {
|
||||
@@ -425,46 +473,59 @@ void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_pdos(ec_slave_config_t *sc, unsigned int n_infos,
|
||||
const ec_pdo_info_t pdo_infos[])
|
||||
int ecrt_slave_config_sync_managers(ec_slave_config_t *sc,
|
||||
unsigned int n_syncs, const ec_sync_info_t syncs[])
|
||||
{
|
||||
unsigned int i, j;
|
||||
const ec_pdo_info_t *pi;
|
||||
ec_pdo_list_t *pl;
|
||||
unsigned int cleared[] = {0, 0};
|
||||
const ec_pdo_entry_info_t *ei;
|
||||
unsigned int i, j, k;
|
||||
const ec_sync_info_t *sync_info;
|
||||
const ec_pdo_info_t *pdo_info;
|
||||
const ec_pdo_entry_info_t *entry_info;
|
||||
|
||||
if (!pdo_infos)
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("ecrt_slave_config_sync_managers(sc = 0x%x, n_syncs = %u, "
|
||||
"syncs = 0x%x)\n", (u32) sc, n_syncs, (u32) syncs);
|
||||
|
||||
if (!syncs)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < n_infos; i++) {
|
||||
pi = &pdo_infos[i];
|
||||
for (i = 0; i < n_syncs; i++) {
|
||||
sync_info = &syncs[i];
|
||||
|
||||
if (pi->dir == EC_END)
|
||||
if (sync_info->index == 0xff)
|
||||
break;
|
||||
|
||||
pl = &sc->pdos[pi->dir];
|
||||
|
||||
if (!cleared[pi->dir]) {
|
||||
ecrt_slave_config_pdo_assign_clear(sc, pi->dir);
|
||||
cleared[pi->dir] = 1;
|
||||
if (sync_info->index >= EC_MAX_SYNCS) {
|
||||
EC_ERR("Invalid sync manager index %u!\n", sync_info->index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ecrt_slave_config_pdo_assign_add(sc, pi->dir, pi->index))
|
||||
if (ecrt_slave_config_sync_manager(
|
||||
sc, sync_info->index, sync_info->dir))
|
||||
return -1;
|
||||
|
||||
if (pi->n_entries && pi->entries) { // mapping provided
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG(" Pdo mapping information provided.\n");
|
||||
if (sync_info->n_pdos && sync_info->pdos) {
|
||||
ecrt_slave_config_pdo_assign_clear(sc, sync_info->index);
|
||||
|
||||
ecrt_slave_config_pdo_mapping_clear(sc, pi->index);
|
||||
for (j = 0; j < sync_info->n_pdos; j++) {
|
||||
pdo_info = &sync_info->pdos[j];
|
||||
|
||||
for (j = 0; j < pi->n_entries; j++) {
|
||||
ei = &pi->entries[j];
|
||||
|
||||
if (ecrt_slave_config_pdo_mapping_add(sc, pi->index,
|
||||
ei->index, ei->subindex, ei->bit_length))
|
||||
if (ecrt_slave_config_pdo_assign_add(
|
||||
sc, sync_info->index, pdo_info->index))
|
||||
return -1;
|
||||
|
||||
if (pdo_info->n_entries && pdo_info->entries) {
|
||||
ecrt_slave_config_pdo_mapping_clear(sc, pdo_info->index);
|
||||
|
||||
for (k = 0; k < pdo_info->n_entries; k++) {
|
||||
entry_info = &pdo_info->entries[k];
|
||||
|
||||
if (ecrt_slave_config_pdo_mapping_add(sc,
|
||||
pdo_info->index, entry_info->index,
|
||||
entry_info->subindex,
|
||||
entry_info->bit_length))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -482,8 +543,8 @@ int ecrt_slave_config_reg_pdo_entry(
|
||||
unsigned int *bit_position
|
||||
)
|
||||
{
|
||||
ec_direction_t dir;
|
||||
ec_pdo_list_t *pdos;
|
||||
uint8_t sync_index;
|
||||
const ec_sync_config_t *sync_config;
|
||||
unsigned int bit_offset, bit_pos;
|
||||
ec_pdo_t *pdo;
|
||||
ec_pdo_entry_t *entry;
|
||||
@@ -492,18 +553,33 @@ int ecrt_slave_config_reg_pdo_entry(
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("ecrt_slave_config_reg_pdo_entry(sc = 0x%x, index = 0x%04X, "
|
||||
"subindex = 0x%02X, domain = 0x%x, bit_position = 0x%x)\n",
|
||||
(unsigned int) sc, index, subindex, (unsigned int) domain,
|
||||
(unsigned int) bit_position);
|
||||
(u32) sc, index, subindex, (u32) domain, (u32) bit_position);
|
||||
|
||||
for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
|
||||
pdos = &sc->pdos[dir];
|
||||
for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++) {
|
||||
sync_config = &sc->sync_configs[sync_index];
|
||||
bit_offset = 0;
|
||||
list_for_each_entry(pdo, &pdos->list, list) {
|
||||
|
||||
list_for_each_entry(pdo, &sync_config->pdos.list, list) {
|
||||
list_for_each_entry(entry, &pdo->entries, list) {
|
||||
if (entry->index != index || entry->subindex != subindex) {
|
||||
bit_offset += entry->bit_length;
|
||||
} else {
|
||||
goto found;
|
||||
sync_offset = ec_slave_config_prepare_fmmu(
|
||||
sc, domain, sync_index, sync_config->dir);
|
||||
if (sync_offset < 0)
|
||||
return -2;
|
||||
|
||||
bit_pos = bit_offset % 8;
|
||||
if (bit_position) {
|
||||
*bit_position = bit_pos;
|
||||
} else if (bit_pos) {
|
||||
EC_ERR("Pdo entry 0x%04X:%02X does not byte-align "
|
||||
"in config %u:%u.\n", index, subindex,
|
||||
sc->alias, sc->position);
|
||||
return -3;
|
||||
}
|
||||
|
||||
return sync_offset + bit_offset / 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -512,22 +588,6 @@ int ecrt_slave_config_reg_pdo_entry(
|
||||
EC_ERR("Pdo entry 0x%04X:%02X is not mapped in slave config %u:%u.\n",
|
||||
index, subindex, sc->alias, sc->position);
|
||||
return -1;
|
||||
|
||||
found:
|
||||
sync_offset = ec_slave_config_prepare_fmmu(sc, domain, dir);
|
||||
if (sync_offset < 0)
|
||||
return -2;
|
||||
|
||||
bit_pos = bit_offset % 8;
|
||||
if (bit_position) {
|
||||
*bit_position = bit_pos;
|
||||
} else if (bit_pos) {
|
||||
EC_ERR("Pdo entry 0x%04X:%02X does not byte-align in config %u:%u.\n",
|
||||
index, subindex, sc->alias, sc->position);
|
||||
return -3;
|
||||
}
|
||||
|
||||
return sync_offset + bit_offset / 8;
|
||||
}
|
||||
|
||||
|
||||
@@ -643,11 +703,12 @@ void ecrt_slave_config_state(const ec_slave_config_t *sc,
|
||||
|
||||
/** \cond */
|
||||
|
||||
EXPORT_SYMBOL(ecrt_slave_config_sync_manager);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_pdo_assign_add);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_pdo_assign_clear);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_pdo_mapping_add);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_pdo_mapping_clear);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_pdos);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_sync_managers);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_reg_pdo_entry);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_sdo);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_sdo8);
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "slave.h"
|
||||
#include "sync_config.h"
|
||||
#include "fmmu_config.h"
|
||||
#include "pdo_list.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -67,13 +67,14 @@ struct ec_slave_config {
|
||||
ec_slave_t *slave; /**< Slave pointer. This is \a NULL, if the slave is
|
||||
offline. */
|
||||
|
||||
ec_pdo_list_t pdos[2]; /**< Output and input Pdo assignment / mapping. */
|
||||
ec_sync_config_t sync_configs[EC_MAX_SYNCS]; /**< Sync manager
|
||||
configurations. */
|
||||
ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]; /**< FMMU configurations. */
|
||||
uint8_t used_fmmus; /**< Number of FMMUs used. */
|
||||
|
||||
struct list_head sdo_configs; /**< List of Sdo configurations. */
|
||||
struct list_head sdo_requests; /**< List of Sdo requests. */
|
||||
|
||||
ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]; /**< FMMU configurations. */
|
||||
uint8_t used_fmmus; /**< Number of FMMUs used. */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -85,9 +86,7 @@ void ec_slave_config_clear(ec_slave_config_t *);
|
||||
int ec_slave_config_attach(ec_slave_config_t *);
|
||||
void ec_slave_config_detach(ec_slave_config_t *);
|
||||
|
||||
void ec_slave_config_load_default_assignment(ec_slave_config_t *);
|
||||
void ec_slave_config_load_default_mapping(const ec_slave_config_t *,
|
||||
ec_pdo_t *);
|
||||
void ec_slave_config_load_default_sync_config(ec_slave_config_t *);
|
||||
|
||||
unsigned int ec_slave_config_sdo_count(const ec_slave_config_t *);
|
||||
const ec_sdo_request_t *ec_slave_config_get_sdo_by_pos_const(
|
||||
|
||||
@@ -49,13 +49,14 @@
|
||||
*/
|
||||
void ec_sync_init(
|
||||
ec_sync_t *sync, /**< EtherCAT sync manager. */
|
||||
ec_slave_t *slave, /**< EtherCAT slave. */
|
||||
unsigned int index /**< Sync manager index. */
|
||||
ec_slave_t *slave /**< EtherCAT slave. */
|
||||
)
|
||||
{
|
||||
sync->slave = slave;
|
||||
sync->index = index;
|
||||
|
||||
sync->physical_start_address = 0x0000;
|
||||
sync->default_length = 0x0000;
|
||||
sync->control_register = 0x00;
|
||||
sync->enable = 0x00;
|
||||
ec_pdo_list_init(&sync->pdos);
|
||||
sync->assign_source = EC_ASSIGN_NONE;
|
||||
}
|
||||
@@ -70,15 +71,12 @@ void ec_sync_init_copy(
|
||||
)
|
||||
{
|
||||
sync->slave = other->slave;
|
||||
sync->index = other->index;
|
||||
sync->physical_start_address = other->physical_start_address;
|
||||
sync->length = other->length;
|
||||
sync->default_length = other->default_length;
|
||||
sync->control_register = other->control_register;
|
||||
sync->enable = other->enable;
|
||||
|
||||
ec_pdo_list_init(&sync->pdos);
|
||||
ec_pdo_list_copy(&sync->pdos, &other->pdos);
|
||||
|
||||
sync->assign_source = other->assign_source;
|
||||
}
|
||||
|
||||
@@ -95,28 +93,37 @@ void ec_sync_clear(
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Initializes a sync manager configuration page with SII data.
|
||||
/** Initializes a sync manager configuration page.
|
||||
*
|
||||
* The referenced memory (\a data) must be at least \a EC_SYNC_SIZE bytes.
|
||||
*/
|
||||
void ec_sync_config(
|
||||
void ec_sync_page(
|
||||
const ec_sync_t *sync, /**< Sync manager. */
|
||||
uint8_t sync_index, /**< Index of the sync manager. */
|
||||
uint16_t data_size, /**< Data size. */
|
||||
ec_direction_t dir, /**< Direction (overrides the control byte,
|
||||
if set to EC_DIR_INPUT or EC_DIR_OUTPUT). */
|
||||
uint8_t *data /**> Configuration memory. */
|
||||
)
|
||||
{
|
||||
// enable only if SII enable is set and size is > 0.
|
||||
uint16_t enable = sync->enable && data_size;
|
||||
uint8_t control = sync->control_register;
|
||||
|
||||
if (sync->slave->master->debug_level) {
|
||||
EC_DBG("SM%u: Addr 0x%04X, Size %3u, Ctrl 0x%02X, En %u\n",
|
||||
sync->index, sync->physical_start_address,
|
||||
data_size, sync->control_register, enable);
|
||||
if (dir == EC_DIR_OUTPUT || dir == EC_DIR_INPUT) {
|
||||
// override sync manager direction bits with dir parameter
|
||||
EC_WRITE_BIT(&control, 2, dir == EC_DIR_OUTPUT ? 1 : 0);
|
||||
EC_WRITE_BIT(&control, 3, 0);
|
||||
}
|
||||
|
||||
if (sync->slave->master->debug_level)
|
||||
EC_DBG("SM%u: Addr 0x%04X, Size %3u, Ctrl 0x%02X, En %u\n",
|
||||
sync_index, sync->physical_start_address,
|
||||
data_size, control, enable);
|
||||
|
||||
EC_WRITE_U16(data, sync->physical_start_address);
|
||||
EC_WRITE_U16(data + 2, data_size);
|
||||
EC_WRITE_U8 (data + 4, sync->control_register);
|
||||
EC_WRITE_U8 (data + 4, control);
|
||||
EC_WRITE_U8 (data + 5, 0x00); // status byte (read only)
|
||||
EC_WRITE_U16(data + 6, enable);
|
||||
}
|
||||
@@ -137,35 +144,17 @@ int ec_sync_add_pdo(
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Get direction covered by sync manager.
|
||||
*
|
||||
* \return Direction covered by the given sync manager.
|
||||
/** Determines the default direction from the control register.
|
||||
*/
|
||||
ec_direction_t ec_sync_direction(
|
||||
ec_direction_t ec_sync_default_direction(
|
||||
const ec_sync_t *sync /**< EtherCAT sync manager. */
|
||||
)
|
||||
{
|
||||
int index = sync->index;
|
||||
|
||||
if (sync->slave->sii.sync_count != 1) {
|
||||
if (sync->slave && sync->slave->sii.mailbox_protocols) {
|
||||
index -= 2;
|
||||
}
|
||||
|
||||
if (index < 0 || index > 1) {
|
||||
EC_WARN("ec_sync_get_direction(): invalid sync manager index.\n");
|
||||
return EC_DIR_OUTPUT;
|
||||
}
|
||||
} else { // sync_count == 1
|
||||
if (!list_empty(&sync->pdos.list)) {
|
||||
const ec_pdo_t *pdo =
|
||||
list_entry(sync->pdos.list.next, ec_pdo_t, list);
|
||||
return pdo->dir;
|
||||
}
|
||||
|
||||
switch ((sync->control_register & 0x0C) >> 2) {
|
||||
case 0x0: return EC_DIR_INPUT;
|
||||
case 0x1: return EC_DIR_INPUT;
|
||||
default: return EC_DIR_INVALID;
|
||||
}
|
||||
|
||||
return (ec_direction_t) index;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
#ifndef __EC_SYNC_H__
|
||||
#define __EC_SYNC_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "../include/ecrt.h"
|
||||
|
||||
#include "globals.h"
|
||||
@@ -64,9 +62,8 @@ typedef enum {
|
||||
*/
|
||||
typedef struct {
|
||||
ec_slave_t *slave; /**< Slave, the sync manager belongs to. */
|
||||
unsigned int index; /**< Sync manager index. */
|
||||
uint16_t physical_start_address; /**< Physical start address. */
|
||||
uint16_t length; /**< Data length in bytes. */
|
||||
uint16_t default_length; /**< Data length in bytes. */
|
||||
uint8_t control_register; /**< Control register value. */
|
||||
uint8_t enable; /**< Enable bit. */
|
||||
ec_pdo_list_t pdos; /**< Current Pdo assignment. */
|
||||
@@ -75,15 +72,13 @@ typedef struct {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_sync_init(ec_sync_t *, ec_slave_t *, unsigned int);
|
||||
void ec_sync_init(ec_sync_t *, ec_slave_t *);
|
||||
void ec_sync_init_copy(ec_sync_t *, const ec_sync_t *);
|
||||
void ec_sync_clear(ec_sync_t *);
|
||||
|
||||
void ec_sync_config(const ec_sync_t *, uint16_t, uint8_t *);
|
||||
|
||||
void ec_sync_page(const ec_sync_t *, uint8_t, uint16_t, ec_direction_t,
|
||||
uint8_t *);
|
||||
int ec_sync_add_pdo(ec_sync_t *, const ec_pdo_t *);
|
||||
|
||||
ec_direction_t ec_sync_direction(const ec_sync_t *);
|
||||
ec_direction_t ec_sync_default_direction(const ec_sync_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
66
master/sync_config.c
Normal file
66
master/sync_config.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
* This file is part of the IgH EtherCAT Master.
|
||||
*
|
||||
* The IgH EtherCAT Master is free software; you can redistribute it
|
||||
* and/or modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The IgH EtherCAT Master is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the IgH EtherCAT Master; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* The right to use EtherCAT Technology is granted and comes free of
|
||||
* charge under condition of compatibility of product made by
|
||||
* Licensee. People intending to distribute/sell products based on the
|
||||
* code, have to sign an agreement to guarantee that products using
|
||||
* software based on IgH EtherCAT master stay compatible with the actual
|
||||
* EtherCAT specification (which are released themselves as an open
|
||||
* standard) as the (only) precondition to have the right to use EtherCAT
|
||||
* Technology, IP and trade marks.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* EtherCAT sync manager configuration methods.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "globals.h"
|
||||
#include "sync_config.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Constructor.
|
||||
*/
|
||||
void ec_sync_config_init(
|
||||
ec_sync_config_t *sync_config /**< Sync manager configuration. */
|
||||
)
|
||||
{
|
||||
sync_config->dir = EC_DIR_INVALID;
|
||||
ec_pdo_list_init(&sync_config->pdos);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Destructor.
|
||||
*/
|
||||
void ec_sync_config_clear(
|
||||
ec_sync_config_t *sync_config /**< Sync manager configuration. */
|
||||
)
|
||||
{
|
||||
ec_pdo_list_clear(&sync_config->pdos);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
64
master/sync_config.h
Normal file
64
master/sync_config.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
* This file is part of the IgH EtherCAT Master.
|
||||
*
|
||||
* The IgH EtherCAT Master is free software; you can redistribute it
|
||||
* and/or modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The IgH EtherCAT Master is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the IgH EtherCAT Master; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* The right to use EtherCAT Technology is granted and comes free of
|
||||
* charge under condition of compatibility of product made by
|
||||
* Licensee. People intending to distribute/sell products based on the
|
||||
* code, have to sign an agreement to guarantee that products using
|
||||
* software based on IgH EtherCAT master stay compatible with the actual
|
||||
* EtherCAT specification (which are released themselves as an open
|
||||
* standard) as the (only) precondition to have the right to use EtherCAT
|
||||
* Technology, IP and trade marks.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* EtherCAT sync manager.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __EC_SYNC_CONFIG_H__
|
||||
#define __EC_SYNC_CONFIG_H__
|
||||
|
||||
#include "../include/ecrt.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "pdo_list.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Sync manager configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
ec_direction_t dir; /**< Sync manager direction. */
|
||||
ec_pdo_list_t pdos; /**< Current Pdo assignment. */
|
||||
} ec_sync_config_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_sync_config_init(ec_sync_config_t *);
|
||||
void ec_sync_config_clear(ec_sync_config_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
@@ -200,11 +200,12 @@ void Master::showConfig()
|
||||
<< hex << setw(8) << config.product_code << endl
|
||||
<< "Attached: " << (config.attached ? "yes" : "no") << endl;
|
||||
|
||||
for (j = 0; j < 2; j++) {
|
||||
if (config.pdo_count[j]) {
|
||||
cout << (j ? "Input" : "Output")
|
||||
<< " Pdo assignment / mapping " << endl;
|
||||
for (k = 0; k < config.pdo_count[j]; k++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (config.syncs[j].pdo_count) {
|
||||
cout << "SM" << dec << j << " ("
|
||||
<< (config.syncs[j].dir == EC_DIR_INPUT
|
||||
? "Input" : "Output") << ")" << endl;
|
||||
for (k = 0; k < config.syncs[j].pdo_count; k++) {
|
||||
getConfigPdo(&pdo, i, j, k);
|
||||
|
||||
cout << " Pdo 0x"
|
||||
@@ -1190,7 +1191,7 @@ void Master::showDomain(unsigned int domainIndex)
|
||||
cout << " SlaveConfig "
|
||||
<< fmmu.slave_config_alias << ":" << fmmu.slave_config_position
|
||||
<< ", Dir "
|
||||
<< setfill(' ') << setw(3) << (fmmu.fmmu_dir ? "In" : "Out")
|
||||
<< setfill(' ') << setw(3) << (fmmu.dir == EC_DIR_INPUT ? "In" : "Out")
|
||||
<< ", LogAddr 0x"
|
||||
<< hex << setfill('0') << setw(8) << fmmu.logical_address
|
||||
<< ", Size " << dec << fmmu.data_size << endl;
|
||||
@@ -1250,7 +1251,8 @@ void Master::listSlavePdos(
|
||||
for (j = 0; j < sync.pdo_count; j++) {
|
||||
getPdo(&pdo, slavePosition, i, j);
|
||||
|
||||
cout << " " << (pdo.dir ? "T" : "R") << "xPdo 0x"
|
||||
cout << " " << (sync.control_register & 0x04 ? "R" : "T")
|
||||
<< "xPdo 0x"
|
||||
<< hex << setfill('0') << setw(4) << pdo.index
|
||||
<< " \"" << pdo.name << "\"" << endl;
|
||||
|
||||
@@ -1423,6 +1425,7 @@ void Master::generateSlaveXml(uint16_t slavePosition)
|
||||
ec_ioctl_slave_t slave;
|
||||
ec_ioctl_sync_t sync;
|
||||
ec_ioctl_pdo_t pdo;
|
||||
string pdoType;
|
||||
ec_ioctl_pdo_entry_t entry;
|
||||
unsigned int i, j, k;
|
||||
|
||||
@@ -1449,9 +1452,11 @@ void Master::generateSlaveXml(uint16_t slavePosition)
|
||||
|
||||
for (j = 0; j < sync.pdo_count; j++) {
|
||||
getPdo(&pdo, slavePosition, i, j);
|
||||
pdoType = (sync.control_register & 0x04 ? "R" : "T");
|
||||
pdoType += "xPdo";
|
||||
|
||||
cout
|
||||
<< " <" << (pdo.dir ? "T" : "R") << "xPdo>" << endl
|
||||
<< " <" << pdoType << ">" << endl
|
||||
<< " <Index>#x"
|
||||
<< hex << setfill('0') << setw(4) << pdo.index
|
||||
<< "</Index>" << endl
|
||||
@@ -1503,7 +1508,7 @@ void Master::generateSlaveXml(uint16_t slavePosition)
|
||||
}
|
||||
|
||||
cout
|
||||
<< " </" << (pdo.dir ? "T" : "R") << "xPdo>" << endl;
|
||||
<< " </" << pdoType << ">" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1553,12 +1558,12 @@ void Master::getConfig(ec_ioctl_config_t *data, unsigned int index)
|
||||
void Master::getConfigPdo(
|
||||
ec_ioctl_config_pdo_t *data,
|
||||
unsigned int index,
|
||||
unsigned int dir,
|
||||
unsigned int pdo_pos
|
||||
uint8_t sync_index,
|
||||
uint16_t pdo_pos
|
||||
)
|
||||
{
|
||||
data->config_index = index;
|
||||
data->direction = dir;
|
||||
data->sync_index = sync_index;
|
||||
data->pdo_pos = pdo_pos;
|
||||
|
||||
if (ioctl(fd, EC_IOCTL_CONFIG_PDO, data) < 0) {
|
||||
@@ -1573,13 +1578,13 @@ void Master::getConfigPdo(
|
||||
void Master::getConfigPdoEntry(
|
||||
ec_ioctl_config_pdo_entry_t *data,
|
||||
unsigned int index,
|
||||
unsigned int dir,
|
||||
unsigned int pdo_pos,
|
||||
unsigned int entry_pos
|
||||
uint8_t sync_index,
|
||||
uint16_t pdo_pos,
|
||||
uint8_t entry_pos
|
||||
)
|
||||
{
|
||||
data->config_index = index;
|
||||
data->direction = dir;
|
||||
data->sync_index = sync_index;
|
||||
data->pdo_pos = pdo_pos;
|
||||
data->entry_pos = entry_pos;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
#include "../include/ecrt.h"
|
||||
#include "../master/ioctl.h"
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -73,10 +74,10 @@ class Master
|
||||
unsigned int slaveCount();
|
||||
void getMaster(ec_ioctl_master_t *);
|
||||
void getConfig(ec_ioctl_config_t *, unsigned int);
|
||||
void getConfigPdo(ec_ioctl_config_pdo_t *, unsigned int,
|
||||
unsigned int, unsigned int);
|
||||
void getConfigPdo(ec_ioctl_config_pdo_t *, unsigned int, uint8_t,
|
||||
uint16_t);
|
||||
void getConfigPdoEntry(ec_ioctl_config_pdo_entry_t *, unsigned int,
|
||||
unsigned int, unsigned int, unsigned int);
|
||||
uint8_t, uint16_t, uint8_t);
|
||||
void getConfigSdo(ec_ioctl_config_sdo_t *, unsigned int, unsigned int);
|
||||
void getDomain(ec_ioctl_domain_t *, unsigned int);
|
||||
void getFmmu(ec_ioctl_domain_fmmu_t *, unsigned int, unsigned int);
|
||||
|
||||
Reference in New Issue
Block a user