Included ecrt_voe_handler_read_nosync()-Patch by Mathias Weber.
--- a/include/ecrt.h Mon Nov 17 17:18:02 2008 +0000
+++ b/include/ecrt.h Tue Nov 18 11:13:49 2008 +0000
@@ -1049,6 +1049,25 @@
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
--- a/lib/voe_handler.c Mon Nov 17 17:18:02 2008 +0000
+++ b/lib/voe_handler.c Tue Nov 18 11:13:49 2008 +0000
@@ -111,6 +111,20 @@
/*****************************************************************************/
+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;
--- a/master/cdev.c Mon Nov 17 17:18:02 2008 +0000
+++ b/master/cdev.c Tue Nov 18 11:13:49 2008 +0000
@@ -2227,6 +2227,45 @@
/*****************************************************************************/
+/** 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 @@
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))
--- a/master/ioctl.h Mon Nov 17 17:18:02 2008 +0000
+++ b/master/ioctl.h Tue Nov 18 11:13:49 2008 +0000
@@ -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)
/*****************************************************************************/
--- a/master/voe_handler.c Mon Nov 17 17:18:02 2008 +0000
+++ b/master/voe_handler.c Tue Nov 18 11:13:49 2008 +0000
@@ -65,6 +65,9 @@
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_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 @@
/*****************************************************************************/
+/** 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)