Added ecrt_master_link_state() to retrieve information about a redundant link.

This commit is contained in:
Florian Pose 2012-05-31 11:03:58 +02:00
parent dee3c96444
commit 6c9e725c29
5 changed files with 168 additions and 41 deletions

View File

@ -42,6 +42,8 @@
* Changed since 1.5:
*
* - Added redundancy_active flag to ec_domain_state_t.
* - Added ecrt_master_link_state() method and ec_master_link_state_t to query
* the state of a redundant link.
*
* Changes in version 1.5:
*
@ -200,6 +202,30 @@ typedef struct {
/*****************************************************************************/
/** Redundant link state.
*
* This is used for the output parameter of ecrt_master_link_state().
*
* \see ecrt_master_link_state().
*/
typedef struct {
unsigned int slaves_responding; /**< Sum of responding slaves on the given
link. */
unsigned int al_states : 4; /**< Application-layer states of the slaves on
the given link. The states are coded in the
lower 4 bits. If a bit is set, it means
that at least one slave in the bus is in the
corresponding state:
- Bit 0: \a INIT
- Bit 1: \a PREOP
- Bit 2: \a SAFEOP
- Bit 3: \a OP */
unsigned int link_up : 1; /**< \a true, if the given Ethernet link is up.
*/
} ec_master_link_state_t;
/*****************************************************************************/
/** Slave configuration state.
*
* This is used as an output parameter of ecrt_slave_config_state().
@ -855,12 +881,29 @@ void ecrt_master_send_ext(
/** Reads the current master state.
*
* Stores the master state information in the given \a state structure.
*
* This method returns a global state. For the link-specific states in a
* redundant bus topology, use the ecrt_master_link_state() method.
*/
void ecrt_master_state(
const ec_master_t *master, /**< EtherCAT master. */
ec_master_state_t *state /**< Structure to store the information. */
);
/** Reads the current state of a redundant link.
*
* Stores the link state information in the given \a state structure.
*
* \return Zero on success, otherwise negative error code.
*/
int ecrt_master_link_state(
const ec_master_t *master, /**< EtherCAT master. */
unsigned int dev_idx, /**< Index of the device (0 = main device, 1 =
first backup device, ...). */
ec_master_link_state_t *state /**< Structure to store the information.
*/
);
/** Sets the application time.
*
* The master has to know the application's time when operating slaves with

View File

@ -235,11 +235,14 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
for ( i = 0; i < EC_MAX_PORTS; i++ ) {
slave_info->ports[i].desc = data.ports[i].desc;
slave_info->ports[i].link.link_up = data.ports[i].link.link_up;
slave_info->ports[i].link.loop_closed = data.ports[i].link.loop_closed;
slave_info->ports[i].link.signal_detected = data.ports[i].link.signal_detected;
slave_info->ports[i].link.loop_closed =
data.ports[i].link.loop_closed;
slave_info->ports[i].link.signal_detected =
data.ports[i].link.signal_detected;
slave_info->ports[i].receive_time = data.ports[i].receive_time;
slave_info->ports[i].next_slave = data.ports[i].next_slave;
slave_info->ports[i].delay_to_next_dc = data.ports[i].delay_to_next_dc;
slave_info->ports[i].delay_to_next_dc =
data.ports[i].delay_to_next_dc;
}
slave_info->al_state = data.al_state;
slave_info->error_flag = data.error_flag;
@ -256,8 +259,9 @@ int ecrt_master_get_sync_manager(ec_master_t *master, uint16_t slave_position,
{
ec_ioctl_slave_sync_t data;
if (sync_index >= EC_MAX_SYNC_MANAGERS)
if (sync_index >= EC_MAX_SYNC_MANAGERS) {
return -ENOENT;
}
memset(&data, 0x00, sizeof(ec_ioctl_slave_sync_t));
data.slave_position = slave_position;
@ -552,6 +556,21 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
/*****************************************************************************/
int ecrt_master_link_state(const ec_master_t *master, unsigned int dev_idx,
ec_master_link_state_t *state)
{
ec_ioctl_link_state_t io;
io.dev_idx = dev_idx;
io.state = state;
if (ioctl(master->fd, EC_IOCTL_MASTER_LINK_STATE, &io) == -1) {
fprintf(stderr, "Failed to get link state: %s\n", strerror(errno));
return -errno;
}
}
/*****************************************************************************/
void ecrt_master_application_time(ec_master_t *master, uint64_t app_time)
{
ec_ioctl_app_time_t data;

View File

@ -1827,6 +1827,40 @@ int ec_cdev_ioctl_master_state(
/*****************************************************************************/
/** Get the master state.
*/
int ec_cdev_ioctl_master_link_state(
ec_master_t *master, /**< EtherCAT master. */
unsigned long arg, /**< ioctl() argument. */
ec_cdev_priv_t *priv /**< Private data structure of file handle. */
)
{
ec_ioctl_link_state_t ioctl;
ec_master_link_state_t state;
int ret;
if (unlikely(!priv->requested)) {
return -EPERM;
}
if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
return -EFAULT;
}
ret = ecrt_master_link_state(master, ioctl.dev_idx, &state);
if (ret < 0) {
return ret;
}
if (copy_to_user((void __user *) ioctl.state, &state, sizeof(state))) {
return -EFAULT;
}
return 0;
}
/*****************************************************************************/
/** Get the master state.
*/
int ec_cdev_ioctl_app_time(
@ -3629,6 +3663,9 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case EC_IOCTL_MASTER_STATE:
ret = ec_cdev_ioctl_master_state(master, arg, priv);
break;
case EC_IOCTL_MASTER_LINK_STATE:
ret = ec_cdev_ioctl_master_link_state(master, arg, priv);
break;
case EC_IOCTL_APP_TIME:
if (!(filp->f_mode & FMODE_WRITE)) {
ret = -EPERM;

View File

@ -56,7 +56,7 @@
*
* Increment this when changing the ioctl interface!
*/
#define EC_IOCTL_VERSION_MAGIC 17
#define EC_IOCTL_VERSION_MAGIC 18
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@ -101,42 +101,43 @@
#define EC_IOCTL_SEND EC_IO(0x23)
#define EC_IOCTL_RECEIVE EC_IO(0x24)
#define EC_IOCTL_MASTER_STATE EC_IOR(0x25, ec_master_state_t)
#define EC_IOCTL_APP_TIME EC_IOW(0x26, ec_ioctl_app_time_t)
#define EC_IOCTL_SYNC_REF EC_IO(0x27)
#define EC_IOCTL_SYNC_SLAVES EC_IO(0x28)
#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x29)
#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x2a, uint32_t)
#define EC_IOCTL_RESET EC_IO(0x2b)
#define EC_IOCTL_SC_SYNC EC_IOW(0x2c, ec_ioctl_config_t)
#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x2d, ec_ioctl_config_t)
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x2e, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x2f, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x30, ec_ioctl_add_pdo_entry_t)
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x31, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x32, ec_ioctl_reg_pdo_entry_t)
#define EC_IOCTL_SC_DC EC_IOW(0x33, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x34, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x35, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x36, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x37, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x38, ec_ioctl_sc_idn_t)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x39)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3a)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x3b)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x3c, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x3d, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x3e, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x3f, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x40, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x41, ec_ioctl_sdo_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x42, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x43, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x44, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x45, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x46, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x47, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x48, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x49, size_t)
#define EC_IOCTL_MASTER_LINK_STATE EC_IOWR(0x26, ec_ioctl_link_state_t)
#define EC_IOCTL_APP_TIME EC_IOW(0x27, ec_ioctl_app_time_t)
#define EC_IOCTL_SYNC_REF EC_IO(0x28)
#define EC_IOCTL_SYNC_SLAVES EC_IO(0x29)
#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x2a)
#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x2b, uint32_t)
#define EC_IOCTL_RESET EC_IO(0x2c)
#define EC_IOCTL_SC_SYNC EC_IOW(0x2d, ec_ioctl_config_t)
#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x2e, ec_ioctl_config_t)
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x2f, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x20, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x31, ec_ioctl_add_pdo_entry_t)
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x32, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x33, ec_ioctl_reg_pdo_entry_t)
#define EC_IOCTL_SC_DC EC_IOW(0x34, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x35, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x36, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x37, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x38, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x39, ec_ioctl_sc_idn_t)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x3a)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3b)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x3c)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x3d, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x3e, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x3f, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x30, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x41, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x42, ec_ioctl_sdo_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x43, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x44, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x45, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x46, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x47, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x48, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x49, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x4a, size_t)
/*****************************************************************************/
@ -671,6 +672,16 @@ typedef struct {
/*****************************************************************************/
typedef struct {
// inputs
uint32_t dev_idx;
// outputs
ec_master_link_state_t *state;
} ec_ioctl_link_state_t;
/*****************************************************************************/
typedef struct {
// inputs
uint64_t app_time;

View File

@ -2507,6 +2507,22 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
/*****************************************************************************/
int ecrt_master_link_state(const ec_master_t *master, unsigned int dev_idx,
ec_master_link_state_t *state)
{
if (dev_idx >= EC_NUM_DEVICES) {
return -EINVAL;
}
state->slaves_responding = master->fsm.slaves_responding[dev_idx];
state->al_states = master->fsm.slave_states[dev_idx];
state->link_up = master->devices[dev_idx].link_state;
return 0;
}
/*****************************************************************************/
void ecrt_master_application_time(ec_master_t *master, uint64_t app_time)
{
master->app_time = app_time;
@ -2980,6 +2996,7 @@ EXPORT_SYMBOL(ecrt_master);
EXPORT_SYMBOL(ecrt_master_get_slave);
EXPORT_SYMBOL(ecrt_master_slave_config);
EXPORT_SYMBOL(ecrt_master_state);
EXPORT_SYMBOL(ecrt_master_link_state);
EXPORT_SYMBOL(ecrt_master_application_time);
EXPORT_SYMBOL(ecrt_master_sync_reference_clock);
EXPORT_SYMBOL(ecrt_master_sync_slave_clocks);