Răsfoiți Sursa

refactor: move netdev stats into netdev struct

Signed-off-by: sakumisu <1203593632@qq.com>
sakumisu 1 săptămână în urmă
părinte
comite
e6421b8005
9 a modificat fișierele cu 162 adăugiri și 316 ștergeri
  1. 1 1
      include/ec_datagram.h
  2. 7 0
      include/ec_def.h
  3. 18 41
      include/ec_master.h
  4. 23 18
      include/ec_netdev.h
  5. 4 13
      include/ec_slave.h
  6. 36 68
      src/ec_cmd.c
  7. 24 105
      src/ec_master.c
  8. 32 49
      src/ec_netdev.c
  9. 17 21
      src/ec_slave.c

+ 1 - 1
include/ec_datagram.h

@@ -45,7 +45,7 @@ typedef struct {
     ec_dlist_t queue;
     ec_dlist_t ext_queue;
     ec_dlist_t sent;
-    ec_netdev_index_t netdev_idx;     /**< Netdev via which the datagram shall be / was sent. */
+    uint8_t netdev_idx;               /**< Netdev via which the datagram shall be / was sent. */
     ec_datagram_type_t type;          /**< Datagram type (APRD, BWR, etc.). */
     bool static_alloc;                /**< True, if \a data is statically allocated. */
     uint8_t address[EC_ADDR_LEN];     /**< Recipient address. */

+ 7 - 0
include/ec_def.h

@@ -127,6 +127,13 @@ typedef enum {
     /**< Acknowledge/Error bit (no actual state) */
 } ec_slave_state_t;
 
+typedef enum {
+    EC_PORT_NOT_IMPLEMENTED, /**< Port is not implemented. */
+    EC_PORT_NOT_CONFIGURED,  /**< Port is not configured. */
+    EC_PORT_EBUS,            /**< Port is an E-Bus. */
+    EC_PORT_MII              /**< Port is a MII. */
+} ec_slave_port_desc_t;
+
 /** Slave information interface CANopen over EtherCAT details flags.
  */
 typedef struct {

+ 18 - 41
include/ec_master.h

@@ -32,37 +32,14 @@
 #include "ec_eoe.h"
 #include "ec_cmd.h"
 
-/** Netdev statistics.
- */
-typedef struct {
-    uint64_t tx_count;                     /**< Number of frames sent. */
-    uint64_t last_tx_count;                /**< Number of frames sent of last statistics cycle. */
-    uint64_t rx_count;                     /**< Number of frames received. */
-    uint64_t last_rx_count;                /**< Number of frames received of last statistics cycle. */
-    uint64_t tx_bytes;                     /**< Number of bytes sent. */
-    uint64_t last_tx_bytes;                /**< Number of bytes sent of last statistics cycle. */
-    uint64_t rx_bytes;                     /**< Number of bytes received. */
-    uint64_t last_rx_bytes;                /**< Number of bytes received of last statistics cycle. */
-    uint64_t last_loss;                    /**< Tx/Rx difference of last statistics cycle. */
-    int32_t tx_frame_rates[EC_RATE_COUNT]; /**< Transmit rates in frames/s for different statistics cycle periods.*/
-    int32_t rx_frame_rates[EC_RATE_COUNT]; /**< Receive rates in frames/s for different statistics cycle periods.*/
-    int32_t tx_byte_rates[EC_RATE_COUNT];  /**< Transmit rates in byte/s for different statistics cycle periods. */
-    int32_t rx_byte_rates[EC_RATE_COUNT];  /**< Receive rates in byte/s for different statistics cycle periods. */
-    int32_t loss_rates[EC_RATE_COUNT];     /**< Frame loss rates for different statistics cycle periods. */
-    uint64_t last_jiffies;                 /**< Jiffies of last statistic cycle. */
-} ec_netdev_stats_t;
-
-/** Cyclic statistics.
- */
 typedef struct {
-    unsigned int timeouts;        /**< datagram timeouts */
-    unsigned int corrupted;       /**< corrupted frames */
-    unsigned int unmatched;       /**< unmatched datagrams (received, but not queued any longer) */
-    unsigned long output_jiffies; /**< time of last output */
-} ec_stats_t;
+    unsigned int timeouts;
+    unsigned int corrupted;
+    unsigned int unmatched;
+} ec_master_stats_t;
 
 typedef enum {
-    EC_ORPHANED, /**< Orphaned phase. The master has no Ethernet device attached. */
+    EC_UNKNOWN,  /**< Unknown phase. No Ethernet device is attached. */
     EC_IDLE,     /**< Idle phase. An Ethernet device is attached, but the master is not in use, yet. */
     EC_OPERATION /**< Operation phase. The master was requested by a realtime application. */
 } ec_master_phase_t;
@@ -81,14 +58,14 @@ typedef struct ec_master {
     uint8_t index;
     ec_netdev_t *netdev[CONFIG_EC_MAX_NETDEVS];
     bool link_state[CONFIG_EC_MAX_NETDEVS];
-    uint32_t slaves_responding[CONFIG_EC_MAX_NETDEVS];
+    uint32_t slaves_working_counter[CONFIG_EC_MAX_NETDEVS];
     ec_slave_state_t slaves_state[CONFIG_EC_MAX_NETDEVS];
-    ec_netdev_stats_t netdev_stats;
-    ec_stats_t stats;
-    ec_master_phase_t phase;
-    bool active;         /**< Master is started. */
+
+    bool started;        /**< Master is started. */
     bool scan_done;      /**< Slave scan is done. */
     bool rescan_request; /**< Rescan requested. */
+    ec_master_stats_t stats;
+    ec_master_phase_t phase;
 
     ec_datagram_t main_datagram; /**< Main datagram for slave scan & state change & config & sii */
 
@@ -96,17 +73,17 @@ typedef struct ec_master {
     ec_dlist_t pdo_datagram_queue; /**< Queue of pdo datagrams*/
     uint8_t datagram_index;
 
-    ec_slave_t *dc_ref_clock;                /**< DC reference clock slave. */
-    ec_datagram_t dc_ref_sync_datagram;      /**< Datagram used for synchronizing the reference clock to the master clock. */
-    ec_datagram_t dc_all_sync_datagram;      /**< Datagram used for synchronizing all slaves to the dc ref clock. */
-    ec_datagram_t systime_diff_mon_datagram; /**< Datagram used for reading the system time difference between master and reference clock. */
+    ec_slave_t *dc_ref_clock;           /**< DC reference clock slave. */
+    ec_datagram_t dc_ref_sync_datagram; /**< Datagram used for synchronizing the reference clock to the master clock. */
+    ec_datagram_t dc_all_sync_datagram; /**< Datagram used for synchronizing all slaves to the dc ref clock. */
 
+    ec_datagram_t systime_diff_mon_datagram; /**< Datagram used for reading the system time difference between master and reference clock. */
+    bool systime_diff_enable;
     uint32_t min_systime_diff;
     uint32_t max_systime_diff;
     uint32_t curr_systime_diff;
     uint32_t systime_diff_count;
     uint64_t total_systime_diff;
-    bool systime_diff_enable;
 
     bool dc_sync_with_dc_ref_enable; /**< true: Sync the reference clock by dc ref clock, false: by master */
     uint32_t cycle_time;             /**< Cycle time [ns]. */
@@ -139,9 +116,9 @@ typedef struct ec_master {
     bool nonperiod_suspend;
 
     uint8_t pdo_buffer[CONFIG_EC_MAX_NETDEVS][CONFIG_EC_MAX_PDO_BUFSIZE];
-    uint32_t actual_pdo_size;
-    uint32_t expected_working_counter;
-    uint32_t actual_working_counter;
+    uint32_t actual_pdo_size;          /**< Actual PDO size for current setting. */
+    uint32_t expected_working_counter; /**< Expected working counter for PDO datagrams. */
+    uint32_t actual_working_counter;   /**< Actual working counter for PDO datagrams. */
 } ec_master_t;
 
 int ec_master_init(ec_master_t *master, uint8_t master_index);

+ 23 - 18
include/ec_netdev.h

@@ -10,34 +10,39 @@
 
 typedef struct ec_master ec_master_t;
 
-typedef struct ec_netdev {
-    ec_master_t *master;
-    struct chry_phy_device phydev;
-    ec_netdev_index_t index;
-    char name[24];
-    uint8_t mac_addr[6];
-    bool link_state;
-    uint8_t tx_frame_index;
-    unsigned long jiffies_poll;
-
-    // Frame statistics
+/** Netdev statistics.
+ */
+typedef struct {
     uint64_t tx_count;                     /**< Number of frames sent. */
-    uint64_t last_tx_count;                /**< Number of frames sent of last statistics cycle.*/
+    uint64_t last_tx_count;                /**< Number of frames sent of last statistics cycle. */
     uint64_t rx_count;                     /**< Number of frames received. */
-    uint64_t last_rx_count;                /**< Number of frames received of last statistics cycle.*/
+    uint64_t last_rx_count;                /**< Number of frames received of last statistics cycle. */
     uint64_t tx_bytes;                     /**< Number of bytes sent. */
-    uint64_t last_tx_bytes;                /**< Number of bytes sent of last statistics cycle.*/
+    uint64_t last_tx_bytes;                /**< Number of bytes sent of last statistics cycle. */
     uint64_t rx_bytes;                     /**< Number of bytes received. */
-    uint64_t last_rx_bytes;                /**< Number of bytes received of last statistics cycle.*/
+    uint64_t last_rx_bytes;                /**< Number of bytes received of last statistics cycle. */
     uint64_t tx_errors;                    /**< Number of transmit errors. */
+    uint64_t loss_count;                   /**< Number of lost frames. */
     int32_t tx_frame_rates[EC_RATE_COUNT]; /**< Transmit rates in frames/s for different statistics cycle periods.*/
     int32_t rx_frame_rates[EC_RATE_COUNT]; /**< Receive rates in frames/s for different statistics cycle periods.*/
-    int32_t tx_byte_rates[EC_RATE_COUNT];  /**< Transmit rates in byte/s for different statistics cycle periods.*/
-    int32_t rx_byte_rates[EC_RATE_COUNT];  /**< Receive rates in byte/s for different statistics cycle periods.*/
+    int32_t tx_byte_rates[EC_RATE_COUNT];  /**< Transmit rates in byte/s for different statistics cycle periods. */
+    int32_t rx_byte_rates[EC_RATE_COUNT];  /**< Receive rates in byte/s for different statistics cycle periods. */
+    int32_t loss_rates[EC_RATE_COUNT];     /**< Frame loss rates for different statistics cycle periods. */
+    uint64_t last_jiffies;                 /**< Jiffies of last statistic cycle. */
+} ec_netdev_stats_t;
+
+typedef struct ec_netdev {
+    ec_master_t *master;
+    struct chry_phy_device phydev;
+    uint8_t index;
+    char name[24];
+    uint8_t mac_addr[6];
+    bool link_state;
+    uint8_t tx_frame_index;
 
+    ec_netdev_stats_t stats;
 } ec_netdev_t;
 
-void ec_netdev_clear_stats(ec_netdev_t *netdev);
 void ec_netdev_update_stats(ec_netdev_t *netdev);
 
 ec_netdev_t *ec_netdev_init(uint8_t netdev_index);

+ 4 - 13
include/ec_slave.h

@@ -37,15 +37,6 @@ typedef struct {
     ec_sync_signal_t dc_sync[EC_SYNC_SIGNAL_COUNT]; /**< DC sync signals. */
 } ec_slave_config_t;
 
-/** EtherCAT slave port descriptor.
- */
-typedef enum {
-    EC_PORT_NOT_IMPLEMENTED, /**< Port is not implemented. */
-    EC_PORT_NOT_CONFIGURED,  /**< Port is not configured. */
-    EC_PORT_EBUS,            /**< Port is an E-Bus. */
-    EC_PORT_MII              /**< Port is a MII. */
-} ec_slave_port_desc_t;
-
 /** EtherCAT slave port information.
  */
 typedef struct {
@@ -63,13 +54,13 @@ typedef struct {
 } ec_slave_port_t;
 
 typedef struct ec_slave {
-    uint32_t index;               /**< Index of the slave in the master slave array. */
-    ec_master_t *master;          /**< Master owning the slave. */
-    ec_netdev_index_t netdev_idx; /**< Index of device the slave responds on. */
+    uint32_t index;      /**< Index of the slave in the master slave array. */
+    ec_master_t *master; /**< Master owning the slave. */
+    uint8_t netdev_idx;  /**< Index of device the slave responds on. */
 
     uint16_t autoinc_address; /**< Auto-increment address. */
     uint16_t station_address; /**< Configured station address. */
-    uint16_t effective_alias; /**< Effective alias address. */
+    uint16_t alias_address;   /**< alias address. */
 
     ec_slave_port_t ports[EC_MAX_PORTS]; /**< Port information. */
 

+ 36 - 68
src/ec_cmd.c

@@ -85,26 +85,27 @@ void ec_master_cmd_master(ec_master_t *master)
 {
     unsigned int dev_idx, j;
     uint64_t lost;
-    double perc;
     int colwidth = 8;
+    ec_netdev_stats_t netdev_stats;
+    uintptr_t flags;
 
     EC_LOG_RAW("Master%d\n", master->index);
     EC_LOG_RAW("  Phase: ");
     switch (master->phase) {
         case 0:
-            EC_LOG_RAW("Waiting for device(s)...");
+            EC_LOG_RAW("Waiting for device attached...\n");
             break;
         case 1:
-            EC_LOG_RAW("Idle");
+            EC_LOG_RAW("Idle\n");
             break;
         case 2:
-            EC_LOG_RAW("Operation");
+            EC_LOG_RAW("Operation\n");
             break;
         default:
-            EC_LOG_RAW("???");
+            EC_LOG_RAW("Unknown\n");
+            break;
     }
 
-    EC_LOG_RAW("\n");
     EC_LOG_RAW("  Slaves: %u\n", master->slave_count);
     EC_LOG_RAW("  Ethernet net devices:\n");
 
@@ -118,89 +119,56 @@ void ec_master_cmd_master(ec_master_t *master)
                    master->netdev[dev_idx]->mac_addr[4],
                    master->netdev[dev_idx]->mac_addr[5]);
         EC_LOG_RAW("      Link: %s\n", master->netdev[dev_idx]->link_state ? "UP" : "DOWN");
-        EC_LOG_RAW("      Tx frames:   %llu\n", master->netdev[dev_idx]->tx_count);
-        EC_LOG_RAW("      Tx bytes:    %llu\n", master->netdev[dev_idx]->tx_bytes);
-        EC_LOG_RAW("      Rx frames:   %llu\n", master->netdev[dev_idx]->rx_count);
-        EC_LOG_RAW("      Rx bytes:    %llu\n", master->netdev[dev_idx]->rx_bytes);
-        EC_LOG_RAW("      Tx errors:   %llu\n", master->netdev[dev_idx]->tx_errors);
+
+        flags = ec_osal_enter_critical_section();
+        memcpy(&netdev_stats, &master->netdev[dev_idx]->stats, sizeof(ec_netdev_stats_t));
+        ec_osal_leave_critical_section(flags);
+
+        EC_LOG_RAW("      Tx frames:   %llu\n", netdev_stats.tx_count);
+        EC_LOG_RAW("      Tx bytes:    %llu\n", netdev_stats.tx_bytes);
+        EC_LOG_RAW("      Rx frames:   %llu\n", netdev_stats.rx_count);
+        EC_LOG_RAW("      Rx bytes:    %llu\n", netdev_stats.rx_bytes);
+        EC_LOG_RAW("      Tx errors:   %llu\n", netdev_stats.tx_errors);
+
+        lost = netdev_stats.loss_count;
+        if (lost == 1)
+            lost = 0;
+        EC_LOG_RAW("      Lost frames: %llu\n", lost);
 
         EC_LOG_RAW("      Tx frame rate [1/s]: ");
         for (j = 0; j < EC_RATE_COUNT; j++) {
-            EC_LOG_RAW("%*.*f", colwidth, 0, master->netdev[dev_idx]->tx_frame_rates[j] / 1000.0);
+            EC_LOG_RAW("%*.*f", colwidth, 0, netdev_stats.tx_frame_rates[j] / 1000.0);
             if (j < EC_RATE_COUNT - 1)
                 EC_LOG_RAW(" ");
         }
         EC_LOG_RAW("\n      Tx rate [KByte/s]:   ");
         for (j = 0; j < EC_RATE_COUNT; j++) {
-            EC_LOG_RAW("%*.*f", colwidth, 1, master->netdev[dev_idx]->tx_byte_rates[j] / 1024.0);
+            EC_LOG_RAW("%*.*f", colwidth, 1, netdev_stats.tx_byte_rates[j] / 1024.0);
             if (j < EC_RATE_COUNT - 1)
                 EC_LOG_RAW(" ");
         }
         EC_LOG_RAW("\n      Rx frame rate [1/s]: ");
         for (j = 0; j < EC_RATE_COUNT; j++) {
-            EC_LOG_RAW("%*.*f", colwidth, 0, master->netdev[dev_idx]->rx_frame_rates[j] / 1000.0);
+            EC_LOG_RAW("%*.*f", colwidth, 0, netdev_stats.rx_frame_rates[j] / 1000.0);
             if (j < EC_RATE_COUNT - 1)
                 EC_LOG_RAW(" ");
         }
         EC_LOG_RAW("\n      Rx rate [KByte/s]:   ");
         for (j = 0; j < EC_RATE_COUNT; j++) {
-            EC_LOG_RAW("%*.*f", colwidth, 1, master->netdev[dev_idx]->rx_byte_rates[j] / 1024.0);
+            EC_LOG_RAW("%*.*f", colwidth, 1, netdev_stats.rx_byte_rates[j] / 1024.0);
             if (j < EC_RATE_COUNT - 1)
                 EC_LOG_RAW(" ");
         }
-        EC_LOG_RAW("\n");
-    }
 
-    lost = master->netdev_stats.tx_count - master->netdev_stats.rx_count;
-    if (lost == 1)
-        lost = 0;
-    EC_LOG_RAW("    Common:\n");
-    EC_LOG_RAW("      Tx frames:   %llu\n", master->netdev_stats.tx_count);
-    EC_LOG_RAW("      Tx bytes:    %llu\n", master->netdev_stats.tx_bytes);
-    EC_LOG_RAW("      Rx frames:   %llu\n", master->netdev_stats.rx_count);
-    EC_LOG_RAW("      Rx bytes:    %llu\n", master->netdev_stats.rx_bytes);
-    EC_LOG_RAW("      Lost frames: %llu\n", lost);
-
-    EC_LOG_RAW("      Tx frame rate [1/s]: ");
-    for (j = 0; j < EC_RATE_COUNT; j++) {
-        EC_LOG_RAW("%*.*f", colwidth, 0, master->netdev_stats.tx_frame_rates[j] / 1000.0);
-        if (j < EC_RATE_COUNT - 1)
-            EC_LOG_RAW(" ");
-    }
-    EC_LOG_RAW("\n      Tx rate [KByte/s]:   ");
-    for (j = 0; j < EC_RATE_COUNT; j++) {
-        EC_LOG_RAW("%*.*f", colwidth, 1, master->netdev_stats.tx_byte_rates[j] / 1024.0);
-        if (j < EC_RATE_COUNT - 1)
-            EC_LOG_RAW(" ");
-    }
-    EC_LOG_RAW("\n      Rx frame rate [1/s]: ");
-    for (j = 0; j < EC_RATE_COUNT; j++) {
-        EC_LOG_RAW("%*.*f", colwidth, 0, master->netdev_stats.rx_frame_rates[j] / 1000.0);
-        if (j < EC_RATE_COUNT - 1)
-            EC_LOG_RAW(" ");
-    }
-    EC_LOG_RAW("\n      Rx rate [KByte/s]:   ");
-    for (j = 0; j < EC_RATE_COUNT; j++) {
-        EC_LOG_RAW("%*.*f", colwidth, 1, master->netdev_stats.rx_byte_rates[j] / 1024.0);
-        if (j < EC_RATE_COUNT - 1)
-            EC_LOG_RAW(" ");
-    }
-    EC_LOG_RAW("\n      Loss rate [1/s]:     ");
-    for (j = 0; j < EC_RATE_COUNT; j++) {
-        EC_LOG_RAW("%*.*f", colwidth, 0, master->netdev_stats.loss_rates[j] / 1000.0);
-        if (j < EC_RATE_COUNT - 1)
-            EC_LOG_RAW(" ");
-    }
-    EC_LOG_RAW("\n      Frame loss [%%]:      ");
-    for (j = 0; j < EC_RATE_COUNT; j++) {
-        perc = 0.0;
-        if (master->netdev_stats.tx_frame_rates[j])
-            perc = 100.0 * master->netdev_stats.loss_rates[j] / master->netdev_stats.tx_frame_rates[j];
-        EC_LOG_RAW("%*.*f", colwidth, 1, perc);
-        if (j < EC_RATE_COUNT - 1)
-            EC_LOG_RAW(" ");
+        EC_LOG_RAW("\n      Loss rate [1/s]:     ");
+        for (j = 0; j < EC_RATE_COUNT; j++) {
+            EC_LOG_RAW("%*.*f", colwidth, 0, netdev_stats.loss_rates[j] / 1000.0);
+            if (j < EC_RATE_COUNT - 1)
+                EC_LOG_RAW(" ");
+        }
+
+        EC_LOG_RAW("\n");
     }
-    EC_LOG_RAW("\n");
 }
 
 static void ec_cmd_show_slave_detail(ec_master_t *master, uint32_t slave_idx)
@@ -222,8 +190,8 @@ static void ec_cmd_show_slave_detail(ec_master_t *master, uint32_t slave_idx)
 
     EC_LOG_RAW("=== Master %d, Slave %d ===\n", master->index, slave_idx);
 
-    if (slave_data.effective_alias != 0) {
-        EC_LOG_RAW("Alias: 0x%04x\n", slave_data.effective_alias);
+    if (slave_data.alias_address != 0) {
+        EC_LOG_RAW("Alias: 0x%04x\n", slave_data.alias_address);
     }
 
     EC_LOG_RAW("Device: %s\n", master->netdev[slave->netdev_idx]->name);

+ 24 - 105
src/ec_master.c

@@ -9,84 +9,6 @@
 
 static void ec_master_period_process(void *arg);
 
-/** List of intervals for statistics [s].
- */
-const unsigned int rate_intervals[] = {
-    1, 10, 60
-};
-
-EC_FAST_CODE_SECTION static void ec_master_update_netdev_stats(ec_master_t *master)
-{
-    ec_netdev_stats_t *s = &master->netdev_stats;
-    int32_t tx_frame_rate, rx_frame_rate, tx_byte_rate, rx_byte_rate, loss_rate;
-    uint64_t loss;
-    unsigned int i, netdev_idx;
-
-    // frame statistics
-    if ((jiffies - s->last_jiffies) < 1000000) {
-        return;
-    }
-
-    tx_frame_rate = (s->tx_count - s->last_tx_count) * 1000;
-    rx_frame_rate = (s->rx_count - s->last_rx_count) * 1000;
-    tx_byte_rate = s->tx_bytes - s->last_tx_bytes;
-    rx_byte_rate = s->rx_bytes - s->last_rx_bytes;
-    loss = s->tx_count - s->rx_count;
-    loss_rate = (loss - s->last_loss) * 1000;
-
-    /* Low-pass filter:
-     *      Y_n = y_(n - 1) + T / tau * (x - y_(n - 1))   | T = 1
-     *   -> Y_n += (x - y_(n - 1)) / tau
-     */
-    for (i = 0; i < EC_RATE_COUNT; i++) {
-        int32_t n = rate_intervals[i];
-        s->tx_frame_rates[i] += (tx_frame_rate - s->tx_frame_rates[i]) / n;
-        s->rx_frame_rates[i] += (rx_frame_rate - s->rx_frame_rates[i]) / n;
-        s->tx_byte_rates[i] += (tx_byte_rate - s->tx_byte_rates[i]) / n;
-        s->rx_byte_rates[i] += (rx_byte_rate - s->rx_byte_rates[i]) / n;
-        s->loss_rates[i] += (loss_rate - s->loss_rates[i]) / n;
-    }
-
-    s->last_tx_count = s->tx_count;
-    s->last_rx_count = s->rx_count;
-    s->last_tx_bytes = s->tx_bytes;
-    s->last_rx_bytes = s->rx_bytes;
-    s->last_loss = loss;
-
-    for (netdev_idx = EC_NETDEV_MAIN; netdev_idx < CONFIG_EC_MAX_NETDEVS;
-         netdev_idx++) {
-        ec_netdev_update_stats(master->netdev[netdev_idx]);
-    }
-
-    s->last_jiffies = jiffies;
-}
-
-EC_FAST_CODE_SECTION static void ec_master_clear_netdev_stats(ec_master_t *master)
-{
-    unsigned int i;
-
-    // zero frame statistics
-    master->netdev_stats.tx_count = 0;
-    master->netdev_stats.last_tx_count = 0;
-    master->netdev_stats.rx_count = 0;
-    master->netdev_stats.last_rx_count = 0;
-    master->netdev_stats.tx_bytes = 0;
-    master->netdev_stats.last_tx_bytes = 0;
-    master->netdev_stats.rx_bytes = 0;
-    master->netdev_stats.last_rx_bytes = 0;
-    master->netdev_stats.last_loss = 0;
-
-    for (i = 0; i < EC_RATE_COUNT; i++) {
-        master->netdev_stats.tx_frame_rates[i] = 0;
-        master->netdev_stats.rx_frame_rates[i] = 0;
-        master->netdev_stats.tx_byte_rates[i] = 0;
-        master->netdev_stats.rx_byte_rates[i] = 0;
-        master->netdev_stats.loss_rates[i] = 0;
-    }
-
-    master->netdev_stats.last_jiffies = 0;
-}
-
 EC_FAST_CODE_SECTION static void ec_master_queue_datagram(ec_master_t *master, ec_datagram_t *datagram)
 {
     ec_datagram_t *queued_datagram;
@@ -113,7 +35,7 @@ EC_FAST_CODE_SECTION static void ec_master_unqueue_datagram(ec_master_t *master,
     }
 }
 
-EC_FAST_CODE_SECTION static void ec_master_send_datagrams(ec_master_t *master, ec_netdev_index_t netdev_idx)
+EC_FAST_CODE_SECTION static void ec_master_send_datagrams(ec_master_t *master, uint8_t netdev_idx)
 {
     ec_datagram_t *datagram, *next;
     size_t datagram_size;
@@ -223,16 +145,17 @@ EC_FAST_CODE_SECTION static void ec_master_send_datagrams(ec_master_t *master, e
 }
 
 EC_FAST_CODE_SECTION void ec_master_receive_datagrams(ec_master_t *master,
-                                                      ec_netdev_index_t netdev_idx,
+                                                      uint8_t netdev_idx,
                                                       const uint8_t *frame_data,
                                                       size_t size)
 {
     size_t frame_size, data_size;
     uint8_t datagram_type, datagram_index;
-    unsigned int cmd_follows, matched;
+    uint32_t cmd_follows, matched;
     const uint8_t *cur_data;
-    unsigned int datagram_count;
+    uint32_t datagram_count;
     ec_datagram_t *datagram;
+    uint64_t start_time;
 
     if (size < EC_FRAME_HEADER_SIZE) {
         EC_LOG_ERR("Corrupted frame received on %s (size %u < %u byte)\n",
@@ -254,9 +177,8 @@ EC_FAST_CODE_SECTION void ec_master_receive_datagrams(ec_master_t *master,
         return;
     }
 
-#ifdef CONFIG_EC_CAL_RX_TIME
-    uint64_t cycles_start = jiffies;
-#endif
+    start_time = jiffies;
+
     datagram_count = 0;
     cmd_follows = 1;
     while (cmd_follows) {
@@ -317,24 +239,23 @@ EC_FAST_CODE_SECTION void ec_master_receive_datagrams(ec_master_t *master,
 
         // dequeue the received datagram
         datagram->state = EC_DATAGRAM_RECEIVED;
-
-        datagram->jiffies_received = master->netdev[EC_NETDEV_MAIN]->jiffies_poll;
+        datagram->jiffies_received = jiffies - start_time;
         ec_master_unqueue_datagram(master, datagram);
 
         datagram_count++;
     }
-#ifdef CONFIG_EC_CAL_RX_TIME
-    EC_LOG_INFO("Recv %u datagrams in %uus.\n", datagram_count, (unsigned int)(jiffies - cycles_start));
-#endif
 }
 
 EC_FAST_CODE_SECTION static void ec_master_send(ec_master_t *master)
 {
     ec_datagram_t *datagram, *n;
-    ec_netdev_index_t netdev_idx;
+    uint8_t netdev_idx;
 
     // update netdev statistics
-    ec_master_update_netdev_stats(master);
+    for (netdev_idx = EC_NETDEV_MAIN; netdev_idx < CONFIG_EC_MAX_NETDEVS;
+         netdev_idx++) {
+        ec_netdev_update_stats(master->netdev[netdev_idx]);
+    }
 
     // dequeue all datagrams that timed out
     ec_dlist_for_each_entry_safe(datagram, n, &master->datagram_queue, queue)
@@ -365,7 +286,7 @@ EC_FAST_CODE_SECTION static void ec_master_send(ec_master_t *master)
             }
 
             // clear frame statistics
-            ec_netdev_clear_stats(master->netdev[netdev_idx]);
+            memset(&master->netdev[netdev_idx]->stats, 0, sizeof(ec_netdev_stats_t));
             continue;
         }
 
@@ -377,7 +298,7 @@ EC_FAST_CODE_SECTION static void ec_master_send(ec_master_t *master)
 static void ec_netdev_linkpoll_timer(void *argument)
 {
     ec_master_t *master = (ec_master_t *)argument;
-    ec_netdev_index_t netdev_idx;
+    uint8_t netdev_idx;
 
     for (netdev_idx = EC_NETDEV_MAIN; netdev_idx < CONFIG_EC_MAX_NETDEVS; netdev_idx++) {
         ec_netdev_poll_link_state(master->netdev[netdev_idx]);
@@ -429,7 +350,7 @@ static void ec_master_scan_thread(void *argument)
 
 int ec_master_init(ec_master_t *master, uint8_t master_index)
 {
-    ec_netdev_index_t netdev_idx;
+    uint8_t netdev_idx;
 
     memset(master, 0, sizeof(ec_master_t));
     master->index = master_index;
@@ -448,8 +369,6 @@ int ec_master_init(ec_master_t *master, uint8_t master_index)
         master->netdev[netdev_idx]->master = master;
     }
 
-    ec_master_clear_netdev_stats(master);
-
     ec_datagram_init(&master->main_datagram, EC_MAX_DATA_SIZE);
     ec_datagram_init(&master->dc_ref_sync_datagram, 8);
     ec_datagram_init(&master->dc_all_sync_datagram, 8);
@@ -498,13 +417,13 @@ int ec_master_start(ec_master_t *master)
     ec_slave_t *slave;
     uint32_t bitlen;
     bool used[2] = { false, false };
-    ec_netdev_index_t netdev_idx;
+    uint8_t netdev_idx;
     uint8_t sm_idx;
 
     EC_ASSERT_MSG(master->cycle_time >= (40 * 1000), "Cycle time %u ns is too small. Minimum is 40000 ns.\n", master->cycle_time);
     EC_ASSERT_MSG(master->cycle_time >= master->shift_time, "Shift time %u ns is larger than cycle time %u ns.\n", master->shift_time, master->cycle_time);
 
-    if (master->active) {
+    if (master->started) {
         return 0;
     }
 
@@ -636,7 +555,7 @@ int ec_master_start(ec_master_t *master)
         master->slaves[i].alstatus_code = 0;
         master->slaves[i].force_update = true;
     }
-    master->active = true;
+    master->started = true;
 
     ec_osal_mutex_give(master->scan_lock);
     return 0;
@@ -645,14 +564,14 @@ int ec_master_start(ec_master_t *master)
 int ec_master_stop(ec_master_t *master)
 {
     ec_pdo_datagram_t *pdo_datagram, *n;
-    ec_netdev_index_t netdev_idx;
+    uint8_t netdev_idx;
 
-    if (!master->active) {
+    if (!master->started) {
         return 0;
     }
 
     ec_osal_mutex_take(master->scan_lock);
-    master->active = false;
+    master->started = false;
 
     for (uint32_t i = 0; i < master->slave_count; i++) {
         master->slaves[i].requested_state = EC_SLAVE_STATE_PREOP;
@@ -837,7 +756,7 @@ EC_FAST_CODE_SECTION static void ec_master_period_process(void *arg)
 {
     ec_master_t *master = (ec_master_t *)arg;
     ec_pdo_datagram_t *pdo_datagram, *n;
-    ec_netdev_index_t netdev_idx;
+    uint8_t netdev_idx;
     uint64_t dc_ref_systime = 0;
     int32_t offsettime = 0;
     uint32_t delta = 0;
@@ -865,7 +784,7 @@ EC_FAST_CODE_SECTION static void ec_master_period_process(void *arg)
                 }
 
                 if (delta > 0) {
-                    ec_htimer_update((master->cycle_time + offsettime) / 1000);
+                    ec_htimer_update((master->cycle_time / 1000 + offsettime / 1000));
                 }
             }
         } else {

+ 32 - 49
src/ec_netdev.c

@@ -6,7 +6,7 @@
 #include "ec_master.h"
 
 extern void ec_master_receive_datagrams(ec_master_t *master,
-                                        ec_netdev_index_t netdev_index,
+                                        uint8_t netdev_index,
                                         const uint8_t *frame_data,
                                         size_t size);
 
@@ -16,37 +16,20 @@ const unsigned int netdev_rate_intervals[] = {
     1, 10, 60
 };
 
-EC_FAST_CODE_SECTION void ec_netdev_clear_stats(ec_netdev_t *netdev)
+EC_FAST_CODE_SECTION void ec_netdev_update_stats(ec_netdev_t *netdev)
 {
     unsigned int i;
 
-    // zero frame statistics
-    netdev->tx_count = 0;
-    netdev->last_tx_count = 0;
-    netdev->rx_count = 0;
-    netdev->last_rx_count = 0;
-    netdev->tx_bytes = 0;
-    netdev->last_tx_bytes = 0;
-    netdev->rx_bytes = 0;
-    netdev->last_rx_bytes = 0;
-    netdev->tx_errors = 0;
-
-    for (i = 0; i < EC_RATE_COUNT; i++) {
-        netdev->tx_frame_rates[i] = 0;
-        netdev->rx_frame_rates[i] = 0;
-        netdev->tx_byte_rates[i] = 0;
-        netdev->rx_byte_rates[i] = 0;
+    if ((jiffies - netdev->stats.last_jiffies) < 1000000) {
+        return;
     }
-}
-
-EC_FAST_CODE_SECTION void ec_netdev_update_stats(ec_netdev_t *netdev)
-{
-    unsigned int i;
 
-    int32_t tx_frame_rate = (netdev->tx_count - netdev->last_tx_count) * 1000;
-    int32_t rx_frame_rate = (netdev->rx_count - netdev->last_rx_count) * 1000;
-    int32_t tx_byte_rate = (netdev->tx_bytes - netdev->last_tx_bytes);
-    int32_t rx_byte_rate = (netdev->rx_bytes - netdev->last_rx_bytes);
+    int32_t tx_frame_rate = (netdev->stats.tx_count - netdev->stats.last_tx_count) * 1000;
+    int32_t rx_frame_rate = (netdev->stats.rx_count - netdev->stats.last_rx_count) * 1000;
+    int32_t tx_byte_rate = (netdev->stats.tx_bytes - netdev->stats.last_tx_bytes);
+    int32_t rx_byte_rate = (netdev->stats.rx_bytes - netdev->stats.last_rx_bytes);
+    int32_t loss = netdev->stats.tx_count - netdev->stats.rx_count;
+    int32_t loss_rate = (loss - netdev->stats.loss_count) * 1000;
 
     /* Low-pass filter:
      *      Y_n = y_(n - 1) + T / tau * (x - y_(n - 1))   | T = 1
@@ -54,20 +37,24 @@ EC_FAST_CODE_SECTION void ec_netdev_update_stats(ec_netdev_t *netdev)
      */
     for (i = 0; i < EC_RATE_COUNT; i++) {
         int32_t n = netdev_rate_intervals[i];
-        netdev->tx_frame_rates[i] +=
-            (tx_frame_rate - netdev->tx_frame_rates[i]) / n;
-        netdev->rx_frame_rates[i] +=
-            (rx_frame_rate - netdev->rx_frame_rates[i]) / n;
-        netdev->tx_byte_rates[i] +=
-            (tx_byte_rate - netdev->tx_byte_rates[i]) / n;
-        netdev->rx_byte_rates[i] +=
-            (rx_byte_rate - netdev->rx_byte_rates[i]) / n;
+        netdev->stats.tx_frame_rates[i] +=
+            (tx_frame_rate - netdev->stats.tx_frame_rates[i]) / n;
+        netdev->stats.rx_frame_rates[i] +=
+            (rx_frame_rate - netdev->stats.rx_frame_rates[i]) / n;
+        netdev->stats.tx_byte_rates[i] +=
+            (tx_byte_rate - netdev->stats.tx_byte_rates[i]) / n;
+        netdev->stats.rx_byte_rates[i] +=
+            (rx_byte_rate - netdev->stats.rx_byte_rates[i]) / n;
+        netdev->stats.loss_rates[i] +=
+            (loss_rate - netdev->stats.loss_rates[i]) / n;
     }
 
-    netdev->last_tx_count = netdev->tx_count;
-    netdev->last_rx_count = netdev->rx_count;
-    netdev->last_tx_bytes = netdev->tx_bytes;
-    netdev->last_rx_bytes = netdev->rx_bytes;
+    netdev->stats.last_tx_count = netdev->stats.tx_count;
+    netdev->stats.last_rx_count = netdev->stats.rx_count;
+    netdev->stats.last_tx_bytes = netdev->stats.tx_bytes;
+    netdev->stats.last_rx_bytes = netdev->stats.rx_bytes;
+    netdev->stats.loss_count = loss;
+    netdev->stats.last_jiffies = jiffies;
 }
 
 ec_netdev_t *ec_netdev_init(uint8_t netdev_index)
@@ -76,7 +63,7 @@ ec_netdev_t *ec_netdev_init(uint8_t netdev_index)
 
     netdev = ec_netdev_low_level_init(netdev_index);
     if (netdev) {
-        ec_netdev_clear_stats(netdev);
+        memset(&netdev->stats, 0, sizeof(ec_netdev_stats_t));
         netdev->index = netdev_index;
         netdev->tx_frame_index = 0;
         netdev->link_state = false;
@@ -139,14 +126,12 @@ EC_FAST_CODE_SECTION uint8_t *ec_netdev_get_txbuf(ec_netdev_t *netdev)
 EC_FAST_CODE_SECTION int ec_netdev_send(ec_netdev_t *netdev, uint32_t size)
 {
     if (ec_netdev_low_level_output(netdev, size + ETH_HLEN) == 0) {
-        netdev->tx_count++;
-        netdev->master->netdev_stats.tx_count++;
-        netdev->tx_bytes += ETH_HLEN + size;
-        netdev->master->netdev_stats.tx_bytes += ETH_HLEN + size;
+        netdev->stats.tx_count++;
+        netdev->stats.tx_bytes += ETH_HLEN + size;
 
         return 0;
     } else {
-        netdev->tx_errors++;
+        netdev->stats.tx_errors++;
         return -1;
     }
 }
@@ -156,10 +141,8 @@ EC_FAST_CODE_SECTION void ec_netdev_receive(ec_netdev_t *netdev, uint8_t *frame,
     const uint8_t *ec_data = frame + ETH_HLEN;
     uint32_t ec_size = size - ETH_HLEN;
 
-    netdev->rx_count++;
-    netdev->master->netdev_stats.rx_count++;
-    netdev->rx_bytes += size;
-    netdev->master->netdev_stats.rx_bytes += size;
+    netdev->stats.rx_count++;
+    netdev->stats.rx_bytes += size;
 
     ec_master_receive_datagrams(netdev->master, netdev->index, ec_data, ec_size);
 }

+ 17 - 21
src/ec_slave.c

@@ -23,7 +23,7 @@
 static void ec_slave_init(ec_slave_t *slave,
                           uint32_t slave_index,
                           ec_master_t *master,
-                          ec_netdev_index_t netdev_idx,
+                          uint8_t netdev_idx,
                           uint16_t autoinc_address,
                           uint16_t station_address)
 {
@@ -996,7 +996,7 @@ void ec_slaves_scanning(ec_master_t *master)
 {
     ec_datagram_t *datagram;
     ec_slave_t *slave;
-    ec_netdev_index_t netdev_idx;
+    uint8_t netdev_idx;
     bool rescan_required = false;
     unsigned int scan_jiffies;
     int ret;
@@ -1020,7 +1020,7 @@ void ec_slaves_scanning(ec_master_t *master)
 
             for (uint8_t i = EC_NETDEV_MAIN; i < CONFIG_EC_MAX_NETDEVS; i++) {
                 master->slaves_state[i] = 0x00;
-                master->slaves_responding[i] = 0;
+                master->slaves_working_counter[i] = 0;
             }
             master->scan_done = false;
             ec_osal_mutex_give(master->scan_lock);
@@ -1037,15 +1037,15 @@ void ec_slaves_scanning(ec_master_t *master)
             return;
         }
 
-        if (datagram->working_counter != master->slaves_responding[netdev_idx]) {
+        if (datagram->working_counter != master->slaves_working_counter[netdev_idx]) {
             rescan_required = 1;
-            master->slaves_responding[netdev_idx] = datagram->working_counter;
+            master->slaves_working_counter[netdev_idx] = datagram->working_counter;
             EC_LOG_INFO("%u slaves responding on %s device\n",
-                        master->slaves_responding[netdev_idx],
+                        master->slaves_working_counter[netdev_idx],
                         master->netdev[netdev_idx]->name);
         }
 
-        if (master->slaves_responding[netdev_idx] > 0) {
+        if (master->slaves_working_counter[netdev_idx] > 0) {
             uint8_t states = EC_READ_U8(datagram->data);
             if (states != master->slaves_state[netdev_idx]) {
                 // slave states changed
@@ -1077,7 +1077,7 @@ void ec_slaves_scanning(ec_master_t *master)
         scan_jiffies = jiffies;
 
         for (uint8_t i = EC_NETDEV_MAIN; i < CONFIG_EC_MAX_NETDEVS; i++) {
-            count += master->slaves_responding[i];
+            count += master->slaves_working_counter[i];
         }
 
         if (!count) {
@@ -1097,7 +1097,7 @@ void ec_slaves_scanning(ec_master_t *master)
         slave_index = 0;
         for (uint8_t netdev_idx = EC_NETDEV_MAIN; netdev_idx < CONFIG_EC_MAX_NETDEVS; netdev_idx++) {
             autoinc_address = 0;
-            for (uint32_t j = 0; j < master->slaves_responding[netdev_idx]; j++) {
+            for (uint32_t j = 0; j < master->slaves_working_counter[netdev_idx]; j++) {
                 slave = master->slaves + slave_index;
 
                 ec_slave_init(slave, slave_index, master, netdev_idx, (int16_t)autoinc_address * (-1), slave_index + 1001);
@@ -1108,7 +1108,7 @@ void ec_slaves_scanning(ec_master_t *master)
         }
 
         for (uint8_t netdev_idx = EC_NETDEV_MAIN; netdev_idx < CONFIG_EC_MAX_NETDEVS; netdev_idx++) {
-            if (master->slaves_responding[netdev_idx] == 0) {
+            if (master->slaves_working_counter[netdev_idx] == 0) {
                 continue;
             }
             // Clear station address
@@ -1172,18 +1172,14 @@ void ec_slaves_scanning(ec_master_t *master)
             slave->base_build = EC_READ_U16(datagram->data + 2);
 
             slave->base_fmmu_count = EC_READ_U8(datagram->data + 4);
-            if (slave->base_fmmu_count > EC_MAX_FMMUS) {
-                EC_SLAVE_LOG_WRN("Slave has more FMMUs (%u) than the master can handle (%u)\n",
-                                 slave->base_fmmu_count, EC_MAX_FMMUS);
-                slave->base_fmmu_count = EC_MAX_FMMUS;
-            }
+            EC_ASSERT_MSG(slave->base_fmmu_count <= EC_MAX_FMMUS,
+                          "Slave %u FMMU count %u is overflow\n",
+                          slave->index, slave->base_fmmu_count);
 
             slave->base_sync_count = EC_READ_U8(datagram->data + 5);
-            if (slave->base_sync_count > EC_MAX_SYNC_MANAGERS) {
-                EC_SLAVE_LOG_WRN("Slave provides more sync managers (%u) than the master can handle (%u)\n",
-                                 slave->base_sync_count, EC_MAX_SYNC_MANAGERS);
-                slave->base_sync_count = EC_MAX_SYNC_MANAGERS;
-            }
+            EC_ASSERT_MSG(slave->base_sync_count <= EC_MAX_SYNC_MANAGERS,
+                          "Slave %u sync managers count %u is overflow\n",
+                          slave->index, slave->base_fmmu_count);
 
             uint8_t data = EC_READ_U8(datagram->data + 7);
             for (uint8_t i = 0; i < EC_MAX_PORTS; i++) {
@@ -1290,7 +1286,7 @@ void ec_slaves_scanning(ec_master_t *master)
 
             slave->sii.aliasaddr =
                 EC_READ_U16(slave->sii_image + 0x0004);
-            slave->effective_alias = slave->sii.aliasaddr;
+            slave->alias_address = slave->sii.aliasaddr;
             slave->sii.vendor_id =
                 EC_READ_U32(slave->sii_image + 0x0008);
             slave->sii.product_code =