On the long wat towards generated code comilation...
authoretisserant
Fri, 21 Sep 2007 17:48:34 +0200
changeset 49 45dc6a944ab6
parent 48 6b30cfee163e
child 50 447b7706a5b6
On the long wat towards generated code comilation...
Beremiz.py
plugger.py
plugins/c_ext/c_ext.py
plugins/canfestival/canfestival.py
plugins/svgui/svgui.py
runtime/__init__.py
runtime/plc_Linux_main.c
runtime/plc_Win32_main.c
runtime/plc_common_main.c
--- a/Beremiz.py	Thu Sep 20 17:32:52 2007 +0200
+++ b/Beremiz.py	Fri Sep 21 17:48:34 2007 +0200
@@ -88,7 +88,8 @@
         def fin(pid,ecode):
             self.exitcode = ecode
             if self.exitcode != 0:
-                self.write("pid %d exited with status %d\n"%(pid,ecode))
+                self.write(Command + "\n")
+                self.write_warning("exited with status %d (pid %d)\n"%(ecode,pid))
 
         def spin(p):
             while not p.finished:
@@ -326,7 +327,7 @@
         if projectOpen:
             self.PluginRoot.LoadProject(projectOpen, self.Log)
             self.RefreshPluginTree()
-            self.PluginTree.SelectItem(self.PluginTree.GetRoot())
+            self.PluginTree.SelectItem(self.PluginTree.GetRootItem())
         
         self.RefreshPluginParams()
         self.RefreshButtons()
--- a/plugger.py	Thu Sep 20 17:32:52 2007 +0200
+++ b/plugger.py	Fri Sep 21 17:48:34 2007 +0200
@@ -485,6 +485,7 @@
 from PLCOpenEditor import PLCOpenEditor, ProjectDialog
 from TextViewer import TextViewer
 from plcopen.structures import IEC_KEYWORDS, AddPluginBlockList, ClearPluginTypes, PluginTypes
+import runtime
 import re
 
 class PluginsRoot(PlugTemplate, PLCControler):
