16-ethercat-1.5-frame-corruption.patch
authorDave Page <dave.page@gleeble.com>
Tue, 14 Apr 2015 16:25:44 -0400
changeset 2630 a380cce7d6f0
parent 2629 a2701af27fde
child 2635 42b62867574d
16-ethercat-1.5-frame-corruption.patch
from ethercat-1.5.0-patches-v2.tar.bz2
by Frank Heckenbach f.heckenbach@ at fh-soft.de
Ref: http://lists.etherlab.org/pipermail/etherlab-dev/2014/000404.html
with some additional edits.
include/ecrt.h
lib/master.c
master/device.h
master/ioctl.c
master/master.c
--- a/include/ecrt.h	Tue Apr 14 13:12:24 2015 -0400
+++ b/include/ecrt.h	Tue Apr 14 16:25:44 2015 -0400
@@ -956,8 +956,10 @@
  *
  * Has to be called cyclically by the application after ecrt_master_activate()
  * has returned.
- */
-void ecrt_master_send(
+ *
+ * Returns the number of bytes sent.
+ */
+size_t ecrt_master_send(
         ec_master_t *master /**< EtherCAT master. */
         );
 
--- a/lib/master.c	Tue Apr 14 13:12:24 2015 -0400
+++ b/lib/master.c	Tue Apr 14 16:25:44 2015 -0400
@@ -607,15 +607,18 @@
 
 /****************************************************************************/
 
-void ecrt_master_send(ec_master_t *master)
-{
-    int ret;
-
-    ret = ioctl(master->fd, EC_IOCTL_SEND, NULL);
+size_t ecrt_master_send(ec_master_t *master)
+{
+    int ret;
+    size_t sent_bytes = 0;
+
+    ret = ioctl(master->fd, EC_IOCTL_SEND, &sent_bytes);
     if (EC_IOCTL_IS_ERROR(ret)) {
         fprintf(stderr, "Failed to send: %s\n",
                 strerror(EC_IOCTL_ERRNO(ret)));
     }
+
+    return sent_bytes;
 }
 
 /****************************************************************************/
--- a/master/device.h	Tue Apr 14 13:12:24 2015 -0400
+++ b/master/device.h	Tue Apr 14 16:25:44 2015 -0400
@@ -48,7 +48,7 @@
  * different memory regions, because otherwise the network device DMA could
  * send the same data twice, if it is called twice.
  */
-#define EC_TX_RING_SIZE 2
+#define EC_TX_RING_SIZE 0x10
 
 #ifdef EC_DEBUG_IF
 #include "debug.h"
--- a/master/ioctl.c	Tue Apr 14 13:12:24 2015 -0400
+++ b/master/ioctl.c	Tue Apr 14 16:25:44 2015 -0400
@@ -1913,11 +1913,18 @@
         ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
         )
 {
+    size_t sent_bytes;
+
     if (unlikely(!ctx->requested)) {
         return -EPERM;
     }
 
-    ecrt_master_send(master);
+    sent_bytes = ecrt_master_send(master);
+
+    if (copy_to_user((void __user *) arg, &sent_bytes, sizeof(sent_bytes))) {
+        return -EFAULT;
+    }
+
     return 0;
 }
 
--- a/master/master.c	Tue Apr 14 13:12:24 2015 -0400
+++ b/master/master.c	Tue Apr 14 16:25:44 2015 -0400
@@ -981,7 +981,7 @@
 /** Sends the datagrams in the queue for a certain device.
  *
  */
-void ec_master_send_datagrams(
+size_t ec_master_send_datagrams(
         ec_master_t *master, /**< EtherCAT master */
         ec_device_index_t device_index /**< Device index. */
         )
@@ -996,6 +996,7 @@
     unsigned long jiffies_sent;
     unsigned int frame_count, more_datagrams_waiting;
     struct list_head sent_datagrams;
+    size_t sent_bytes = 0;
 
 #ifdef EC_HAVE_CYCLES
     cycles_start = get_cycles();
@@ -1081,6 +1082,8 @@
         // send frame
         ec_device_send(&master->devices[device_index],
                 cur_data - frame_data);
+        /* preamble and inter-frame gap */
+        sent_bytes += ETH_HLEN + cur_data - frame_data + ETH_FCS_LEN + 20;
 #ifdef EC_HAVE_CYCLES
         cycles_sent = get_cycles();
 #endif
@@ -1098,7 +1101,7 @@
 
         frame_count++;
     }
-    while (more_datagrams_waiting);
+    while (more_datagrams_waiting && frame_count < EC_TX_RING_SIZE);
 
 #ifdef EC_HAVE_CYCLES
     if (unlikely(master->debug_level > 1)) {
@@ -1108,6 +1111,7 @@
                (unsigned int) (cycles_end - cycles_start) * 1000 / cpu_khz);
     }
 #endif
+    return sent_bytes;
 }
 
 /*****************************************************************************/
@@ -1535,9 +1539,7 @@
 {
     ec_master_t *master = (ec_master_t *) priv_data;
     int fsm_exec;
-#ifdef EC_USE_HRTIMER
     size_t sent_bytes;
-#endif
 
     // send interval in IDLE phase
     ec_master_set_send_interval(master, 1000000 / HZ);
@@ -1570,11 +1572,7 @@
         if (fsm_exec) {
             ec_master_queue_datagram(master, &master->fsm_datagram);
         }
-        ecrt_master_send(master);
-#ifdef EC_USE_HRTIMER
-        sent_bytes = master->devices[EC_DEVICE_MAIN].tx_skb[
-            master->devices[EC_DEVICE_MAIN].tx_ring_index]->len;
-#endif
+        sent_bytes = ecrt_master_send(master);
         up(&master->io_sem);
 
         if (ec_fsm_master_idle(&master->fsm)) {
@@ -1586,7 +1584,8 @@
 #endif
         } else {
 #ifdef EC_USE_HRTIMER
-            ec_master_nanosleep(sent_bytes * EC_BYTE_TRANSMISSION_TIME_NS);
+            ec_master_nanosleep(
+                    sent_bytes * EC_BYTE_TRANSMISSION_TIME_NS * 6 / 5);
 #else
             schedule();
 #endif
@@ -2447,10 +2446,12 @@
 
 /*****************************************************************************/
 
-void ecrt_master_send(ec_master_t *master)
+size_t ecrt_master_send(ec_master_t *master)
 {
     ec_datagram_t *datagram, *n;
     ec_device_index_t dev_idx;
+    size_t sent_bytes = 0;
+
 
     if (master->injection_seq_rt != master->injection_seq_fsm) {
         // inject datagram produced by master FSM
@@ -2485,8 +2486,11 @@
         }
 
         // send frames
-        ec_master_send_datagrams(master, dev_idx);
-    }
+        sent_bytes = max(sent_bytes,
+            ec_master_send_datagrams(master, dev_idx));
+    }
+
+    return sent_bytes;
 }
 
 /*****************************************************************************/