Hi Gavin,

I have a gift for you. The attached patch should make your scenario with
different PDOs of interest in different apps working. The problem was that
the master always makes the last PDO assign in SyncManager as the default
PDO assign, and it don't remember any older PDO assignment. I made a patch
to get a memory for the PDO mappings, and it always merge the new PDO
mapping list into the old list, instead of throw the old list away. It
remembers things.

It is still not so smart like you said to fetch the PDO assign using their
index via CoE automatically. I don't know if it's a good idea for the
master to do it blindly. The question is when should the master fetch it.
If the master fetches all the PDO mappings during the bus scan, isn't that
a waste of time, because most of the time we don't need all of them? If
fetch it when needed, the master needs to call several
ecrt_master_sdo_upload() in the function ecrt_slave_config_pdos() to fetch
the mapping, which makes the code quite ugly. And actually the app can do
it itself, and then provides the correct default PDO mapping to the master.

Hope you enjoy it!

Regards,
Jun



On 22 April 2014 09:33, Gavin Lambert <gav...@compacsort.com> wrote:

> Hi all,
>
> TLDR: when reassigning PDOs, why doesn't the master read mappings from the
> slave via CoE?
>
> I have a (custom) slave that provides a number of different PDOs.  I have a
> couple of different master applications which are interested in different
> subsets of these PDOs.  As an example, let's say that the slave has an
> RxPDO
> at 0x1600 that points to 0x7000:0x00:0x20, and one app wants to use this
> value and the other doesn't.
>
> If the master apps just use ecrt_domain_reg_pdo_entry_list to register the
> PDOs of interest, then they both work (assuming that the slave has all the
> required PDOs assigned by default), but it wastes space in the packet as
> the
> whole SM is transferred even if some of the data is not of interest to that
> particular master app.  (And in the case of outputs, it forces the master
> app to write something even when it doesn't want to, lest the slave get
> uninitialized data and think it needs to do something with it.)
>
> If the master apps use ecrt_slave_config_pdos to select the PDOs of
> interest, then things get troublesome.  If the master apps specify the full
> mappings explicitly, then again things work, but as the slave does not
> support remapping (just reassignment) this generates warnings, and it just
> seems ugly to me to have to specify all this data that the slave already
> knows.  (And it makes things more brittle, as if the mapping is changed in
> a
> future version of the slave it will generate an error instead of just
> working, as it would if it had loaded the slave's current mappings.)
>
> If the master apps don't specify the full mappings, however (just the sync
> manager -> PDO assignments, which seems like it's a supported scenario
> given
> the docs and examples), then results are mixed.  If the slave is rebooted
> prior to running either master app, it works.  If not, then the master app
> that wants the extra PDO will fail to run.
>
> The problem case seems to be:
>   - slave boots, has all PDOs in SII and CoE PDO assign.
>   - first app runs, specifies PDO Assign to not include 0x1600.
>     - runs successfully.
>     - PDO Assign is updated in the actual slave.
>   - second app runs, specifies PDO Assign to include 0x1600.
>     - fails at ecrt_reg_pdo_entry_list as it cannot find a mapping for
> 0x7000:0x00.
>     - problem is "Loading default mapping for PDO 0x1600." - "No default
> mapping found."
>     - PDO Assign of the actual slave is never actually updated in this case
> as it fails before it activates the slave configs.
>   - "ethercat rescan" / "ethercat pdos" at this point does not show 0x1600.
>   - it requires rebooting the slave, or manually updating PDO Assign (and
> rescanning) before the master will admit that it exists again.
>
> Shouldn't this scenario work?  The PDO is always specified in the SII, even
> if not presently in PDO Assign, so the master ought to know that it exists.
> And failing that, it could just try to read the mappings directly from the
> slave (if CoE is available) when unable to load default mapping from its
> cache.  (I think part of the problem is that the CoE data appears to be
> replacing the SII data in the master's PDO cache.)
>
> I'm also a little puzzled as to why (if it wants to have a cache of PDO
> mappings) it seems to limit itself to reading only the currently assigned
> PDOs during the initial scan, instead of fetching all of them.  They
> shouldn't be hard to find -- they can be identified purely by their index.
>
> It shouldn't be all that uncommon to have a slave that provides PDOs that
> aren't in the default PDO Assign, or to provide more information than
> needed
> for particular master apps.  Is it just expected that master apps always
> hard-code the full mappings, instead of fetching the mappings from the
> slave?  Or is this something missing from the library at present?
>
> Regards,
> Gavin Lambert
>
>
> _______________________________________________
> etherlab-users mailing list
> etherlab-users@etherlab.org
> http://lists.etherlab.org/mailman/listinfo/etherlab-users
>