@@ -680,7 +681,7 @@
             ex: [((0,0,4,5),'I','STRING','__IX_0_0_4_5'),...]
         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
         """
-        return [(C_file_name, "-I"+ieclib_path) for C_file_name in self.PLCGeneratedCFiles ] , ""
+        return [(C_file_name, self.CFLAGS) for C_file_name in self.PLCGeneratedCFiles ] , ""
     
     def _getBuildPath(self):
         return os.path.join(self.ProjectPath, "build")
@@ -749,6 +750,8 @@
         self.PLCGeneratedCFiles = C_files
         # Keep track of generated located variables for later use by self._Generate_C
         self.PLCGeneratedLocatedVars = locations
+        # compute CFLAGS for plc
+        self.CFLAGS = "-I"+ieclib_path
         return True
 
     def _build(self, logger):
@@ -791,6 +794,32 @@
         #logger.write("LocationCFilesAndCFLAGS :\n"+pp.pformat(LocationCFilesAndCFLAGS)+"\n")
         #logger.write("LDFLAGS :\n"+pp.pformat(LDFLAGS)+"\n")
         
+        # Generate main
+        locstrs = map(lambda x:"_".join(map(str,x)), [loc for loc in zip(*LocationCFilesAndCFLAGS)[0] if loc])
+        plc_main = runtime.code("plc_common_main") % {
+            "calls_prototypes":"".join(["""
+void __init%(s)s();
+void __cleanup%(s)s();
+void __retrive%(s)s();
+void __publish%(s)s();"""%{'s':locstr} for locstr in locstrs]),
+            "retrive_calls":"".join(["""
+    __retrive%(s)s();"""%{'s':locstr} for locstr in locstrs]),
+            "publish_calls":"".join(["""
+    __publish%(s)s();"""%{'s':locstr} for locstr in locstrs]),
+            "init_calls":"".join(["""
+    __init%(s)s();"""%{'s':locstr} for locstr in locstrs]),
+            "cleanup_calls":"".join(["""
+    __cleanup%(s)s();"""%{'s':locstr} for locstr in locstrs])}
+        target_name = self.BeremizRoot.TargetType.content["name"]
+        plc_main += runtime.code("plc_%s_main"%target_name)
+
+        main_path = os.path.join(buildpath, "main.c" )
+        f = open(main_path,'w')
+        f.write(plc_main)
+        f.close()
+        # First element is necessarely root
+        LocationCFilesAndCFLAGS[0][1].insert(0,(main_path, self.CFLAGS))
+        
         # Compile the resulting code into object files.
         compiler = self.BeremizRoot.getCompiler()
         for Location, CFilesAndCFLAGS in LocationCFilesAndCFLAGS:
@@ -802,8 +831,13 @@
             for CFile, CFLAGS in CFilesAndCFLAGS:
                 bn = os.path.basename(CFile)
                 logger.write("   [CC]  "+bn+" -> "+os.path.splitext(bn)[0]+".o\n")
-                objectfilename = os.path.splitext(bn)[0]+".o"
+                objectfilename = os.path.splitext(CFile)[0]+".o"
                 status, result, err_result = logger.LogCommand("%s -c %s -o %s %s"%(compiler, CFile, objectfilename, CFLAGS))
+                if status != 0:
+                    logger.write_error("Build failed\n")
+                    return False
+                    
+        return True
         
         
         # Link object files into something that can be executed on target
--- a/plugins/c_ext/c_ext.py	Thu Sep 20 17:32:52 2007 +0200
+++ b/plugins/c_ext/c_ext.py	Fri Sep 21 17:48:34 2007 +0200
@@ -130,7 +130,7 @@
         location_str = "_".join(map(lambda x:str(x), current_location))
         res = []
         for CFile in self.CFileBaseNames():
-            Gen_Cfile_path = os.path.join(buildpath, location_str + "_" + os.path.splitext(CFile)[0] + "_CFile.c" )
+            Gen_Cfile_path = os.path.join(buildpath, "CFile_%s_%s.c"%(location_str, os.path.splitext(CFile)[0]))
             f = open(Gen_Cfile_path,'w')
             f.write("/* Header generated by Beremiz c_ext plugin */\n")
             f.write("#include \"iec_std_lib.h\"\n")
--- a/plugins/canfestival/canfestival.py	Thu Sep 20 17:32:52 2007 +0200
+++ b/plugins/canfestival/canfestival.py	Fri Sep 21 17:48:34 2007 +0200
@@ -1,13 +1,13 @@
 import os, sys
 base_folder = os.path.split(sys.path[0])[0]
-sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
-CanfestivalIncludePath = os.path.join(base_folder, "CanFestival-3", "include")
-CanfestivalLibPath = os.path.join(base_folder, "CanFestival-3", "src")
+CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
+sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
 
 from nodelist import NodeList
 from nodemanager import NodeManager
 import config_utils, gen_cfile
 from networkedit import networkedit
+import canfestival_config
 
 class _NetworkEdit(networkedit):
     " Overload some of CanFestival Network Editor methods "
@@ -78,14 +78,14 @@
         current_location = self.GetCurrentLocation()
         # define a unique name for the generated C file
         prefix = "_".join(map(lambda x:str(x), current_location))
-        Gen_OD_path = os.path.join(buildpath, prefix + "_OD.c" )
+        Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
         # Create a new copy of the model with DCF loaded with PDO mappings for desired location
         master = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs())
         res = gen_cfile.GenerateFile(Gen_OD_path, master)
         if res :
             raise Exception, res
         
-        return [(Gen_OD_path,"-I"+CanfestivalIncludePath)],""
+        return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],""
     
 class RootClass:
     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
@@ -101,6 +101,6 @@
     PlugChildsTypes = [("CanOpenNode",_NodeListPlug)]
     
     def PlugGenerate_C(self, buildpath, locations, logger):
-        return [],"-L"+CanfestivalLibPath+" -lcanfestival"
+        return [],canfestival_config.getLDFLAGS(CanFestivalPath)
 
 
--- a/plugins/svgui/svgui.py	Thu Sep 20 17:32:52 2007 +0200
+++ b/plugins/svgui/svgui.py	Fri Sep 21 17:48:34 2007 +0200
@@ -758,7 +758,7 @@
     def PlugGenerate_C(self, buildpath, locations, logger):
         current_location = self.GetCurrentLocation()
         self.BusNumber = "_".join(map(lambda x:str(x), current_location))
-        progname = self.BusNumber + "_SVGUI"
+        progname = "SVGUI_" + self.BusNumber
         self.GenerateProgram(buildpath, progname)
         Gen_C_file = os.path.join(buildpath, progname+".cpp" )
         return [(Gen_C_file,"")],""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/__init__.py	Fri Sep 21 17:48:34 2007 +0200
@@ -0,0 +1,10 @@
+# module which import C files as strings
+
+import os
+
+def code(name):
+    filename = os.path.join(os.path.split(__file__)[0],name + ".c")
+    if os.path.exists(filename):
+        return open(filename).read()
+    else:
+        return "#error %s target not implemented !!!\n"%name
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/plc_Linux_main.c	Fri Sep 21 17:48:34 2007 +0200
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <signal.h>
+
+
+void timer_notify(sigval_t val)
+{
+    struct timespec CURRENT_TIME;
+    clock_gettime(CLOCK_REALTIME, &CURRENT_TIME);
+    __run();
+}
+
+void catch_signal(int sig)
+{
+  signal(SIGTERM, catch_signal);
+  signal(SIGINT, catch_signal);
+  printf("Got Signal %d\n",sig);
+}
+
+int main(int argc,char **argv)
+{
+    timer_t timer;
+    struct sigevent sigev;
+    long tv_nsec = 1000000 * (maxval(common_ticktime__,1)%1000);
+    time_t tv_sec = common_ticktime__/1000;
+    struct itimerspec timerValues;
+    
+    memset (&sigev, 0, sizeof (struct sigevent));
+    memset (&timerValues, 0, sizeof (struct itimerspec));
+    sigev.sigev_value.sival_int = 0;
+    sigev.sigev_notify = SIGEV_THREAD;
+    sigev.sigev_notify_attributes = NULL;
+    sigev.sigev_notify_function = timer_notify;
+    timerValues.it_value.tv_sec = tv_sec;
+    timerValues.it_value.tv_nsec = tv_nsec;
+    timerValues.it_interval.tv_sec = tv_sec;
+    timerValues.it_interval.tv_nsec = tv_nsec;
+
+    __init();
+
+    timer_create (CLOCK_REALTIME, &sigev, &timer);
+    timer_settime (timer, 0, &timerValues, NULL);
+    
+    /* install signal handler for manual break */
+    signal(SIGTERM, catch_signal);
+    signal(SIGINT, catch_signal);
+    
+    pause();
+    
+    timer_delete (timer);
+
+    __cleanup();
+    
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/plc_Win32_main.c	Fri Sep 21 17:48:34 2007 +0200
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <sys/timeb.h>
+#include <time.h>
+#include <windows.h>
+
+void timer_notify()
+{
+   struct _timeb timebuffer;
+
+   _ftime( &timebuffer );
+   CURRENT_TIME.tv_sec = timebuffer.time;
+   CURRENT_TIME.tv_nsec = timebuffer.millitm * 1000000
+   __run();
+}
+
+int main(int argc,char **argv)
+{
+    HANDLE hTimer = NULL;
+    LARGE_INTEGER liDueTime;
+
+    liDueTime.QuadPart = -10000 * maxval(common_ticktime__,1);;
+
+    // Create a waitable timer.
+    hTimer = CreateWaitableTimer(NULL, TRUE, "WaitableTimer");
+    if (NULL == hTimer)
+    {
+        printf("CreateWaitableTimer failed (%d)\n", GetLastError());
+        return 1;
+    }
+
+    __init();
+
+    // Set a timer to wait for 10 seconds.
+    if (!SetWaitableTimer(hTimer, &liDueTime, common_ticktime__, NULL, NULL, 0))
+    {
+        printf("SetWaitableTimer failed (%d)\n", GetLastError());
+        return 2;
+    }
+
+    while(1){
+    // Wait for the timer.
+        if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)
+        {
+            printf("WaitForSingleObject failed (%d)\n", GetLastError());
+            break;
+        }
+        timer_notify();
+    }
+
+    __cleanup();
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/plc_common_main.c	Fri Sep 21 17:48:34 2007 +0200
@@ -0,0 +1,48 @@
+/*
+ * Functions and variables provied by generated C softPLC
+ **/ 
+extern int common_ticktime__;
+
+/*
+ * Functions and variables provied by plc.c
+ **/ 
+void run(long int tv_sec, long int tv_nsec);
+
+#define maxval(a,b) ((a>b)?a:b)
+
+#include "iec_types.h"
+
+/*
+ * Functions and variables provied by generated C softPLC
+ **/ 
+void config_run__(int tick);
+void config_init__(void);
+
+/*
+ *  Functions and variables to export to generated C softPLC
+ **/
+ 
+IEC_TIME __CURRENT_TIME;
+
+static int tick = 0;
+
+%(calls_prototypes)s
+
+void __run()
+{
+    %(retrive_calls)s
+    config_run__(tick++);
+    %(publish_calls)s
+}
+
+void __init()
+{
+    config_init__();
+    %(init_calls)s
+}
+
+void __cleanup()
+{
+    %(cleanup_calls)s
+}
+