Included ecrt_voe_handler_read_nosync()-Patch by Mathias Weber.
This commit is contained in:
parent
8d46a283f6
commit
fae8df09b0
|
|
@ -1049,6 +1049,25 @@ void ecrt_voe_handler_read(
|
|||
ec_voe_handler_t *voe /**< VoE handler. */
|
||||
);
|
||||
|
||||
/** Start a VoE read operation without querying the sync manager status.
|
||||
*
|
||||
* After this function has been called, the ecrt_voe_handler_execute() method
|
||||
* must be called in every bus cycle as long as it returns EC_REQUEST_BUSY. No
|
||||
* other operation may be started while the handler is busy.
|
||||
*
|
||||
* The state machine queries the slave by sending an empty mailbox. The slave
|
||||
* fills its data to the master in this mailbox. If no data appear within the
|
||||
* EC_VOE_RESPONSE_TIMEOUT (defined in master/voe_handler.c), the operation
|
||||
* fails.
|
||||
*
|
||||
* On success, the size of the read data can be determined via
|
||||
* ecrt_voe_handler_data_size(), while the VoE header of the received data
|
||||
* can be retrieved with ecrt_voe_handler_received_header().
|
||||
*/
|
||||
void ecrt_voe_handler_read_nosync(
|
||||
ec_voe_handler_t *voe /**< VoE handler. */
|
||||
);
|
||||
|
||||
/** Execute the handler.
|
||||
*
|
||||
* This method executes the VoE handler. It has to be called in every bus cycle
|
||||
|
|
|
|||
|
|
@ -111,6 +111,20 @@ void ecrt_voe_handler_read(ec_voe_handler_t *voe)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_read_nosync(ec_voe_handler_t *voe)
|
||||
{
|
||||
ec_ioctl_voe_t data;
|
||||
|
||||
data.config_index = voe->config->index;
|
||||
data.voe_index = voe->index;
|
||||
|
||||
if (ioctl(voe->config->master->fd, EC_IOCTL_VOE_READ_NOSYNC, &data) == -1)
|
||||
fprintf(stderr, "Failed to initiate VoE reading: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_write(ec_voe_handler_t *voe, size_t size)
|
||||
{
|
||||
ec_ioctl_voe_t data;
|
||||
|
|
|
|||
|
|
@ -2227,6 +2227,45 @@ int ec_cdev_ioctl_voe_read(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Starts a VoE read operation without sending a sync message first.
|
||||
*/
|
||||
int ec_cdev_ioctl_voe_read_nosync(
|
||||
ec_master_t *master, /**< EtherCAT master. */
|
||||
unsigned long arg, /**< ioctl() argument. */
|
||||
ec_cdev_priv_t *priv /**< Private data structure of file handle. */
|
||||
)
|
||||
{
|
||||
ec_ioctl_voe_t data;
|
||||
ec_slave_config_t *sc;
|
||||
ec_voe_handler_t *voe;
|
||||
|
||||
if (unlikely(!priv->requested))
|
||||
return -EPERM;
|
||||
|
||||
if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
|
||||
return -EFAULT;
|
||||
|
||||
if (down_interruptible(&master->master_sem))
|
||||
return -EINTR;
|
||||
|
||||
if (!(sc = ec_master_get_config(master, data.config_index))) {
|
||||
up(&master->master_sem);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) {
|
||||
up(&master->master_sem);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
up(&master->master_sem);
|
||||
|
||||
ecrt_voe_handler_read_nosync(voe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Starts a VoE write operation.
|
||||
*/
|
||||
int ec_cdev_ioctl_voe_write(
|
||||
|
|
@ -2559,6 +2598,10 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
case EC_IOCTL_VOE_READ:
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
return -EPERM;
|
||||
case EC_IOCTL_VOE_READ_NOSYNC:
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
return -EPERM;
|
||||
return ec_cdev_ioctl_voe_read_nosync(master, arg, priv);
|
||||
return ec_cdev_ioctl_voe_read(master, arg, priv);
|
||||
case EC_IOCTL_VOE_WRITE:
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
|
|
|
|||
|
|
@ -104,9 +104,10 @@
|
|||
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x2a, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x2b, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ EC_IOW(0x2c, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x2d, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x2e, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_DATA EC_IOWR(0x2f, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x2d, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x2e, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x2f, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_DATA EC_IOWR(0x30, ec_ioctl_voe_t)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ void ec_voe_handler_state_read_start(ec_voe_handler_t *);
|
|||
void ec_voe_handler_state_read_check(ec_voe_handler_t *);
|
||||
void ec_voe_handler_state_read_response(ec_voe_handler_t *);
|
||||
|
||||
void ec_voe_handler_state_read_nosync_start(ec_voe_handler_t *);
|
||||
void ec_voe_handler_state_read_nosync_response(ec_voe_handler_t *);
|
||||
|
||||
void ec_voe_handler_state_end(ec_voe_handler_t *);
|
||||
void ec_voe_handler_state_error(ec_voe_handler_t *);
|
||||
|
||||
|
|
@ -168,6 +171,15 @@ void ecrt_voe_handler_read(ec_voe_handler_t *voe)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_read_nosync(ec_voe_handler_t *voe)
|
||||
{
|
||||
voe->dir = EC_DIR_INPUT;
|
||||
voe->state = ec_voe_handler_state_read_nosync_start;
|
||||
voe->request_state = EC_INT_REQUEST_QUEUED;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ecrt_voe_handler_write(ec_voe_handler_t *voe, size_t size)
|
||||
{
|
||||
voe->dir = EC_DIR_OUTPUT;
|
||||
|
|
@ -427,6 +439,106 @@ void ec_voe_handler_state_read_response(ec_voe_handler_t *voe)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Start reading VoE data without sending a sync message before.
|
||||
*/
|
||||
void ec_voe_handler_state_read_nosync_start(ec_voe_handler_t *voe)
|
||||
{
|
||||
ec_datagram_t *datagram = &voe->datagram;
|
||||
ec_slave_t *slave = voe->config->slave;
|
||||
|
||||
if (slave->master->debug_level)
|
||||
EC_DBG("Reading VoE data to slave %u.\n", slave->ring_position);
|
||||
|
||||
if (!(slave->sii.mailbox_protocols & EC_MBOX_VOE)) {
|
||||
EC_ERR("Slave %u does not support VoE!\n", slave->ring_position);
|
||||
voe->state = ec_voe_handler_state_error;
|
||||
voe->request_state = EC_INT_REQUEST_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
|
||||
|
||||
voe->jiffies_start = jiffies;
|
||||
voe->retries = EC_FSM_RETRIES;
|
||||
voe->state = ec_voe_handler_state_read_nosync_response;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Read the pending mailbox data without sending a sync message before. This
|
||||
* might lead to an empty reponse from the client.
|
||||
*/
|
||||
void ec_voe_handler_state_read_nosync_response(ec_voe_handler_t *voe)
|
||||
{
|
||||
ec_datagram_t *datagram = &voe->datagram;
|
||||
ec_slave_t *slave = voe->config->slave;
|
||||
ec_master_t *master = voe->config->master;
|
||||
uint8_t *data, mbox_prot;
|
||||
size_t rec_size;
|
||||
|
||||
if (datagram->state == EC_DATAGRAM_TIMED_OUT && voe->retries--)
|
||||
return;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
voe->state = ec_voe_handler_state_error;
|
||||
voe->request_state = EC_INT_REQUEST_FAILURE;
|
||||
EC_ERR("Failed to receive VoE read datagram for"
|
||||
" slave %u (datagram state %u).\n",
|
||||
slave->ring_position, datagram->state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter == 0) {
|
||||
voe->state = ec_voe_handler_state_error;
|
||||
voe->request_state = EC_INT_REQUEST_FAILURE;
|
||||
EC_DBG("Slave (%u) did not send data with Mailbox.",
|
||||
slave->ring_position);
|
||||
return;
|
||||
}
|
||||
|
||||
if (datagram->working_counter != 1) {
|
||||
voe->state = ec_voe_handler_state_error;
|
||||
voe->request_state = EC_INT_REQUEST_FAILURE;
|
||||
EC_WARN("Reception of VoE read response failed on slave %u: ",
|
||||
slave->ring_position);
|
||||
ec_datagram_print_wc_error(datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_mbox_fetch(slave, datagram,
|
||||
&mbox_prot, &rec_size))) {
|
||||
voe->state = ec_voe_handler_state_error;
|
||||
voe->request_state = EC_INT_REQUEST_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mbox_prot != EC_MBOX_TYPE_VOE) {
|
||||
voe->state = ec_voe_handler_state_error;
|
||||
voe->request_state = EC_INT_REQUEST_FAILURE;
|
||||
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
|
||||
ec_print_data(data, rec_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rec_size < EC_VOE_HEADER_SIZE) {
|
||||
voe->state = ec_voe_handler_state_error;
|
||||
voe->request_state = EC_INT_REQUEST_FAILURE;
|
||||
EC_ERR("Received VoE header is incomplete (%u bytes)!\n", rec_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (master->debug_level) {
|
||||
EC_DBG("VoE data:\n");
|
||||
ec_print_data(data, rec_size);
|
||||
}
|
||||
|
||||
voe->data_size = rec_size - EC_VOE_HEADER_SIZE;
|
||||
voe->request_state = EC_INT_REQUEST_SUCCESS;
|
||||
voe->state = ec_voe_handler_state_end; // success
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Successful termination state function.
|
||||
*/
|
||||
void ec_voe_handler_state_end(ec_voe_handler_t *voe)
|
||||
|
|
|
|||
Loading…
Reference in New Issue