-- 
Jun Yuan
[Aussprache: Djün Üän]

Robotics Technology Leaders GmbH
Am Loferfeld 58, D-81249 München
Tel: +49 89 189 0465 24
Fax: +49 89 189 0465 11
mailto: j.y...@rtleaders.com

Umlautregel in der chinesischen Lautschrift Pinyin: Nach den Anlauten y, j,
q, und x wird u als ü ausgesprochen, z.B. yu => ü,  ju => dschü,  qu =>
tschü,  xu => schü.
diff --git a/master/fsm_pdo.c b/master/fsm_pdo.c
--- a/master/fsm_pdo.c
+++ b/master/fsm_pdo.c
@@ -294,6 +294,7 @@
     // finished reading PDO configuration
 
     ec_pdo_list_copy(&fsm->sync->pdos, &fsm->pdos);
+    ec_pdo_list_merge_copy(&fsm->slave->default_pdos, &fsm->pdos);
     ec_pdo_list_clear_pdos(&fsm->pdos);
 
     // next sync manager
@@ -771,6 +772,7 @@
 
     // PDOs have been configured
     ec_pdo_list_copy(&fsm->sync->pdos, &fsm->pdos);
+    ec_pdo_list_merge_copy(&fsm->slave->default_pdos, &fsm->pdos);
 
     EC_SLAVE_DBG(fsm->slave, 1, "Successfully configured"
             " PDO assignment of SM%u.\n", fsm->sync_index);
diff --git a/master/pdo_list.c b/master/pdo_list.c
--- a/master/pdo_list.c
+++ b/master/pdo_list.c
@@ -170,6 +170,53 @@
 
 /*****************************************************************************/
 
