Implemented debug frame ring to output the last n frames for debugging
authorFlorian Pose <fp@igh-essen.com>
Thu, 09 Aug 2007 15:01:14 +0000
changeset 692 fe7cf37c33f1
parent 691 77b79a29e0e7
child 693 e341f1788608
Implemented debug frame ring to output the last n frames for debugging
reasons.
configure.ac
master/device.c
master/device.h
master/master.c
--- a/configure.ac	Thu Aug 09 14:47:37 2007 +0000
+++ b/configure.ac	Thu Aug 09 15:01:14 2007 +0000
@@ -368,6 +368,30 @@
 AM_CONDITIONAL(ENABLE_DEBUG_IF, test "x$dbg" = "x1")
 
 #------------------------------------------------------------------------------
+# Debug ring
+#------------------------------------------------------------------------------
+
+AC_ARG_ENABLE([debug-ring],
+    AS_HELP_STRING([--enable-debug-ring],
+                   [Create a debug ring to record frames @<:@NO@:>@]),
+    [
+        case "${enableval}" in
+            yes) debugring=1
+                ;;
+            no) debugring=0
+                ;;
+            *) AC_MSG_ERROR([Invalid value for --enable-debug-ring])
+                ;;
+        esac
+    ],
+    [debugring=0]
+)
+
+if test "x${debugring}" = "x1"; then
+    AC_DEFINE([EC_DEBUG_RING], [1], [Debug ring enabled])
+fi
+
+#------------------------------------------------------------------------------
 # Dummy master module
 #------------------------------------------------------------------------------
 
--- a/master/device.c	Thu Aug 09 14:47:37 2007 +0000
+++ b/master/device.c	Thu Aug 09 15:01:14 2007 +0000
@@ -46,6 +46,18 @@
 #include "device.h"
 #include "master.h"
 
+#ifdef EC_DEBUG_RING
+#define timersub(a, b, result) \
+    do { \
+        (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+        (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+        if ((result)->tv_usec < 0) { \
+            --(result)->tv_sec; \
+            (result)->tv_usec += 1000000; \
+        } \
+    } while (0)
+#endif
+
 /*****************************************************************************/
 
 /**
@@ -61,6 +73,10 @@
     char ifname[10];
     char mb = 'x';
 #endif
+#ifdef EC_DEBUG_RING
+    device->debug_frame_index = 0;
+    device->debug_frame_count = 0;
+#endif
 
     device->master = master;
 
@@ -249,6 +265,10 @@
 #ifdef EC_DEBUG_IF
     ec_debug_send(&device->dbg, device->tx_skb->data, ETH_HLEN + size);
 #endif
+#ifdef EC_DEBUG_RING
+    ec_device_debug_ring_append(
+            device, TX, device->tx_skb->data + ETH_HLEN, size);
+#endif
 
     // start sending
     device->dev->hard_start_xmit(device->tx_skb, device->dev);
@@ -257,6 +277,79 @@
 
 /*****************************************************************************/
 
+#ifdef EC_DEBUG_RING
+/**
+ * Appends frame data to the debug ring.
+ */
+
+void ec_device_debug_ring_append(
+        ec_device_t *device, /**< EtherCAT device */
+        ec_debug_frame_dir_t dir, /**< direction */
+        const void *data, /**< frame data */
+        size_t size /**< data size */
+        )
+{
+    ec_debug_frame_t *df = &device->debug_frames[device->debug_frame_index];
+
+    df->dir = dir;
+    if (dir == TX)
+        do_gettimeofday(&df->t);
+    else
+        df->t = device->timeval_poll;
+    memcpy(df->data, data, size);
+    df->data_size = size;
+
+    device->debug_frame_index++;
+    device->debug_frame_index %= EC_DEBUG_RING_SIZE;
+    if (unlikely(device->debug_frame_count < EC_DEBUG_RING_SIZE))
+        device->debug_frame_count++;
+}
+
+/*****************************************************************************/
+
+/**
+ * Outputs the debug ring.
+ */
+
+void ec_device_debug_ring_print(
+        const ec_device_t *device /**< EtherCAT device */
+        )
+{
+    int i;
+    unsigned int ring_index;
+    const ec_debug_frame_t *df;
+    struct timeval t0, diff;
+
+    // calculate index of the newest frame in the ring to get its time
+    ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE - 1)
+        % EC_DEBUG_RING_SIZE;
+    t0 = device->debug_frames[ring_index].t;
+
+    EC_DBG("Debug ring %i:\n", ring_index);
+
+    // calculate index of the oldest frame in the ring
+    ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE
+            - device->debug_frame_count) % EC_DEBUG_RING_SIZE;
+
+    for (i = 0; i < device->debug_frame_count; i++) {
+        df = &device->debug_frames[ring_index];
+        timersub(&t0, &df->t, &diff);
+
+        EC_DBG("Frame %i, dt=%u.%06u s, %s:\n",
+                i + 1 - device->debug_frame_count,
+                (unsigned int) diff.tv_sec,
+                (unsigned int) diff.tv_usec,
+                (df->dir == TX) ? "TX" : "RX");
+        ec_print_data(df->data, df->data_size);
+
+        ring_index++;
+        ring_index %= EC_DEBUG_RING_SIZE;
+    }
+}
+#endif
+
+/*****************************************************************************/
+
 /**
    Calls the poll function of the assigned net_device.
    The master itself works without using interrupts. Therefore the processing
@@ -268,6 +361,9 @@
 {
     device->cycles_poll = get_cycles();
     device->jiffies_poll = jiffies;
+#ifdef EC_DEBUG_RING
+    do_gettimeofday(&device->timeval_poll);
+#endif
     device->poll(device->dev);
 }
 
@@ -287,21 +383,23 @@
                    size_t size /**< number of bytes received */
                    )
 {
+    const void *ec_data = data + ETH_HLEN;
+    size_t ec_size = size - ETH_HLEN;
     device->rx_count++;
 
     if (unlikely(device->master->debug_level > 1)) {
         EC_DBG("Received frame:\n");
-        ec_print_data_diff(device->tx_skb->data + ETH_HLEN,
-                           data + ETH_HLEN, size - ETH_HLEN);
+        ec_print_data_diff(device->tx_skb->data + ETH_HLEN, ec_data, ec_size);
     }
 
 #ifdef EC_DEBUG_IF
     ec_debug_send(&device->dbg, data, size);
 #endif
-
-    ec_master_receive_datagrams(device->master,
-                                data + ETH_HLEN,
-                                size - ETH_HLEN);
+#ifdef EC_DEBUG_RING
+    ec_device_debug_ring_append(device, RX, ec_data, ec_size);
+#endif
+
+    ec_master_receive_datagrams(device->master, ec_data, ec_size);
 }
 
 /*****************************************************************************/
