Implemented ecrt_slave_config_pdo_mode() interface.

This commit is contained in:
Florian Pose
2026-08-13 17:42:08 +02:00
parent 1e5a9be3c3
commit 46fefd0958
16 changed files with 403 additions and 19 deletions
+1
View File
@@ -14,4 +14,5 @@ filter=-whitespace/comments
filter=-whitespace/empty_loop_body
filter=-whitespace/indent
filter=-whitespace/newline
filter=-whitespace/parens
linelength=78
+3
View File
@@ -2,6 +2,9 @@
## Version 1.7.0
- Added `ecrt_slave_config_pdo_mode()` to select whether a slave's PDO
assignment and PDO configuration are read from resp. written to it via
CoE, for slaves with a fixed or otherwise well-known PDO layout.
- Added SII caching functionality with
- the kernel module parameter `sii_caching`,
- the configuration variable `SII_CACHING`,
+9
View File
@@ -639,6 +639,15 @@ int ecrt_slave_config_watchdog(
return 0;
}
int ecrt_slave_config_pdo_mode(
ec_slave_config_t *sc, /**< Slave configuration. */
ec_pdo_mode_t assign_mode, /**< Mode for the PDO assignment. */
ec_pdo_mode_t config_mode /**< Mode for the PDO configuration. */
)
{
return 0;
}
int ecrt_slave_config_pdo_assign_add(
ec_slave_config_t *sc, /**< Slave configuration. */
uint8_t sync_index, /**< Sync manager index. Must be less
+97 -1
View File
@@ -36,6 +36,9 @@
* - Added ecrt_master_sii_caching() to set the SII caching method and added
* the feature flag EC_HAVE_SII_CACHING and the enum type
* ec_sii_caching_fields_t.
* - Added ecrt_slave_config_pdo_mode() to select whether a slave's PDO
* assignment and PDO configuration are read from resp. written to it via
* CoE, the enum type ec_pdo_mode_t and the feature flag EC_HAVE_PDO_MODE.
*
* Changes in version 1.6.0:
*
@@ -252,6 +255,11 @@
*/
#define EC_HAVE_SII_CACHING
/** Defined, if the method ecrt_slave_config_pdo_mode() and the enum type
* ec_pdo_mode_t are available.
*/
#define EC_HAVE_PDO_MODE
/****************************************************************************/
/** Symbol visibility control macro.
@@ -394,7 +402,7 @@ typedef struct {
- 8: \a OP
Note that each state is coded in a different
bit! */
bit. */
} ec_slave_config_state_t;
/****************************************************************************/
@@ -532,6 +540,42 @@ typedef enum {
/****************************************************************************/
/** PDO handling mode.
*
* Used for the \a assign_mode and \a config_mode parameters of
* ecrt_slave_config_pdo_mode() to select whether a slave's PDO assignment
* (which PDOs are mapped into a sync manager, CoE objects 0x1C10-0x1C13)
* resp. its PDO configuration (the entries mapped into an assigned PDO) are
* read from resp. written to the slave via CoE.
*/
typedef enum {
EC_PDO_MODE_FIXED, /**< Neither read nor write via CoE. Trust that the
slave already matches the layout given via
ecrt_slave_config_pdos() and friends. */
EC_PDO_MODE_WRITE, /**< Write the configured state via CoE every time
the slave is configured, without reading the
current state first ("blind write"). */
EC_PDO_MODE_READ_WRITE, /**< Read the current state via CoE while
scanning the slave, and unconditionally
(re-)write it every time the slave is
configured. This is the default. */
EC_PDO_MODE_WRITE_IF_DIFFERENT, /**< Read the current state via CoE
while scanning the slave, and write
it back only if it differs from the
configured state. */
} ec_pdo_mode_t;
/** Default PDO handling mode: read via CoE while scanning, and
* unconditionally (re-)write via CoE every time the slave is configured.
* This is the behavior in effect if ecrt_slave_config_pdo_mode() is never
* called.
*
* \see ec_pdo_mode_t
*/
#define EC_PDO_MODE_DEFAULT EC_PDO_MODE_READ_WRITE
/****************************************************************************/
/** PDO entry configuration information.
*
* This is the data type of the \a entries field in ec_pdo_info_t.
@@ -1444,6 +1488,58 @@ EC_PUBLIC_API int ecrt_slave_config_watchdog(
so the default is used. */
);
/** Selects how a slave's PDO assignment and PDO configuration are read
* from resp. written to it via CoE.
*
* By default (i. e. if this method is not called), a slave's PDO
* assignment and PDO configuration are both read via CoE while the bus is
* scanned, and are both unconditionally (re-)written via CoE every time
* the slave is configured (e. g. after a state change or reconnect). For
* slaves with a fixed or otherwise well-known PDO structure, this can be
* relaxed independently for the assignment and the configuration, to save
* mailbox round trips during bus scanning and/or slave configuration.
*
* If \a assign_mode resp. \a config_mode is EC_PDO_MODE_FIXED or
* EC_PDO_MODE_WRITE, the corresponding aspect is not read from the slave
* while scanning; the master then relies solely on the PDO configuration
* made available through ecrt_slave_config_pdos(),
* ecrt_slave_config_sync_manager(), ecrt_slave_config_pdo_assign_add()
* and ecrt_slave_config_pdo_mapping_add(). The application is responsible
* for making sure this matches the slave's actual capabilities in that
* case.
*
* \note Reading the PDO configuration requires first discovering the PDO
* assignment (which PDOs exist), since the master must know a PDO's index
* before it can query its entries. Therefore, whenever \a config_mode is
* EC_PDO_MODE_READ_WRITE or EC_PDO_MODE_WRITE_IF_DIFFERENT, the PDO
* assignment is read while scanning the bus as well, regardless of \a
* assign_mode. This is harmless, but means that the mailbox traffic saved
* by choosing EC_PDO_MODE_FIXED or EC_PDO_MODE_WRITE for \a assign_mode is
* not realized in that particular combination.
*
* \attention Because bus scanning happens before slave configurations are
* attached to their slaves, a non-default \a assign_mode or \a
* config_mode is only guaranteed to take effect for the scanning of a
* slave if this method is called (i. e. the slave configuration is
* created via ecrt_master_slave_config()) before that slave is scanned
* for the first time. Otherwise, the scan falls back to the default
* (reading) behavior for that particular scan; a subsequent bus rescan
* (e. g. via the "ethercat rescan" command) will pick up the configured
* mode.
*
* This method has to be called in non-realtime context before
* ecrt_master_activate().
*
* \apiusage{master_idle,blocking}
*
* \return 0 on success, otherwise negative error code.
*/
EC_PUBLIC_API int ecrt_slave_config_pdo_mode(
ec_slave_config_t *sc, /**< Slave configuration. */
ec_pdo_mode_t assign_mode, /**< Mode for the PDO assignment. */
ec_pdo_mode_t config_mode /**< Mode for the PDO configuration. */
);
/** Add a PDO to a sync manager's PDO assignment.
*
* This method has to be called in non-realtime context before
+1
View File
@@ -119,4 +119,5 @@ LIBETHERCAT_1.6 {
LIBETHERCAT_1.7 {
global:
ecrt_master_sii_caching;
ecrt_slave_config_pdo_mode;
} LIBETHERCAT_1.6;
+24 -2
View File
@@ -139,6 +139,28 @@ int ecrt_slave_config_watchdog(ec_slave_config_t *sc,
/****************************************************************************/
int ecrt_slave_config_pdo_mode(ec_slave_config_t *sc,
ec_pdo_mode_t assign_mode, ec_pdo_mode_t config_mode)
{
ec_ioctl_config_t data;
int ret;
memset(&data, 0x00, sizeof(ec_ioctl_config_t));
data.config_index = sc->index;
data.pdo_assign_mode = assign_mode;
data.pdo_config_mode = config_mode;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_PDO_MODE, &data);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to set PDO mode: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/****************************************************************************/
int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
uint8_t sync_index, uint16_t pdo_index)
{
@@ -258,7 +280,6 @@ int ecrt_slave_config_pdos(ec_slave_config_t *sc,
ecrt_slave_config_pdo_assign_clear(sc, sync_info->index);
if (sync_info->n_pdos && sync_info->pdos) {
for (j = 0; j < sync_info->n_pdos; j++) {
pdo_info = &sync_info->pdos[j];
@@ -846,7 +867,8 @@ int ecrt_slave_config_state(const ec_slave_config_t *sc,
/****************************************************************************/
int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no,
uint16_t idn, ec_al_state_t al_state, const uint8_t *data, size_t size)
uint16_t idn, ec_al_state_t al_state, const uint8_t *data,
size_t size)
{
ec_ioctl_sc_idn_t io;
int ret;
+66 -4
View File
@@ -39,6 +39,7 @@ void ec_fsm_pdo_print(const ec_fsm_pdo_t *);
int ec_fsm_pdo_running(const ec_fsm_pdo_t *);
ec_pdo_t *ec_fsm_pdo_conf_action_next_pdo(const ec_fsm_pdo_t *,
const struct list_head *);
static int ec_pdo_mode_reads(ec_pdo_mode_t);
/****************************************************************************/
@@ -118,10 +119,16 @@ void ec_fsm_pdo_print(
*/
void ec_fsm_pdo_start_reading(
ec_fsm_pdo_t *fsm, /**< PDO configuration state machine. */
ec_slave_t *slave /**< slave to configure */
ec_slave_t *slave, /**< slave to configure */
ec_pdo_mode_t assign_mode, /**< Whether/how to read the PDO
assignment. */
ec_pdo_mode_t config_mode /**< Whether/how to read the PDO
configuration. */
)
{
fsm->slave = slave;
fsm->assign_mode = assign_mode;
fsm->config_mode = config_mode;
fsm->state = ec_fsm_pdo_read_state_start;
}
@@ -184,6 +191,18 @@ int ec_fsm_pdo_success(
return fsm->state == ec_fsm_pdo_state_end;
}
/****************************************************************************/
/** Returns, if the given PDO handling mode implies reading via CoE.
*/
static int ec_pdo_mode_reads(
ec_pdo_mode_t mode /**< PDO handling mode. */
)
{
return mode == EC_PDO_MODE_READ_WRITE
|| mode == EC_PDO_MODE_WRITE_IF_DIFFERENT;
}
/*****************************************************************************
* Reading state funtions.
****************************************************************************/
@@ -217,6 +236,13 @@ void ec_fsm_pdo_read_action_next_sync(
if (!(fsm->sync = ec_slave_get_sync(slave, fsm->sync_index)))
continue;
// reading the PDO configuration requires first discovering the PDO
// assignment, so a read is done if either aspect is to be read
if (!ec_pdo_mode_reads(fsm->assign_mode)
&& !ec_pdo_mode_reads(fsm->config_mode)) {
continue;
}
EC_SLAVE_DBG(slave, 1, "Reading PDO assignment of SM%u.\n",
fsm->sync_index);
@@ -344,6 +370,14 @@ void ec_fsm_pdo_read_state_pdo(
list_add_tail(&fsm->pdo->list, &fsm->pdos.list);
if (!ec_pdo_mode_reads(fsm->config_mode)) {
// PDO assignment only; the entries mapped into this PDO are not
// to be read
fsm->pdo_pos++;
ec_fsm_pdo_read_action_next_pdo(fsm, datagram);
return;
}
fsm->state = ec_fsm_pdo_read_state_pdo_entries;
ec_fsm_pdo_entry_start_reading(&fsm->fsm_pdo_entry, fsm->slave, fsm->pdo);
fsm->state(fsm, datagram); // execute immediately
@@ -429,6 +463,9 @@ void ec_fsm_pdo_conf_action_next_sync(
return;
}
fsm->assign_mode = fsm->slave->config->pdo_assign_mode;
fsm->config_mode = fsm->slave->config->pdo_config_mode;
if (ec_pdo_list_copy(&fsm->pdos,
&fsm->slave->config->sync_configs[fsm->sync_index].pdos))
{
@@ -479,7 +516,8 @@ void ec_fsm_pdo_conf_action_pdo_mapping(
ec_pdo_clear_entries(&fsm->slave_pdo);
}
if (list_empty(&fsm->slave_pdo.entries)) {
if (list_empty(&fsm->slave_pdo.entries)
&& ec_pdo_mode_reads(fsm->config_mode)) {
EC_SLAVE_DBG(fsm->slave, 1, "Reading mapping of PDO 0x%04X.\n",
fsm->pdo->index);
@@ -528,12 +566,24 @@ void ec_fsm_pdo_conf_action_check_mapping(
ec_datagram_t *datagram /**< Datagram to use. */
)
{
if (fsm->config_mode == EC_PDO_MODE_FIXED) {
// PDO configuration is trusted to already match; do not touch it
ec_fsm_pdo_conf_action_next_pdo_mapping(fsm, datagram);
return;
}
// check, if slave supports PDO configuration
if ((fsm->slave->sii.mailbox_protocols & EC_MBOX_COE)
&& fsm->slave->sii.has_general
&& fsm->slave->sii.coe_details.enable_pdo_configuration) {
if (fsm->config_mode == EC_PDO_MODE_WRITE_IF_DIFFERENT
&& ec_pdo_equal_entries(fsm->pdo, &fsm->slave_pdo)) {
// mapping already matches the desired configuration
ec_fsm_pdo_conf_action_next_pdo_mapping(fsm, datagram);
return;
}
// always write PDO mapping
// write PDO mapping
ec_fsm_pdo_entry_start_configuration(&fsm->fsm_pdo_entry, fsm->slave,
fsm->pdo, &fsm->slave_pdo);
fsm->state = ec_fsm_pdo_conf_state_mapping;
@@ -603,11 +653,23 @@ void ec_fsm_pdo_conf_action_check_assignment(
ec_datagram_t *datagram /**< Datagram to use. */
)
{
if (fsm->assign_mode == EC_PDO_MODE_FIXED) {
// PDO assignment is trusted to already match; do not touch it
ec_fsm_pdo_conf_action_next_sync(fsm, datagram);
return;
}
if ((fsm->slave->sii.mailbox_protocols & EC_MBOX_COE)
&& fsm->slave->sii.has_general
&& fsm->slave->sii.coe_details.enable_pdo_assign) {
if (fsm->assign_mode == EC_PDO_MODE_WRITE_IF_DIFFERENT
&& ec_pdo_list_equal(&fsm->sync->pdos, &fsm->pdos)) {
// assignment already matches the desired configuration
ec_fsm_pdo_conf_action_next_sync(fsm, datagram);
return;
}
// always write PDO assignment
// write PDO assignment
if (fsm->slave->master->debug_level) {
EC_SLAVE_DBG(fsm->slave, 1, "Setting PDO assignment of SM%u:\n",
fsm->sync_index);
+10 -1
View File
@@ -58,6 +58,14 @@ struct ec_fsm_pdo
ec_pdo_t *pdo; /**< Current PDO. */
unsigned int pdo_pos; /**< Assignment position of current PDOs. */
unsigned int pdo_count; /**< Number of assigned PDOs. */
ec_pdo_mode_t assign_mode; /**< Whether/how to read resp. write the PDO
assignment. Set once by
ec_fsm_pdo_start_reading() for reading, or
refreshed from fsm->slave->config for each
sync manager while writing. */
ec_pdo_mode_t config_mode; /**< Whether/how to read resp. write the PDO
configuration. See \a assign_mode. */
};
/****************************************************************************/
@@ -65,7 +73,8 @@ struct ec_fsm_pdo
void ec_fsm_pdo_init(ec_fsm_pdo_t *, ec_fsm_coe_t *);
void ec_fsm_pdo_clear(ec_fsm_pdo_t *);
void ec_fsm_pdo_start_reading(ec_fsm_pdo_t *, ec_slave_t *);
void ec_fsm_pdo_start_reading(ec_fsm_pdo_t *, ec_slave_t *,
ec_pdo_mode_t, ec_pdo_mode_t);
void ec_fsm_pdo_start_configuration(ec_fsm_pdo_t *, ec_slave_t *);
int ec_fsm_pdo_exec(ec_fsm_pdo_t *, ec_datagram_t *);
+23 -1
View File
@@ -1056,10 +1056,32 @@ void ec_fsm_slave_scan_enter_pdos(
)
{
ec_slave_t *slave = fsm->slave;
ec_pdo_mode_t assign_mode = EC_PDO_MODE_DEFAULT;
ec_pdo_mode_t config_mode = EC_PDO_MODE_DEFAULT;
const ec_slave_config_t *sc;
// Look up a not-yet-attached configuration for this slave (attaching
// only happens after the whole bus has been scanned) to find out if
// the application requested non-default PDO scanning behavior.
if ((sc = ec_master_find_config_for_slave(slave->master, slave))) {
assign_mode = sc->pdo_assign_mode;
config_mode = sc->pdo_config_mode;
}
if (assign_mode == EC_PDO_MODE_FIXED
|| assign_mode == EC_PDO_MODE_WRITE) {
if (config_mode == EC_PDO_MODE_FIXED
|| config_mode == EC_PDO_MODE_WRITE) {
EC_SLAVE_DBG(slave, 1, "Skipping PDO scanning"
" (fixed PDO assignment/configuration).\n");
fsm->state = ec_fsm_slave_scan_state_end;
return;
}
}
EC_SLAVE_DBG(slave, 1, "Scanning PDO assignment and mapping.\n");
fsm->state = ec_fsm_slave_scan_state_pdos;
ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave);
ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave, assign_mode, config_mode);
ec_fsm_pdo_exec(fsm->fsm_pdo, fsm->datagram); // execute immediately
}
+63 -5
View File
@@ -63,7 +63,8 @@
# define ec_ioctl_lock(lock) rt_mutex_lock(lock)
# define ec_ioctl_unlock(lock) rt_mutex_unlock(lock)
# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) || \
(defined(CONFIG_PREEMPT_RT_FULL) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
(defined(CONFIG_PREEMPT_RT_FULL) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
# define ec_ioctl_lock_interruptible(lock) \
rt_mutex_lock_interruptible(lock)
# else
@@ -650,7 +651,7 @@ static ATTRIBUTES int ec_ioctl_master_rescan(
)
{
EC_MASTER_DBG(master, 1, "Got rescan command via ioctl()."
" Re-scanning on next possibility.\n");
" Re-scanning on next possibility.\n");
master->fsm.rescan_required = 1;
return 0;
}
@@ -896,8 +897,9 @@ static ATTRIBUTES int ec_ioctl_slave_sdo_download(
}
if (data.complete_access) {
retval = ecrt_master_sdo_download_complete(master, data.slave_position,
data.sdo_index, sdo_data, data.data_size, &data.abort_code);
retval = ecrt_master_sdo_download_complete(master,
data.slave_position, data.sdo_index, sdo_data, data.data_size,
&data.abort_code);
} else {
retval = ecrt_master_sdo_download(master, data.slave_position,
data.sdo_index, data.sdo_entry_subindex, sdo_data,
@@ -1262,6 +1264,8 @@ static ATTRIBUTES int ec_ioctl_config(
}
data.watchdog_divider = sc->watchdog_divider;
data.watchdog_intervals = sc->watchdog_intervals;
data.pdo_assign_mode = sc->pdo_assign_mode;
data.pdo_config_mode = sc->pdo_config_mode;
data.sdo_count = ec_slave_config_sdo_count(sc);
data.idn_count = ec_slave_config_idn_count(sc);
data.flag_count = ec_slave_config_flag_count(sc);
@@ -1716,6 +1720,7 @@ static ATTRIBUTES int ec_ioctl_eoe_handler(
/****************************************************************************/
#ifdef EC_EOE
/** Request EoE IP parameter setting.
*
* \return Zero on success, otherwise a negative error code.
@@ -1796,9 +1801,10 @@ static ATTRIBUTES int ec_ioctl_slave_eoe_ip_param(
return req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
#endif
/*****************************************************************************/
/****************************************************************************/
/** Request the master from userspace.
*
@@ -2505,6 +2511,51 @@ out_return:
/****************************************************************************/
/** Configure a slave's PDO handling mode.
*
* \return Zero on success, otherwise a negative error code.
*/
static ATTRIBUTES int ec_ioctl_sc_pdo_mode(
ec_master_t *master, /**< EtherCAT master. */
void *arg, /**< ioctl() argument. */
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
ec_ioctl_config_t data;
ec_slave_config_t *sc;
int ret = 0;
if (unlikely(!ctx->requested)) {
ret = -EPERM;
goto out_return;
}
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
ret = -EFAULT;
goto out_return;
}
if (down_interruptible(&master->master_sem)) {
ret = -EINTR;
goto out_return;
}
if (!(sc = ec_master_get_config(master, data.config_index))) {
ret = -ENOENT;
goto out_up;
}
ret = ecrt_slave_config_pdo_mode(sc,
data.pdo_assign_mode, data.pdo_config_mode);
out_up:
up(&master->master_sem);
out_return:
return ret;
}
/****************************************************************************/
/** Add a PDO to the assignment.
*
* \return Zero on success, otherwise a negative error code.
@@ -5453,6 +5504,13 @@ static long ec_ioctl_nrt
}
ret = ec_ioctl_sc_watchdog(master, arg, ctx);
break;
case EC_IOCTL_SC_PDO_MODE:
if (!ctx->writable) {
ret = -EPERM;
break;
}
ret = ec_ioctl_sc_pdo_mode(master, arg, ctx);
break;
case EC_IOCTL_SC_ADD_PDO:
if (!ctx->writable) {
ret = -EPERM;
+6 -3
View File
@@ -162,6 +162,7 @@
#define EC_IOCTL_VOE_DATA EC_IOWR(0x65, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x66, size_t)
#define EC_IOCTL_SII_CACHING EC_IOW(0x67, uint32_t)
#define EC_IOCTL_SC_PDO_MODE EC_IOW(0x68, ec_ioctl_config_t)
/****************************************************************************/
@@ -501,6 +502,8 @@ typedef struct {
} syncs[EC_MAX_SYNC_MANAGERS];
uint16_t watchdog_divider;
uint16_t watchdog_intervals;
ec_pdo_mode_t pdo_assign_mode;
ec_pdo_mode_t pdo_config_mode;
uint32_t sdo_count;
uint32_t idn_count;
uint32_t flag_count;
@@ -645,11 +648,11 @@ typedef struct {
struct in_addr dns;
char name[EC_MAX_HOSTNAME_SIZE];
// output
uint16_t result;
// output
uint16_t result;
} ec_ioctl_eoe_ip_t;
/*****************************************************************************/
/****************************************************************************/
typedef struct {
// outputs
+40
View File
@@ -1884,6 +1884,46 @@ const ec_slave_t *ec_master_find_slave_const(
EC_FIND_SLAVE;
}
/** Finds the slave configuration that will be attached to the given slave.
*
* Unlike ec_slave_config_attach(), this does not actually attach the
* configuration; it just looks one up by alias/position (and, if given,
* matching vendor ID/product code), which also works before the bus scan
* has completed and configurations have been attached to their slaves.
*
* \return The matching slave configuration, or \a NULL, if none matches.
*/
ec_slave_config_t *ec_master_find_config_for_slave(
ec_master_t *master, /**< EtherCAT master. */
const ec_slave_t *slave /**< Slave to find a configuration for. */
)
{
ec_slave_config_t *sc;
list_for_each_entry(sc, &master->configs, list) {
if (ec_master_find_slave(master, sc->alias, sc->position) != slave)
continue;
#ifdef EC_IDENT_WILDCARDS
if (sc->vendor_id != 0xffffffff
&& slave->sii.vendor_id != sc->vendor_id)
continue;
if (sc->product_code != 0xffffffff
&& slave->sii.product_code != sc->product_code)
continue;
#else
if (slave->sii.vendor_id != sc->vendor_id)
continue;
if (slave->sii.product_code != sc->product_code)
continue;
#endif
return sc;
}
return NULL;
}
/****************************************************************************/
/** Get the number of slave configurations provided by the application.
+5 -2
View File
@@ -202,7 +202,7 @@ struct ec_master {
#if EC_MAX_NUM_DEVICES > 1
unsigned int num_devices; /**< Number of devices. Access this always via
ec_master_num_devices(), because it may be
optimized! */
optimized. */
#endif
struct semaphore device_sem; /**< Device semaphore. */
ec_device_stats_t device_stats; /**< Device statistics. */
@@ -352,6 +352,8 @@ void ec_master_attach_slave_configs(ec_master_t *);
ec_slave_t *ec_master_find_slave(ec_master_t *, uint16_t, uint16_t);
const ec_slave_t *ec_master_find_slave_const(const ec_master_t *, uint16_t,
uint16_t);
ec_slave_config_t *ec_master_find_config_for_slave(ec_master_t *,
const ec_slave_t *);
void ec_master_output_stats(ec_master_t *);
#ifdef EC_EOE
void ec_master_clear_eoe_handlers(ec_master_t *);
@@ -369,7 +371,8 @@ const ec_domain_t *ec_master_find_domain_const(const ec_master_t *,
unsigned int);
#ifdef EC_EOE
uint16_t ec_master_eoe_handler_count(const ec_master_t *);
const ec_eoe_t *ec_master_get_eoe_handler_const(const ec_master_t *, uint16_t);
const ec_eoe_t *ec_master_get_eoe_handler_const(const ec_master_t *,
uint16_t);
#endif
int ec_master_debug_level(ec_master_t *, unsigned int);
+28
View File
@@ -89,6 +89,9 @@ void ec_slave_config_init(
sc->watchdog_divider = 0; // use default
sc->watchdog_intervals = 0; // use default
sc->pdo_assign_mode = EC_PDO_MODE_DEFAULT;
sc->pdo_config_mode = EC_PDO_MODE_DEFAULT;
sc->slave = NULL;
for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++)
@@ -716,6 +719,30 @@ int ecrt_slave_config_watchdog(ec_slave_config_t *sc,
/****************************************************************************/
int ecrt_slave_config_pdo_mode(ec_slave_config_t *sc,
ec_pdo_mode_t assign_mode, ec_pdo_mode_t config_mode)
{
EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, assign_mode = %u,"
" config_mode = %u)\n", __func__, sc, assign_mode, config_mode);
if (assign_mode > EC_PDO_MODE_WRITE_IF_DIFFERENT) {
EC_CONFIG_ERR(sc, "Invalid PDO assignment mode %u!\n", assign_mode);
return -EINVAL;
}
if (config_mode > EC_PDO_MODE_WRITE_IF_DIFFERENT) {
EC_CONFIG_ERR(sc, "Invalid PDO configuration mode %u!\n",
config_mode);
return -EINVAL;
}
sc->pdo_assign_mode = assign_mode;
sc->pdo_config_mode = config_mode;
return 0;
}
/****************************************************************************/
int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
uint8_t sync_index, uint16_t pdo_index)
{
@@ -1612,6 +1639,7 @@ int ecrt_slave_config_state_timeout(ec_slave_config_t *sc,
EXPORT_SYMBOL(ecrt_slave_config_sync_manager);
EXPORT_SYMBOL(ecrt_slave_config_watchdog);
EXPORT_SYMBOL(ecrt_slave_config_pdo_mode);
EXPORT_SYMBOL(ecrt_slave_config_pdo_assign_add);
EXPORT_SYMBOL(ecrt_slave_config_pdo_assign_clear);
EXPORT_SYMBOL(ecrt_slave_config_pdo_mapping_add);
+7
View File
@@ -123,6 +123,13 @@ struct ec_slave_config {
uint16_t watchdog_intervals; /**< Process data watchdog intervals (see
spec. reg. 0x0420). */
ec_pdo_mode_t pdo_assign_mode; /**< Whether/how to read resp. write the
PDO assignment via CoE. \see
ecrt_slave_config_pdo_mode(). */
ec_pdo_mode_t pdo_config_mode; /**< Whether/how to read resp. write the
PDO configuration via CoE. \see
ecrt_slave_config_pdo_mode(). */
ec_slave_t *slave; /**< Slave pointer. This is \a NULL, if the slave is
offline. */
+20
View File
@@ -46,6 +46,21 @@ using std::left;
/****************************************************************************/
/** Returns a human-readable string for a PDO handling mode.
*/
static string pdoModeString(ec_pdo_mode_t mode)
{
switch (mode) {
case EC_PDO_MODE_FIXED: return "Fixed";
case EC_PDO_MODE_WRITE: return "Write";
case EC_PDO_MODE_READ_WRITE: return "Read+Write";
case EC_PDO_MODE_WRITE_IF_DIFFERENT: return "Write if different";
default: return "???";
}
}
/****************************************************************************/
CommandConfig::CommandConfig():
Command("config", "Show slave configurations.")
{
@@ -205,6 +220,11 @@ void CommandConfig::showDetailedConfigs(
}
cout << endl;
cout << indent << "PDO assignment mode: "
<< pdoModeString(configIter->pdo_assign_mode) << endl
<< indent << "PDO configuration mode: "
<< pdoModeString(configIter->pdo_config_mode) << endl;
for (j = 0; j < EC_MAX_SYNC_MANAGERS; j++) {
if (configIter->syncs[j].pdo_count) {
cout << indent << "SM" << dec << j << ", Dir: "