+/** Add or merge the copy of an given PDO to the list
+ *
+ * \return 0 on success, else < 0
+ */
+int ec_pdo_list_merge_pdo_copy(
+        ec_pdo_list_t *pl, /**< PDO list. */
+        const ec_pdo_t *pdo /**< PDO to add. */
+        )
+{
+    ec_pdo_t *mapped_pdo;
+    int ret;
+
+    // ignores pdo with empty entry
+    if (ec_pdo_entry_count(pdo) == 0)
+    	return 0;
+
+    // PDO already mapped?
+    list_for_each_entry(mapped_pdo, &pl->list, list) {
+        if (mapped_pdo->index != pdo->index) continue;
+
+        ec_pdo_clear(mapped_pdo);
+        ret = ec_pdo_init_copy(mapped_pdo, pdo);
+        if (ret < 0) {
+        	list_del(&mapped_pdo->list);
+            kfree(mapped_pdo);
+            return ret;
+        }
+        return 0;
+    }
+
+    if (!(mapped_pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
+        EC_ERR("Failed to allocate PDO memory.\n");
+        return -ENOMEM;
+    }
+
+    ret = ec_pdo_init_copy(mapped_pdo, pdo);
+    if (ret < 0) {
+        kfree(mapped_pdo);
+        return ret;
+    }
+
+    list_add_tail(&mapped_pdo->list, &pl->list);
+    return 0;
+}
+
+/*****************************************************************************/
+
 /** Makes a deep copy of another PDO list.
  *
  * \return 0 on success, else < 0
@@ -196,6 +243,29 @@
 
 /*****************************************************************************/
 
+/** Merge from another PDO list.
+ *
+ * \return 0 on success, else < 0
+ */
+int ec_pdo_list_merge_copy(
+        ec_pdo_list_t *pl, /**< PDO list. */
+        const ec_pdo_list_t *other /**< PDO list to copy from. */
+        )
+{
+    ec_pdo_t *other_pdo;
+    int ret;
+
+    list_for_each_entry(other_pdo, &other->list, list) {
+        ret = ec_pdo_list_merge_pdo_copy(pl, other_pdo);
+        if (ret)
+            return ret;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
 /** Compares two PDO lists.
  *
  * Only the list is compared, not the PDO entries (i. e. the PDO
diff --git a/master/pdo_list.h b/master/pdo_list.h
--- a/master/pdo_list.h
+++ b/master/pdo_list.h
@@ -59,8 +59,10 @@
 
 ec_pdo_t *ec_pdo_list_add_pdo(ec_pdo_list_t *, uint16_t);
 int ec_pdo_list_add_pdo_copy(ec_pdo_list_t *, const ec_pdo_t *);
+int ec_pdo_list_merge_pdo_copy(ec_pdo_list_t *, const ec_pdo_t *);
 
 int ec_pdo_list_copy(ec_pdo_list_t *, const ec_pdo_list_t *);
+int ec_pdo_list_merge_copy(ec_pdo_list_t *, const ec_pdo_list_t *);
 
 uint16_t ec_pdo_list_total_size(const ec_pdo_list_t *);
 int ec_pdo_list_equal(const ec_pdo_list_t *, const ec_pdo_list_t *);
diff --git a/master/slave.c b/master/slave.c
--- a/master/slave.c
+++ b/master/slave.c
@@ -146,6 +146,8 @@
 
     INIT_LIST_HEAD(&slave->sii.pdos);
 
+    ec_pdo_list_init(&slave->default_pdos);
+
     INIT_LIST_HEAD(&slave->sdo_dictionary);
 
     slave->sdo_dictionary_fetched = 0;
@@ -241,6 +243,8 @@
         kfree(pdo);
     }
 
+    ec_pdo_list_clear(&slave->default_pdos);
+
     if (slave->sii_words) {
         kfree(slave->sii_words);
     }
@@ -539,6 +543,8 @@
             data += 8;
         }
 
+        ec_pdo_list_merge_pdo_copy(&slave->default_pdos, pdo);
+
         // if sync manager index is positive, the PDO is mapped by default
         if (pdo->sync_index >= 0) {
             ec_sync_t *sync;
diff --git a/master/slave.h b/master/slave.h
--- a/master/slave.h
+++ b/master/slave.h
@@ -222,6 +222,9 @@
     // Slave information interface
     ec_sii_t sii; /**< Extracted SII data. */
 
+    // Default PDO mapping with PDO entries
+    ec_pdo_list_t default_pdos;
+
     struct list_head sdo_dictionary; /**< SDO dictionary list */
     uint8_t sdo_dictionary_fetched; /**< Dictionary has been fetched. */
     unsigned long jiffies_preop; /**< Time, the slave went to PREOP. */
diff --git a/master/slave_config.c b/master/slave_config.c
--- a/master/slave_config.c
+++ b/master/slave_config.c
@@ -318,8 +318,6 @@
         ec_pdo_t *pdo
         )
 {
-    unsigned int i;
-    const ec_sync_t *sync;
     const ec_pdo_t *default_pdo;
 
     if (!sc->slave)
@@ -328,36 +326,32 @@
     EC_CONFIG_DBG(sc, 1, "Loading default mapping for PDO 0x%04X.\n",
             pdo->index);
 
-    // find PDO in any sync manager (it could be reassigned later)
-    for (i = 0; i < sc->slave->sii.sync_count; i++) {
-        sync = &sc->slave->sii.syncs[i];
+    // find PDO in default PDO mappings (it could be reassigned later)
+    list_for_each_entry(default_pdo, &sc->slave->default_pdos.list, list) {
+        if (default_pdo->index != pdo->index)
+            continue;
 
-        list_for_each_entry(default_pdo, &sync->pdos.list, list) {
-            if (default_pdo->index != pdo->index)
-                continue;
+        if (default_pdo->name) {
+            EC_CONFIG_DBG(sc, 1, "Found PDO name \"%s\".\n",
+                    default_pdo->name);
 
-            if (default_pdo->name) {
-                EC_CONFIG_DBG(sc, 1, "Found PDO name \"%s\".\n",
-                        default_pdo->name);
+            // take PDO name from assigned one
+            ec_pdo_set_name(pdo, default_pdo->name);
+        }
 
-                // take PDO name from assigned one
-                ec_pdo_set_name(pdo, default_pdo->name);
+        // copy entries (= default PDO mapping)
+        if (ec_pdo_copy_entries(pdo, default_pdo))
+            return;
+
+        if (sc->master->debug_level) {
+            const ec_pdo_entry_t *entry;
+            list_for_each_entry(entry, &pdo->entries, list) {
+                EC_CONFIG_DBG(sc, 1, "Entry 0x%04X:%02X.\n",
+                        entry->index, entry->subindex);
             }
+        }
 
-            // copy entries (= default PDO mapping)
-            if (ec_pdo_copy_entries(pdo, default_pdo))
-                return;
-
-            if (sc->master->debug_level) {
-                const ec_pdo_entry_t *entry;
-                list_for_each_entry(entry, &pdo->entries, list) {
-                    EC_CONFIG_DBG(sc, 1, "Entry 0x%04X:%02X.\n",
-                            entry->index, entry->subindex);
-                }
-            }
-
-            return;
-        }
+        return;
     }
 
     EC_CONFIG_DBG(sc, 1, "No default mapping found.\n");
_______________________________________________
etherlab-users mailing list
etherlab-users@etherlab.org
http://lists.etherlab.org/mailman/listinfo/etherlab-users

Reply via email to