Fix C code Generator to use CoE section contained in the slave ESI file for defining Ethercat network configuration
authorLaurent Bessard
Sun, 23 Sep 2012 23:25:57 +0200
changeset 2079 49242019a9ca
parent 2078 7d0ebbff1d08
child 2080 6d0d94cd0fe0
Fix C code Generator to use CoE section contained in the slave ESI file for defining Ethercat network configuration
etherlab/etherlab.py
etherlab/plc_cia402node.c
etherlab/plc_etherlab.c
--- a/etherlab/etherlab.py	Sat Sep 22 12:07:06 2012 +0200
+++ b/etherlab/etherlab.py	Sun Sep 23 23:25:57 2012 +0200
@@ -61,16 +61,6 @@
 
 class _EthercatSlaveCTN:
     
-    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
-    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-      <xsd:element name="SlaveParams">
-        <xsd:complexType>
-          <xsd:attribute name="DynamicPDOs" type="xsd:boolean" use="optional" default="true"/>
-        </xsd:complexType>
-      </xsd:element>
-    </xsd:schema>
-    """
-    
     NODE_PROFILE = None
     EditorType = NodeEditor
     
@@ -184,7 +174,6 @@
         <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
           <xsd:element name="CIA402SlaveParams">
             <xsd:complexType>
-              <xsd:attribute name="DynamicPDOs" type="xsd:boolean" use="optional" default="true"/>
               %s
             </xsd:complexType>
           </xsd:element>
@@ -361,7 +350,6 @@
       <xsd:element name="EtherlabNode">
         <xsd:complexType>
           <xsd:attribute name="MasterNumber" type="xsd:integer" use="optional" default="0"/>
-          <xsd:attribute name="ConfigurePDOs" type="xsd:boolean" use="optional" default="true"/>
         </xsd:complexType>
       </xsd:element>
     </xsd:schema>
@@ -655,13 +643,8 @@
         slaves = self.GetSlaves()
         for slave_pos in slaves:
             slave = self.GetSlave(slave_pos)
-            slave_node = self.GetChildByIECLocation([slave_pos])
-            if slave_node.CTNParams is not None:
-                slave_infos = slave_node.CTNParams[1]
-            else:
-                slave_infos = None
             if slave is not None:
-                self.FileGenerator.DeclareSlave(slave_pos, slave.getInfo().getAutoIncAddr(), slave.getType(), slave_infos)
+                self.FileGenerator.DeclareSlave(slave_pos, slave.getInfo().getAutoIncAddr(), slave.getType())
         
         for location in locations:
             loc = location["LOC"][len(current_location):]
@@ -821,9 +804,9 @@
 
     def __del__(self):
         self.Controler = None            
-
-    def DeclareSlave(self, slave_index, slave_alias, slave, slave_infos):
-        self.Slaves.append((slave_index, slave_alias, slave, slave_infos))
+    
+    def DeclareSlave(self, slave_index, slave_alias, slave):
+        self.Slaves.append((slave_index, slave_alias, slave))
 
     def DeclareVariable(self, slave_index, index, subindex, iec_type, dir, name):
         slave_variables = self.UsedVariables.setdefault(slave_index, {})
@@ -838,14 +821,15 @@
         
     def GenerateCFile(self, filepath, location_str, etherlab_node_infos):
         
+        # Extract etherlab master code template
         plc_etherlab_filepath = os.path.join(os.path.split(__file__)[0], "plc_etherlab.c")
         plc_etherlab_file = open(plc_etherlab_filepath, 'r')
         plc_etherlab_code = plc_etherlab_file.read()
         plc_etherlab_file.close()
         
+        # Initialize strings for formatting master code template
         str_completion = {
             "location": location_str,
-            "configure_pdos": int(etherlab_node_infos.getConfigurePDOs()),
             "master_number": etherlab_node_infos.getMasterNumber(),
             "located_variables_declaration": [],
             "used_pdo_entry_offset_variables_declaration": [],
@@ -859,35 +843,48 @@
             "publish_variables": [],
         }
         
+        # Initialize variable storing variable mapping state
         for slave_entries in self.UsedVariables.itervalues():
             for entry_infos in slave_entries.itervalues():
                 entry_infos["mapped"] = False
         
+        # Sort slaves by position (IEC_Channel)
         self.Slaves.sort()
+        # Initialize dictionary storing alias auto-increment position values
         alias = {}
-        for (slave_idx, slave_alias, type_infos, slave_infos) in self.Slaves:
+        
+        # Generating code for each slave
+        for (slave_idx, slave_alias, type_infos) in self.Slaves:
+            
+            # Defining slave alias and auto-increment position
             if alias.get(slave_alias) is not None:
                 alias[slave_alias] += 1
             else:
                 alias[slave_alias] = 0
             slave_pos = (slave_alias, alias[slave_alias])
             
+            # Extract slave device informations
             device = self.Controler.GetModuleInfos(type_infos)
             if device is not None:
-            
+                
+                # Extract slaves variables to be mapped
                 slave_variables = self.UsedVariables.get(slave_idx, {})
+                
+                # Extract slave device object dictionary entries
                 device_entries = device.GetEntriesList()
                 
-                if len(device.getTxPdo() + device.getRxPdo()) > 0 or len(slave_variables) > 0:
+                # Adding code for declaring slave in master code template strings
+                for element in ["vendor", "product_code", "revision_number"]:
+                    type_infos[element] = ExtractHexDecValue(type_infos[element])
+                type_infos.update(dict(zip(["slave", "alias", "position"], (slave_idx,) + slave_pos)))
+                
+                # Extract slave device CoE informations
+                device_coe = device.getCoE()
+                if device_coe is not None:
                     
-                    for element in ["vendor", "product_code", "revision_number"]:
-                        type_infos[element] = ExtractHexDecValue(type_infos[element])
-                    type_infos.update(dict(zip(["slave", "alias", "position"], (slave_idx,) + slave_pos)))
-                
-                    str_completion["slaves_declaration"] += "static ec_slave_config_t *slave%(slave)d = NULL;\n" % type_infos
-                    str_completion["slaves_configuration"] += SLAVE_CONFIGURATION_TEMPLATE % type_infos
-    
-                    for initCmd in device.getInitCmd():
+                    # If device support CanOpen over Ethernet, adding code for calling 
+                    # init commands when initializing slave in master code template strings
+                    for initCmd in device_coe.getInitCmd():
                         index = ExtractHexDecValue(initCmd.getIndex())
                         subindex = ExtractHexDecValue(initCmd.getSubIndex())
                         entry = device_entries.get((index, subindex), None)
@@ -903,7 +900,20 @@
                             }
                             init_cmd_infos.update(type_infos)
                             str_completion["slaves_initialization"] += SLAVE_INITIALIZATION_TEMPLATE % init_cmd_infos
-
+                
+                    # Extract slave device PDO configuration capabilities
+                    PdoAssign = device_coe.getPdoAssign()
+                    PdoConfig = device_coe.getPdoConfig()
+                else:
+                    PdoAssign = PdoConfig = False
+                
+                # Test if slave has a configuration or need one
+                if len(device.getTxPdo() + device.getRxPdo()) > 0 or len(slave_variables) > 0 and PdoConfig and PdoAssign:
+                    
+                    str_completion["slaves_declaration"] += "static ec_slave_config_t *slave%(slave)d = NULL;\n" % type_infos
+                    str_completion["slaves_configuration"] += SLAVE_CONFIGURATION_TEMPLATE % type_infos
+                    
+                    # Initializing 
                     pdos_infos = {
                         "pdos_entries_infos": [],
                         "pdos_infos": [],
@@ -989,7 +999,7 @@
                                     
                                     ConfigureVariable(entry_infos, str_completion)
                                 
-                                elif pdo_type == "Outputs" and entry.getDataType() is not None:
+                                elif pdo_type == "Outputs" and entry.getDataType() is not None and device_coe is not None:
                                     entry_infos["dir"] = "Q"
                                     entry_infos["data_size"] = max(1, entry_infos["bitlen"] / 8)
                                     entry_infos["var_type"] = entry.getDataType().getcontent()
@@ -1024,7 +1034,7 @@
                                      "entries_number": len(entries_infos),
                                      "fixed": pdo.getFixed() == True})
                     
-                    if slave_infos is None or slave_infos.getDynamicPDOs():
+                    if PdoConfig and PdoAssign:
                         dynamic_pdos = {}
                         dynamic_pdos_number = 0
                         for category, min_index, max_index in [("Inputs", 0x1600, 0x1800), 
@@ -1104,11 +1114,11 @@
                                 
                                 if pdo["entries_number"] == 255:
                                     dynamic_pdos[pdo_type]["pdos"].pop(0)
-                            
+                    
                     pdo_offset = 0
                     entry_offset = 0
                     for sync_manager_infos in sync_managers:
-                        
+                    
                         for pdo_infos in sync_manager_infos["pdos"]:
                             pdo_infos["offset"] = entry_offset
                             pdo_entries = pdo_infos["entries"]
@@ -1130,7 +1140,13 @@
                         pdos_infos[element] = "\n".join(pdos_infos[element])
                     
                     str_completion["pdos_configuration_declaration"] += SLAVE_PDOS_CONFIGURATION_DECLARATION % pdos_infos
-        
+                
+                for (index, subindex), entry_declaration in slave_variables.iteritems():
+                    if not entry_declaration["mapped"]:
+                        message = _("Entry index 0x%4.4x, subindex 0x%2.2x not mapped for device %s") % \
+                                        (index, subindex, type_infos["device_type"])
+                        self.Controler.GetCTRoot().logger.write_warning(_("Warning: ") + message + "\n")
+                    
         for element in ["used_pdo_entry_offset_variables_declaration", 
                         "used_pdo_entry_configuration", 
                         "located_variables_declaration", 
@@ -1216,17 +1232,12 @@
     
     setattr(cls, "ExtractDataTypes", ExtractDataTypes)
     
-    def getInitCmd(self):
+    def getCoE(self):
         mailbox = self.getMailbox()
-        if mailbox is None:
-            return []
-        
-        coe = mailbox.getCoE()
-        if coe is None:
-            return []
-
-        return coe.getInitCmd()
-    setattr(cls, "getInitCmd", getInitCmd)
+        if mailbox is not None:
+            return mailbox.getCoE()
+        return None
+    setattr(cls, "getCoE", getCoE)
 
     def GetEntriesList(self):
         if self.DataTypes is None:
--- a/etherlab/plc_cia402node.c	Sat Sep 22 12:07:06 2012 +0200
+++ b/etherlab/plc_cia402node.c	Sun Sep 23 23:25:57 2012 +0200
@@ -48,7 +48,8 @@
 %(init_entry_variables)s
 	*__IW%(location)s_0 = __MK_Alloc_AXIS_REF();
 	__CIA402Node_%(location)s.axis = __MK_GetPublic_AXIS_REF(*__IW%(location)s_0);
-	return 0;
+	*(__CIA402Node_%(location)s.ModesOfOperation) = 0x08;
+    return 0;
 }
 
 void __cleanup_%(location)s()
--- a/etherlab/plc_etherlab.c	Sat Sep 22 12:07:06 2012 +0200
+++ b/etherlab/plc_etherlab.c	Sun Sep 23 23:25:57 2012 +0200
@@ -21,9 +21,6 @@
 // declaration of interface variables
 %(located_variables_declaration)s
 
-// Optional features
-#define CONFIGURE_PDOS  %(configure_pdos)d
-
 // process data
 uint8_t *domain1_pd = NULL;
 %(used_pdo_entry_offset_variables_declaration)s
@@ -34,9 +31,7 @@
 };
 /*****************************************************************************/
 
-#if CONFIGURE_PDOS
 %(pdos_configuration_declaration)s
-#endif
 
 int rt_fd = -1;
 CstructMstrAttach MstrAttach;
@@ -64,10 +59,8 @@
 	domain1 = ecrt_master_create_domain(master);
 	if (!domain1) return -1;
 
-#if CONFIGURE_PDOS
-    fprintf(stdout, "Configure PDOs...\n");
-	%(slaves_configuration)s
-#endif
+    // slaves PDO configuration
+%(slaves_configuration)s
 
     if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
         fprintf(stderr, "PDO entry registration failed!\n");
@@ -76,8 +69,10 @@
 
 	ecrt_master_set_send_interval(master, common_ticktime__);
 
+    // slaves initialization
 %(slaves_initialization)s
 
+    // extracting default value for not mapped entry in output PDOs
 %(slaves_output_pdos_default_values_extraction)s
 
     sprintf(&rt_dev_file[0],"%%s%%u",EC_RTDM_DEV_FILE_NAME,0);