From 50b3085270dbbda95bb39967c0ec5f877eed3067 Mon Sep 17 00:00:00 2001
From: Florian Pose <fp@igh-essen.com>
Date: Fri, 22 Feb 2008 17:23:05 +0000
Subject: [PATCH] Calculate expected working counter for domains.

---
 TODO                 |   1 -
 examples/mini/mini.c | 109 ++++++++++++++++++++++++-------------------
 master/domain.c      |  58 +++++++++++++++++------
 master/domain.h      |   3 ++
 master/fmmu_config.c |   4 +-
 master/fmmu_config.h |   7 ++-
 master/pdo_mapping.h |   1 +
 7 files changed, 115 insertions(+), 68 deletions(-)

diff --git a/TODO b/TODO
index ca3a96eb..01bb9f20 100644
--- a/TODO
+++ b/TODO
@@ -19,7 +19,6 @@ Version 1.4.0:
   applications.
 * Update documentation.
 * READMEs for examples.
-* Calculate expected working counter for domains.
 * Distributed clocks.
 
 Future issues:
diff --git a/examples/mini/mini.c b/examples/mini/mini.c
index 7a296312..614c13ec 100644
--- a/examples/mini/mini.c
+++ b/examples/mini/mini.c
@@ -43,9 +43,7 @@
 
 #define FREQUENCY 100
 
-//#define KBUS
-#define PDOS
-#define MAPPING
+#define CONFIGURE_MAPPING
 #define EXTERNAL_MEMORY
 
 /*****************************************************************************/
@@ -54,17 +52,13 @@ static struct timer_list timer;
 
 // EtherCAT
 static ec_master_t *master = NULL;
-static ec_domain_t *domain1 = NULL;
+static ec_master_state_t master_state = {};
 spinlock_t master_lock = SPIN_LOCK_UNLOCKED;
-static ec_master_state_t master_state, old_state = {};
 
-// data fields
-#ifdef KBUS
-static void *r_inputs;
-static void *r_outputs;
-#endif
+static ec_domain_t *domain1 = NULL;
+static ec_domain_state_t domain1_state = {};
 
