Added ecrt_master_link_state() to retrieve information about a redundant link.
This commit is contained in:
parent
dee3c96444
commit
6c9e725c29
|
|
@ -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
|
||||
|
|
|
|||
27
lib/master.c
27
lib/master.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue