mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-02-06 03:41:52 +08:00
Added watchdog configuration via application interface (thanks to J. Mohre).
This commit is contained in:
1
NEWS
1
NEWS
@@ -11,6 +11,7 @@ Changes since 1.4.0:
|
||||
* Added a userspace library for accessing the application interface. This
|
||||
library is licensed under LGPLv2.
|
||||
* Added distributed clocks support.
|
||||
* Added watchdog configuration via application interface (thanks to J. Mohre).
|
||||
* Added VoE mailbox protocol support.
|
||||
* Improved the callback mechanism. ecrt_master_callbacks() now takes two
|
||||
callback functions for sending and receiving datagrams.
|
||||
|
||||
1
TODO
1
TODO
@@ -43,7 +43,6 @@ Version 1.5.0:
|
||||
* Check for ioctl() interface version.
|
||||
* Improve application-triggered SDO transfers by moving the state machine into
|
||||
the SDO handlers.
|
||||
* Apply watchdog patches from J. Mohre.
|
||||
* Move device driver files in subdirectories.
|
||||
* Document ec_fsm_foe members.
|
||||
* Test KBUILD_EXTRA_SYMBOLS.
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
* callback functions for sending and receiving datagrams.
|
||||
* ecrt_master_send_ext() is used to execute the sending of non-application
|
||||
* datagrams.
|
||||
* - Added watchdog configuration (method ecrt_slave_config_watchdog(),
|
||||
* #ec_watchdog_mode_t, \a watchdog_mode parameter in ec_sync_info_t and
|
||||
* ecrt_slave_config_sync_manager()).
|
||||
* - Added ecrt_open_master() and ecrt_master_reserve() separation for
|
||||
* userspace.
|
||||
* - Added ecrt_master() userspace interface, to get information about a
|
||||
@@ -61,7 +64,7 @@
|
||||
* ecrt_slave_config_reg_pdo_entry() and ecrt_slave_config_sdo*().
|
||||
* - Imlemented the Vendor-specific over EtherCAT mailbox protocol. See
|
||||
* ecrt_slave_config_create_voe_handler().
|
||||
* - Renamed ec_sdo_request_state_t to ec_request_state_t, because it is also
|
||||
* - Renamed ec_sdo_request_state_t to #ec_request_state_t, because it is also
|
||||
* used by VoE handlers.
|
||||
* - Removed 'const' from argument of ecrt_sdo_request_state(), because the
|
||||
* userspace library has to modify object internals.
|
||||
@@ -275,6 +278,18 @@ typedef enum {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Watchdog mode for sync manager configuration.
|
||||
*
|
||||
* Used to specify, if a sync manager's watchdog is to be enabled.
|
||||
*/
|
||||
typedef enum {
|
||||
EC_WD_DEFAULT, /**< Use the default setting of the sync manager. */
|
||||
EC_WD_ENABLE, /**< Enable the watchdog. */
|
||||
EC_WD_DISABLE, /**< Disable the watchdog. */
|
||||
} ec_watchdog_mode_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** PDO entry configuration information.
|
||||
*
|
||||
* This is the data type of the \a entries field in ec_pdo_info_t.
|
||||
@@ -322,6 +337,7 @@ typedef struct {
|
||||
unsigned int 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_watchdog_mode_t watchdog_mode; /**< Watchdog mode. */
|
||||
} ec_sync_info_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -709,7 +725,18 @@ int ecrt_slave_config_sync_manager(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
uint8_t sync_index, /**< Sync manager index. Must be less
|
||||
than #EC_MAX_SYNC_MANAGERS. */
|
||||
ec_direction_t dir /**< Input/Output. */
|
||||
ec_direction_t direction, /**< Input/Output. */
|
||||
ec_watchdog_mode_t watchdog_mode /** Watchdog mode. */
|
||||
);
|
||||
|
||||
/** Configure a slave's watchdog times.
|
||||
*/
|
||||
void ecrt_slave_config_watchdog(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
uint16_t watchdog_divider, /**< Number of 40 ns intervals. Used as a
|
||||
base unit for all slave watchdogs. */
|
||||
uint16_t watchdog_intervals /**< Number of base intervals for process
|
||||
data watchdog. */
|
||||
);
|
||||
|
||||
/** Add a PDO to a sync manager's PDO assignment.
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
|
||||
ec_direction_t dir)
|
||||
ec_direction_t dir, ec_watchdog_mode_t watchdog_mode)
|
||||
{
|
||||
ec_ioctl_config_t data;
|
||||
unsigned int i;
|
||||
@@ -55,6 +55,8 @@ int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
|
||||
memset(&data, 0x00, sizeof(ec_ioctl_config_t));
|
||||
data.config_index = sc->index;
|
||||
data.syncs[sync_index].dir = dir;
|
||||
data.syncs[sync_index].watchdog_mode = watchdog_mode;
|
||||
data.syncs[sync_index].config_this = 1;
|
||||
|
||||
if (ioctl(sc->master->fd, EC_IOCTL_SC_SYNC, &data) == -1) {
|
||||
fprintf(stderr, "Failed to config sync manager: %s\n",
|
||||
@@ -67,6 +69,24 @@ int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_watchdog(ec_slave_config_t *sc,
|
||||
uint16_t divider, uint16_t intervals)
|
||||
{
|
||||
ec_ioctl_config_t data;
|
||||
|
||||
memset(&data, 0x00, sizeof(ec_ioctl_config_t));
|
||||
data.config_index = sc->index;
|
||||
data.watchdog_divider = divider;
|
||||
data.watchdog_intervals = intervals;
|
||||
|
||||
if (ioctl(sc->master->fd, EC_IOCTL_SC_WATCHDOG, &data) == -1) {
|
||||
fprintf(stderr, "Failed to config watchdog: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
||||
uint8_t sync_index, uint16_t pdo_index)
|
||||
{
|
||||
@@ -166,8 +186,8 @@ int ecrt_slave_config_pdos(ec_slave_config_t *sc,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = ecrt_slave_config_sync_manager(
|
||||
sc, sync_info->index, sync_info->dir);
|
||||
ret = ecrt_slave_config_sync_manager(sc, sync_info->index,
|
||||
sync_info->dir, sync_info->watchdog_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -1759,7 +1759,7 @@ int ec_cdev_ioctl_sync_slaves(
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Set the direction of a sync manager.
|
||||
/** Configure a sync manager.
|
||||
*/
|
||||
int ec_cdev_ioctl_sc_sync(
|
||||
ec_master_t *master, /**< EtherCAT master. */
|
||||
@@ -1793,9 +1793,9 @@ int ec_cdev_ioctl_sc_sync(
|
||||
}
|
||||
|
||||
for (i = 0; i < EC_MAX_SYNC_MANAGERS; i++) {
|
||||
ec_direction_t dir = data.syncs[i].dir;
|
||||
if (dir == EC_DIR_INPUT || dir == EC_DIR_OUTPUT) {
|
||||
if (ecrt_slave_config_sync_manager(sc, i, dir)) {
|
||||
if (data.syncs[i].config_this) {
|
||||
if (ecrt_slave_config_sync_manager(sc, i, data.syncs[i].dir,
|
||||
data.syncs[i].watchdog_mode)) {
|
||||
ret = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
@@ -1810,6 +1810,49 @@ out_return:
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Configure a slave's watchdogs.
|
||||
*/
|
||||
int ec_cdev_ioctl_sc_watchdog(
|
||||
ec_master_t *master, /**< EtherCAT master. */
|
||||
unsigned long arg, /**< ioctl() argument. */
|
||||
ec_cdev_priv_t *priv /**< Private data structure of file handle. */
|
||||
)
|
||||
{
|
||||
ec_ioctl_config_t data;
|
||||
ec_slave_config_t *sc;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(!priv->requested)) {
|
||||
ret = -EPERM;
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
|
||||
ret = -EFAULT;
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
if (down_interruptible(&master->master_sem)) {
|
||||
ret = -EINTR;
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
if (!(sc = ec_master_get_config(master, data.config_index))) {
|
||||
ret = -ENOENT;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
ecrt_slave_config_watchdog(sc,
|
||||
data.watchdog_divider, data.watchdog_intervals);
|
||||
|
||||
out_up:
|
||||
up(&master->master_sem);
|
||||
out_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Add a PDO to the assignment.
|
||||
*/
|
||||
int ec_cdev_ioctl_sc_add_pdo(
|
||||
@@ -3229,6 +3272,10 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
return -EPERM;
|
||||
return ec_cdev_ioctl_sc_sync(master, arg, priv);
|
||||
case EC_IOCTL_SC_WATCHDOG:
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
return -EPERM;
|
||||
return ec_cdev_ioctl_sc_watchdog(master, arg, priv);
|
||||
case EC_IOCTL_SC_ADD_PDO:
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
return -EPERM;
|
||||
|
||||
@@ -54,6 +54,8 @@ void ec_fsm_slave_config_state_dc_write_offset(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_state_mbox_sync(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_state_boot_preop(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_state_watchdog_divider(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_state_watchdog(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_state_fmmu(ec_fsm_slave_config_t *);
|
||||
@@ -70,6 +72,8 @@ void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_enter_boot_preop(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_enter_pdo_conf(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_enter_watchdog_divider(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_enter_watchdog(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_enter_pdo_sync(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_enter_fmmu(ec_fsm_slave_config_t *);
|
||||
void ec_fsm_slave_config_enter_dc_cycle(ec_fsm_slave_config_t *);
|
||||
@@ -558,7 +562,7 @@ void ec_fsm_slave_config_enter_mbox_sync(
|
||||
for (i = 0; i < 2; i++) {
|
||||
ec_sync_page(&slave->sii.syncs[i], i,
|
||||
slave->sii.syncs[i].default_length,
|
||||
EC_DIR_INVALID, // use default direction
|
||||
NULL, // use default sync manager configuration
|
||||
datagram->data + EC_SYNC_PAGE_SIZE * i);
|
||||
}
|
||||
|
||||
@@ -587,7 +591,7 @@ void ec_fsm_slave_config_enter_mbox_sync(
|
||||
sync.control_register = 0x26;
|
||||
sync.enable = 1;
|
||||
ec_sync_page(&sync, 0, slave->sii.std_rx_mailbox_size,
|
||||
EC_DIR_INVALID, // use default direction
|
||||
NULL, // use default sync manager configuration
|
||||
datagram->data);
|
||||
slave->configured_rx_mailbox_offset =
|
||||
slave->sii.std_rx_mailbox_offset;
|
||||
@@ -599,7 +603,7 @@ void ec_fsm_slave_config_enter_mbox_sync(
|
||||
sync.control_register = 0x22;
|
||||
sync.enable = 1;
|
||||
ec_sync_page(&sync, 1, slave->sii.std_tx_mailbox_size,
|
||||
EC_DIR_INVALID, // use default direction
|
||||
NULL, // use default sync manager configuration
|
||||
datagram->data + EC_SYNC_PAGE_SIZE);
|
||||
slave->configured_tx_mailbox_offset =
|
||||
slave->sii.std_tx_mailbox_offset;
|
||||
@@ -844,6 +848,125 @@ void ec_fsm_slave_config_state_pdo_conf(
|
||||
fsm->slave->ring_position);
|
||||
}
|
||||
|
||||
ec_fsm_slave_config_enter_watchdog_divider(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** WATCHDOG_DIVIDER entry function.
|
||||
*/
|
||||
void ec_fsm_slave_config_enter_watchdog_divider(
|
||||
ec_fsm_slave_config_t *fsm /**< slave state machine */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_master_t *master = slave->master;
|
||||
ec_slave_config_t *config = slave->config;
|
||||
|
||||
if (config && config->watchdog_divider) {
|
||||
if (master->debug_level)
|
||||
EC_DBG("Setting watchdog divider to %u.\n",
|
||||
config->watchdog_divider);
|
||||
|
||||
ec_datagram_fpwr(datagram, slave->station_address, 0x0400, 2);
|
||||
EC_WRITE_U16(datagram->data, config->watchdog_divider);
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_slave_config_state_watchdog_divider;
|
||||
} else {
|
||||
ec_fsm_slave_config_enter_watchdog(fsm);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Slave configuration state: WATCHDOG_DIVIDER.
|
||||
*/
|
||||
void ec_fsm_slave_config_state_watchdog_divider(
|
||||
ec_fsm_slave_config_t *fsm /**< slave state machine */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
return;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
fsm->state = ec_fsm_slave_config_state_error;
|
||||
EC_ERR("Failed to receive watchdog divider configuration datagram for"
|
||||
" slave %u (datagram state %u).\n",
|
||||
slave->ring_position, datagram->state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
slave->error_flag = 1;
|
||||
EC_WARN("Failed to set watchdog divider of slave %u: ",
|
||||
slave->ring_position);
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
ec_fsm_slave_config_enter_watchdog(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** WATCHDOG entry function
|
||||
*/
|
||||
void ec_fsm_slave_config_enter_watchdog(
|
||||
ec_fsm_slave_config_t *fsm /**< slave state machine */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
ec_slave_config_t *config = slave->config;
|
||||
|
||||
if (config && config->watchdog_intervals) {
|
||||
if (slave->master->debug_level)
|
||||
EC_DBG("Setting process data watchdog intervals to %u.\n",
|
||||
config->watchdog_intervals);
|
||||
|
||||
ec_datagram_fpwr(datagram, slave->station_address, 0x0420, 2);
|
||||
EC_WRITE_U16(datagram->data, config->watchdog_intervals);
|
||||
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
fsm->state = ec_fsm_slave_config_state_watchdog;
|
||||
}
|
||||
|
||||
ec_fsm_slave_config_enter_pdo_sync(fsm);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Slave configuration state: WATCHDOG.
|
||||
*/
|
||||
|
||||
void ec_fsm_slave_config_state_watchdog(
|
||||
ec_fsm_slave_config_t *fsm /**< slave state machine */
|
||||
)
|
||||
{
|
||||
ec_datagram_t *datagram = fsm->datagram;
|
||||
ec_slave_t *slave = fsm->slave;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
|
||||
return;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
fsm->state = ec_fsm_slave_config_state_error;
|
||||
EC_ERR("Failed to receive sync manager watchdog configuration "
|
||||
"datagram for slave %u (datagram state %u).\n",
|
||||
slave->ring_position, datagram->state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
EC_WARN("Failed to set process data watchdog intervals of slave %u: ",
|
||||
slave->ring_position);
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
}
|
||||
|
||||
ec_fsm_slave_config_enter_pdo_sync(fsm);
|
||||
}
|
||||
|
||||
@@ -861,7 +984,6 @@ void ec_fsm_slave_config_enter_pdo_sync(
|
||||
uint8_t sync_index;
|
||||
const ec_sync_t *sync;
|
||||
uint16_t size;
|
||||
ec_direction_t dir;
|
||||
|
||||
if (slave->sii.mailbox_protocols) {
|
||||
offset = 2; // slave has mailboxes
|
||||
@@ -884,21 +1006,20 @@ void ec_fsm_slave_config_enter_pdo_sync(
|
||||
ec_datagram_zero(datagram);
|
||||
|
||||
for (i = 0; i < num_pdo_syncs; i++) {
|
||||
const ec_sync_config_t *sync_config;
|
||||
sync_index = i + offset;
|
||||
sync = &slave->sii.syncs[sync_index];
|
||||
|
||||
if (slave->config) {
|
||||
const ec_sync_config_t *sync_config;
|
||||
sync_config = &slave->config->sync_configs[sync_index];
|
||||
size = ec_pdo_list_total_size(&sync_config->pdos);
|
||||
dir = sync_config->dir;
|
||||
} else {
|
||||
sync_config = NULL;
|
||||
size = sync->default_length;
|
||||
dir = EC_DIR_INVALID;
|
||||
}
|
||||
|
||||
ec_sync_page(sync, sync_index, size, dir, datagram->data +
|
||||
EC_SYNC_PAGE_SIZE * i);
|
||||
ec_sync_page(sync, sync_index, size, sync_config,
|
||||
datagram->data + EC_SYNC_PAGE_SIZE * i);
|
||||
}
|
||||
|
||||
fsm->retries = EC_FSM_RETRIES;
|
||||
|
||||
@@ -91,32 +91,33 @@
|
||||
#define EC_IOCTL_SYNC_REF EC_IO(0x21)
|
||||
#define EC_IOCTL_SYNC_SLAVES EC_IO(0x22)
|
||||
#define EC_IOCTL_SC_SYNC EC_IOW(0x23, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x24, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x25, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x26, ec_ioctl_add_pdo_entry_t)
|
||||
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x27, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x28, ec_ioctl_reg_pdo_entry_t)
|
||||
#define EC_IOCTL_SC_DC EC_IOW(0x29, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_SC_SDO EC_IOW(0x2a, ec_ioctl_sc_sdo_t)
|
||||
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x2b, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SC_VOE EC_IOWR(0x2c, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_SC_STATE EC_IOWR(0x2d, ec_ioctl_sc_state_t)
|
||||
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x2e)
|
||||
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x2f)
|
||||
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x30)
|
||||
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x31, ec_ioctl_domain_state_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x32, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x33, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x34, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x35, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x36, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x37, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x38, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ EC_IOW(0x39, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x3a, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x3b, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x3c, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_DATA EC_IOWR(0x3d, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x24, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x25, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x26, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x27, ec_ioctl_add_pdo_entry_t)
|
||||
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x28, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x29, ec_ioctl_reg_pdo_entry_t)
|
||||
#define EC_IOCTL_SC_DC EC_IOW(0x2a, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_SC_SDO EC_IOW(0x2b, ec_ioctl_sc_sdo_t)
|
||||
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x2c, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SC_VOE EC_IOWR(0x2d, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_SC_STATE EC_IOWR(0x2e, ec_ioctl_sc_state_t)
|
||||
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x2f)
|
||||
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x20)
|
||||
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x31)
|
||||
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x32, ec_ioctl_domain_state_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x33, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x34, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x35, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x36, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x37, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x38, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x39, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ EC_IOW(0x3a, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x3b, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x3c, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x3d, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_DATA EC_IOWR(0x3e, ec_ioctl_voe_t)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -389,8 +390,12 @@ typedef struct {
|
||||
uint32_t product_code;
|
||||
struct {
|
||||
ec_direction_t dir;
|
||||
ec_watchdog_mode_t watchdog_mode;
|
||||
uint32_t pdo_count;
|
||||
uint8_t config_this;
|
||||
} syncs[EC_MAX_SYNC_MANAGERS];
|
||||
uint16_t watchdog_divider;
|
||||
uint16_t watchdog_intervals;
|
||||
uint32_t sdo_count;
|
||||
int32_t slave_position;
|
||||
uint16_t dc_assign_activate;
|
||||
|
||||
@@ -66,6 +66,8 @@ void ec_slave_config_init(
|
||||
sc->position = position;
|
||||
sc->vendor_id = vendor_id;
|
||||
sc->product_code = product_code;
|
||||
sc->watchdog_divider = 0; // use default
|
||||
sc->watchdog_intervals = 0; // use default
|
||||
|
||||
sc->slave = NULL;
|
||||
|
||||
@@ -411,13 +413,14 @@ ec_voe_handler_t *ec_slave_config_find_voe_handler(
|
||||
*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
|
||||
ec_direction_t dir)
|
||||
ec_direction_t dir, ec_watchdog_mode_t watchdog_mode)
|
||||
{
|
||||
ec_sync_config_t *sync_config;
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("ecrt_slave_config_sync_manager(sc = 0x%x, sync_index = %u, "
|
||||
"dir = %u)\n", (u32) sc, sync_index, dir);
|
||||
"dir = %i, watchdog_mode = %i)\n",
|
||||
(u32) sc, sync_index, dir, watchdog_mode);
|
||||
|
||||
if (sync_index >= EC_MAX_SYNC_MANAGERS) {
|
||||
EC_ERR("Invalid sync manager index %u!\n", sync_index);
|
||||
@@ -431,11 +434,25 @@ int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
|
||||
|
||||
sync_config = &sc->sync_configs[sync_index];
|
||||
sync_config->dir = dir;
|
||||
sync_config->watchdog_mode = watchdog_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_slave_config_watchdog(ec_slave_config_t *sc,
|
||||
uint16_t divider, uint16_t intervals)
|
||||
{
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("%s(sc = 0x%x, divider = %u, intervals = %u)\n",
|
||||
__func__, (u32) sc, divider, intervals);
|
||||
|
||||
sc->watchdog_divider = divider;
|
||||
sc->watchdog_intervals = intervals;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
||||
uint8_t sync_index, uint16_t pdo_index)
|
||||
{
|
||||
@@ -579,8 +596,8 @@ int ecrt_slave_config_pdos(ec_slave_config_t *sc,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = ecrt_slave_config_sync_manager(
|
||||
sc, sync_info->index, sync_info->dir);
|
||||
ret = ecrt_slave_config_sync_manager(sc, sync_info->index,
|
||||
sync_info->dir, sync_info->watchdog_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -894,6 +911,7 @@ void ecrt_slave_config_state(const ec_slave_config_t *sc,
|
||||
/** \cond */
|
||||
|
||||
EXPORT_SYMBOL(ecrt_slave_config_sync_manager);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_watchdog);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_pdo_assign_add);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_pdo_assign_clear);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_pdo_mapping_add);
|
||||
|
||||
@@ -58,6 +58,11 @@ struct ec_slave_config {
|
||||
uint32_t vendor_id; /**< Slave vendor ID. */
|
||||
uint32_t product_code; /**< Slave product code. */
|
||||
|
||||
uint16_t watchdog_divider; /**< Watchdog divider as a number of 40ns
|
||||
intervals (see spec. reg. 0x0400). */
|
||||
uint16_t watchdog_intervals; /**< Process data watchdog intervals (see
|
||||
spec. reg. 0x0420). */
|
||||
|
||||
ec_slave_t *slave; /**< Slave pointer. This is \a NULL, if the slave is
|
||||
offline. */
|
||||
|
||||
|
||||
@@ -95,8 +95,7 @@ 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). */
|
||||
const ec_sync_config_t *sync_config, /**< Configuration. */
|
||||
uint8_t *data /**> Configuration memory. */
|
||||
)
|
||||
{
|
||||
@@ -104,10 +103,28 @@ void ec_sync_page(
|
||||
uint16_t enable = sync->enable && data_size;
|
||||
uint8_t control = sync->control_register;
|
||||
|
||||
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_config) {
|
||||
|
||||
switch (sync_config->dir) {
|
||||
case EC_DIR_OUTPUT:
|
||||
case EC_DIR_INPUT:
|
||||
EC_WRITE_BIT(&control, 2,
|
||||
sync_config->dir == EC_DIR_OUTPUT ? 1 : 0);
|
||||
EC_WRITE_BIT(&control, 3, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (sync_config->watchdog_mode) {
|
||||
case EC_WD_ENABLE:
|
||||
case EC_WD_DISABLE:
|
||||
EC_WRITE_BIT(&control, 6,
|
||||
sync_config->watchdog_mode == EC_WD_ENABLE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sync->slave->master->debug_level)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "pdo_list.h"
|
||||
#include "sync_config.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -57,8 +58,8 @@ typedef struct {
|
||||
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_page(const ec_sync_t *, uint8_t, uint16_t, ec_direction_t,
|
||||
uint8_t *);
|
||||
void ec_sync_page(const ec_sync_t *, uint8_t, uint16_t,
|
||||
const ec_sync_config_t *, uint8_t *);
|
||||
int ec_sync_add_pdo(ec_sync_t *, const ec_pdo_t *);
|
||||
ec_direction_t ec_sync_default_direction(const ec_sync_t *);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ void ec_sync_config_init(
|
||||
)
|
||||
{
|
||||
sync_config->dir = EC_DIR_INVALID;
|
||||
sync_config->watchdog_mode = EC_WD_DEFAULT;
|
||||
ec_pdo_list_init(&sync_config->pdos);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
*/
|
||||
typedef struct {
|
||||
ec_direction_t dir; /**< Sync manager direction. */
|
||||
ec_watchdog_mode_t watchdog_mode; /**< Watchdog mode. */
|
||||
ec_pdo_list_t pdos; /**< Current PDO assignment. */
|
||||
} ec_sync_config_t;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user