-#ifdef MAPPING
+#ifdef CONFIGURE_MAPPING
 const ec_pdo_entry_info_t el3162_channel1[] = {
     {0x3101, 1,  8}, // status
     {0x3101, 2, 16}  // value
@@ -95,7 +89,6 @@ const ec_pdo_info_t el2004_mapping[] = {
 };
 #endif
 
-#ifdef PDOS
 static uint8_t *pd; /**< Process data. */
 static unsigned int off_ana_in;
 static unsigned int off_dig_out;
@@ -105,7 +98,49 @@ const static ec_pdo_entry_reg_t domain1_regs[] = {
     {0, 3, Beckhoff_EL2004, 0x3001, 1, &off_dig_out},
     {}
 };
-#endif
+
+/*****************************************************************************/
+
+void check_domain1_state(void)
+{
+    ec_domain_state_t ds;
+
+    ecrt_domain_state(domain1, &ds);
+    if (ds.working_counter != domain1_state.working_counter)
+        printk(KERN_INFO PFX "domain1 working_counter changed to %u.\n",
+                ds.working_counter);
+
+    if (ds.wc_state != domain1_state.wc_state)
+        printk(KERN_INFO PFX "domain1 wc_state changed to %u.\n",
+                ds.wc_state);
+
+    domain1_state = ds;
+}
+
+/*****************************************************************************/
+
+void check_master_state(void)
+{
+    ec_master_state_t ms;
+
+    spin_lock(&master_lock);
+    ecrt_master_state(master, &ms);
+    spin_unlock(&master_lock);
+
+    if (ms.bus_state != master_state.bus_state) {
+        printk(KERN_INFO PFX "bus state changed to %i.\n", ms.bus_state);
+    }
+    if (ms.bus_tainted != master_state.bus_tainted) {
+        printk(KERN_INFO PFX "tainted flag changed to %u.\n",
+                ms.bus_tainted);
+    }
+    if (ms.slaves_responding != master_state.slaves_responding) {
+        printk(KERN_INFO PFX "slaves_responding changed to %u.\n",
+                ms.slaves_responding);
+    }
+
+    master_state = ms;
+}
 
 /*****************************************************************************/
 
@@ -114,53 +149,33 @@ void run(unsigned long data)
     static unsigned int counter = 0;
     static unsigned int blink = 0;
 
-    // receive
+    // receive process data
     spin_lock(&master_lock);
     ecrt_master_receive(master);
     ecrt_domain_process(domain1);
     spin_unlock(&master_lock);
 
-    // process data
-    EC_WRITE_U8(pd + off_dig_out, blink ? 0x0F : 0x00);
+    // check process data state (optional)
+    check_domain1_state();
 
     if (counter) {
         counter--;
-    }
-    else {
+    } else { // do this at FREQUENCY
         counter = FREQUENCY;
-        blink = !blink;
 
-        spin_lock(&master_lock);
-        ecrt_master_state(master, &master_state);
-        spin_unlock(&master_lock);
+        // calculate new process data
+        blink = !blink;
 
-        if (master_state.bus_state != old_state.bus_state) {
-            printk(KERN_INFO PFX "bus state changed to %i.\n",
-                    master_state.bus_state);
-        }
-        if (master_state.bus_tainted != old_state.bus_tainted) {
-            printk(KERN_INFO PFX "tainted flag changed to %u.\n",
-                    master_state.bus_tainted);
-        }
-        if (master_state.slaves_responding !=
-                old_state.slaves_responding) {
-            printk(KERN_INFO PFX "slaves_responding changed to %u.\n",
-                    master_state.slaves_responding);
-        }
-       
-        old_state = master_state;
+        // check for master state (optional)
+        check_master_state();
     }
 
-#ifdef KBUS
-    EC_WRITE_U8(r_outputs + 2, blink ? 0xFF : 0x00);
-#endif
+    // write process data
+    EC_WRITE_U8(pd + off_dig_out, blink ? 0x0F : 0x00);
 
-    // send
+    // send process data
     spin_lock(&master_lock);
     ecrt_domain_queue(domain1);
-    spin_unlock(&master_lock);
-
-    spin_lock(&master_lock);
     ecrt_master_send(master);
     spin_unlock(&master_lock);
 
@@ -188,7 +203,7 @@ void release_lock(void *data)
 
 int __init init_mini_module(void)
 {
-#ifdef MAPPING
+#ifdef CONFIGURE_MAPPING
     ec_slave_config_t *sc;
 #endif
 #ifdef EXTERNAL_MEMORY
@@ -210,7 +225,7 @@ int __init init_mini_module(void)
         goto out_release_master;
     }
 
-#ifdef MAPPING
+#ifdef CONFIGURE_MAPPING
     printk(KERN_INFO PFX "Configuring Pdo mapping...\n");
     if (!(sc = ecrt_master_slave_config(master, 0, 1, Beckhoff_EL3162))) {
         printk(KERN_ERR PFX "Failed to get slave configuration.\n");
@@ -234,12 +249,10 @@ int __init init_mini_module(void)
 #endif
 
     printk(KERN_INFO PFX "Registering Pdo entries...\n");
-#ifdef PDOS
     if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
         printk(KERN_ERR PFX "Pdo entry registration failed!\n");
         goto out_release_master;
     }
-#endif
 
 #ifdef EXTERNAL_MEMORY
     if ((size = ecrt_domain_size(domain1))) {
diff --git a/master/domain.c b/master/domain.c
index 24b0a7ef..28475ac9 100644
--- a/master/domain.c
+++ b/master/domain.c
@@ -54,6 +54,14 @@ ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *);
 
 /*****************************************************************************/
 
+/** Working counter increment values for logical read/write operations.
+ *
+ * \attention This is indexed by ec_direction_t.
+ */
+static const unsigned int working_counter_increment[] = {2, 1};
+
+/*****************************************************************************/
+
 /** \cond */
 
 EC_SYSFS_READ_ATTR(image_size);
@@ -91,12 +99,14 @@ int ec_domain_init(
     domain->master = master;
     domain->index = index;
     domain->data_size = 0;
+    domain->expected_working_counter = 0;
     domain->data = NULL;
     domain->data_origin = EC_ORIG_INTERNAL;
     domain->logical_base_address = 0L;
     domain->working_counter = 0xFFFFFFFF;
-    domain->notify_jiffies = 0;
+    domain->state = 0;
     domain->working_counter_changes = 0;
+    domain->notify_jiffies = 0;
 
     INIT_LIST_HEAD(&domain->datagrams);
 
@@ -121,11 +131,10 @@ int ec_domain_init(
 
 /*****************************************************************************/
 
-/**
-   Domain destructor.
-   Clears and frees a domain object.
-*/
-
+/** Domain destructor.
+ *
+ * Clears and frees a domain object.
+ */
 void ec_domain_destroy(ec_domain_t *domain /**< EtherCAT domain */)
 {
     ec_datagram_t *datagram;
@@ -143,12 +152,11 @@ void ec_domain_destroy(ec_domain_t *domain /**< EtherCAT domain */)
 
 /*****************************************************************************/
 
-/**
-   Clear and free domain.
-   This method is called by the kobject,
-   once there are no more references to it.
-*/
-
+/** Clear and free domain.
+ *
+ * This method is called by the kobject, once there are no more references
+ * to it.
+ */
 void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
 {
     ec_domain_t *domain;
@@ -182,6 +190,21 @@ void ec_domain_clear_data(
 
 /*****************************************************************************/
 
+/** Adds an FMMU configuration to the domain.
+ */
+void ec_domain_add_fmmu_config(
+        ec_domain_t *domain, /**< EtherCAT domain. */
+        ec_fmmu_config_t *fmmu /**< FMMU configuration. */
+        )
+{
+    fmmu->domain = domain;
+
+    domain->data_size += fmmu->data_size;
+    domain->expected_working_counter += working_counter_increment[fmmu->dir];
+}
+
+/*****************************************************************************/
+
 /** Allocates a domain datagram and appends it to the list.
  *
  * \return 0 in case of success, else < 0
@@ -449,7 +472,16 @@ void ecrt_domain_queue(ec_domain_t *domain)
 void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
 {
     state->working_counter = domain->working_counter;
-    state->wc_state = EC_WC_ZERO; // FIXME
+
+    if (domain->working_counter) {
+        if (domain->working_counter == domain->expected_working_counter) {
+            state->wc_state = EC_WC_COMPLETE;
+        } else {
+            state->wc_state = EC_WC_INCOMPLETE;
+        }
+    } else {
+        state->wc_state = EC_WC_ZERO;
+    }
 }
 
 /*****************************************************************************/
diff --git a/master/domain.h b/master/domain.h
index ac7a8cbb..6f8b67cd 100644
--- a/master/domain.h
+++ b/master/domain.h
@@ -47,6 +47,7 @@
 #include "globals.h"
 #include "datagram.h"
 #include "master.h"
+#include "fmmu_config.h"
 
 /*****************************************************************************/
 
@@ -63,6 +64,7 @@ struct ec_domain
     ec_master_t *master; /**< EtherCAT master owning the domain. */
     unsigned int index; /**< Index (just a number). */
     size_t data_size; /**< Size of the process data. */
+    unsigned int expected_working_counter; /**< Expected working counter. */
     uint8_t *data; /**< Memory for the process data. */
     ec_origin_t data_origin; /**< Origin of the \a data memory. */
     struct list_head datagrams; /**< Datagrams for process data exchange. */
@@ -80,6 +82,7 @@ struct ec_domain
 int ec_domain_init(ec_domain_t *, ec_master_t *, unsigned int);
 void ec_domain_destroy(ec_domain_t *);
 
+void ec_domain_add_fmmu_config(ec_domain_t *, ec_fmmu_config_t *);
 int ec_domain_finish(ec_domain_t *, uint32_t);
 
 /*****************************************************************************/
diff --git a/master/fmmu_config.c b/master/fmmu_config.c
index 56ee0b69..fab308ca 100644
--- a/master/fmmu_config.c
+++ b/master/fmmu_config.c
@@ -59,12 +59,12 @@ void ec_fmmu_config_init(
         )
 {
     fmmu->sc = sc;
-    fmmu->domain = domain;
     fmmu->dir = dir;
 
     fmmu->logical_start_address = domain->data_size;
     fmmu->data_size = ec_pdo_mapping_total_size(&sc->mapping[dir]);
-    domain->data_size += fmmu->data_size;
+
+    ec_domain_add_fmmu_config(domain, fmmu);
 }
 
 /*****************************************************************************/
diff --git a/master/fmmu_config.h b/master/fmmu_config.h
index 8cf45a06..91cd13bf 100644
--- a/master/fmmu_config.h
+++ b/master/fmmu_config.h
@@ -43,21 +43,20 @@
 #include "../include/ecrt.h"
 
 #include "globals.h"
+#include "sync.h"
 
 /*****************************************************************************/
 
 /** FMMU configuration.
  */
-typedef struct
-{
+typedef struct {
     const ec_slave_config_t *sc; /**< EtherCAT slave config. */
     const ec_domain_t *domain; /**< Domain. */
     ec_direction_t dir; /**< Pdo direction. */
 
     uint32_t logical_start_address; /**< Logical start address. */
     unsigned int data_size; /**< Covered Pdo size. */
-}
-ec_fmmu_config_t;
+} ec_fmmu_config_t;
 
 /*****************************************************************************/
 
diff --git a/master/pdo_mapping.h b/master/pdo_mapping.h
index 1d1113ed..af2dc134 100644
--- a/master/pdo_mapping.h
+++ b/master/pdo_mapping.h
@@ -46,6 +46,7 @@
 #include "../include/ecrt.h"
 
 #include "globals.h"
+#include "pdo.h"
 
 /*****************************************************************************/
 
-- 
GitLab