--- a/master/device.h	Thu Aug 09 14:47:37 2007 +0000
+++ b/master/device.h	Thu Aug 09 15:01:14 2007 +0000
@@ -51,6 +51,23 @@
 #include "debug.h"
 #endif
 
+#ifdef EC_DEBUG_RING
+#define EC_DEBUG_RING_SIZE 10
+
+typedef enum {
+    TX, RX
+} ec_debug_frame_dir_t;
+
+typedef struct {
+    ec_debug_frame_dir_t dir;
+    struct timeval t;
+    unsigned int addr;
+    uint8_t data[EC_MAX_DATA_SIZE];
+    unsigned int data_size;
+} ec_debug_frame_t;
+
+#endif
+
 /*****************************************************************************/
 
 /**
@@ -70,12 +87,20 @@
     struct sk_buff *tx_skb; /**< transmit socket buffer */
     struct ethhdr *eth; /**< pointer to ethernet header in socket buffer */
     cycles_t cycles_poll; /**< cycles of last poll */
+#ifdef EC_DEBUG_RING
+    struct timeval timeval_poll;
+#endif
     unsigned long jiffies_poll; /**< jiffies of last poll */
     unsigned int tx_count; /**< number of frames sent */
     unsigned int rx_count; /**< number of frames received */
 #ifdef EC_DEBUG_IF
     ec_debug_t dbg; /**< debug device */
 #endif
+#ifdef EC_DEBUG_RING
+    ec_debug_frame_t debug_frames[EC_DEBUG_RING_SIZE];
+    unsigned int debug_frame_index;
+    unsigned int debug_frame_count;
+#endif
 };
 
 /*****************************************************************************/
@@ -94,6 +119,12 @@
 uint8_t *ec_device_tx_data(ec_device_t *);
 void ec_device_send(ec_device_t *, size_t);
 
+#ifdef EC_DEBUG_RING
+void ec_device_debug_ring_append(ec_device_t *, ec_debug_frame_dir_t,
+        const void *, size_t);
+void ec_device_debug_ring_print(const ec_device_t *);
+#endif
+
 /*****************************************************************************/
 
 #endif
--- a/master/master.c	Thu Aug 09 14:47:37 2007 +0000
+++ b/master/master.c	Thu Aug 09 15:01:14 2007 +0000
@@ -724,6 +724,9 @@
                 ec_print_data(cur_data - EC_DATAGRAM_HEADER_SIZE,
                         EC_DATAGRAM_HEADER_SIZE + data_size
                         + EC_DATAGRAM_FOOTER_SIZE);
+#ifdef EC_DEBUG_RING
+                ec_device_debug_ring_print(&master->main_device);
+#endif
             }
 
             cur_data += data_size + EC_DATAGRAM_FOOTER_SIZE;