add autostart plc feature for beremiz_service
authorgreg
Mon, 30 Mar 2009 17:04:30 +0200
changeset 329 22e65b8e20f4
parent 328 c23daa6996c2
child 330 fdf81615ed04
add autostart plc feature for beremiz_service
runtime/PLCObject.py
targets/Linux/plc_Linux_main.c
targets/Win32/plc_Win32_main.c
targets/Xenomai/__init__.py
targets/plc_python.c
--- a/runtime/PLCObject.py	Tue Mar 24 17:33:46 2009 +0100
+++ b/runtime/PLCObject.py	Mon Mar 30 17:04:30 2009 +0200
@@ -46,7 +46,7 @@
 
 class PLCObject(pyro.ObjBase):
     _Idxs = []
-    def __init__(self, workingdir, daemon, argv, statuschange=None, evaluator=eval):
+    def __init__(self, workingdir, daemon, argv, statuschange, evaluator):
         pyro.ObjBase.__init__(self)
         self.evaluator = evaluator
         self.argv = [workingdir] + argv # force argv[0] to be "path" to exec...
@@ -57,7 +57,6 @@
         self._FreePLC()
         self.daemon = daemon
         self.statuschange = statuschange
-        self.python_threads_vars = None
         self.hmi_frame = None
         
         # Get the last transfered PLC if connector must be restart
@@ -220,23 +219,21 @@
                             break
             except:
                 PLCprint(traceback.format_exc())
-            
-    def BeginRuntimePy(self):
         runtime_begin = self.python_threads_vars.get("_runtime_begin",None)
         if runtime_begin is not None:
-            self.evaluator(runtime_begin)
+            runtime_begin()
 
     def FinishRuntimePy(self):
         runtime_cleanup = self.python_threads_vars.get("_runtime_cleanup",None)
         if runtime_cleanup is not None:
-            self.evaluator(runtime_cleanup)
+            runtime_cleanup()
         if self.hmi_frame is not None:
-            self.evaluator(self.hmi_frame.Destroy)
+            self.hmi_frame.Destroy()
         self.python_threads_vars = None
 
     def PythonThreadProc(self):
         PLCprint("PythonThreadProc started")
-        self.BeginRuntimePy()
+        self.evaluator(self.PrepareRuntimePy)
         res,cmd = "None","None"
         while self.PLCStatus == "Started":
             #print "_PythonIterator(", res, ")",
@@ -249,6 +246,7 @@
             except Exception,e:
                 res = "#EXCEPTION : "+str(e)
                 PLCprint(res)
+        self.evaluator(self.FinishRuntimePy)
         PLCprint("PythonThreadProc interrupted")
     
     def StartPLC(self, debug=False):
@@ -262,7 +260,6 @@
                     self._resumeDebug()
                 self.PLCStatus = "Started"
                 self.StatusChange()
-                self.evaluator(self.PrepareRuntimePy)
                 self.PythonThread = Thread(target=self.PythonThreadProc)
                 self.PythonThread.start()
                 return True
@@ -272,12 +269,8 @@
         return False
 
     def _DoStopPLC(self):
+        self.PLCStatus = "Stopped"
         self._stopPLC()
-        self.PLCStatus = "Stopped"
-        self.PythonThread.join(timeout=1)
-        if self.PythonThread.isAlive():
-            PLCprint("Python thread couldn't be killed")
-        self.FinishRuntimePy()
         if self._FreePLC():
             self.PLCStatus = "Dirty"
         self.StatusChange()
--- a/targets/Linux/plc_Linux_main.c	Tue Mar 24 17:33:46 2009 +0100
+++ b/targets/Linux/plc_Linux_main.c	Mon Mar 30 17:04:30 2009 +0200
@@ -1,13 +1,13 @@
 /**
  * Linux specific code
- **/ 
+ **/
 
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
 #include <signal.h>
 #include <stdlib.h>
-#include <pthread.h> 
+#include <pthread.h>
 
 /* provided by POUS.C */
 extern int common_ticktime__;
@@ -51,7 +51,7 @@
 	    timerValues.it_interval.tv_sec = period / 1000000000;
 	    timerValues.it_interval.tv_nsec = period % 1000000000;
 #endif
-	}	
+	}
     timer_settime (PLC_timer, 0, &timerValues, NULL);
 }
 //
@@ -77,20 +77,23 @@
     struct sigevent sigev;
     /* Translate PLC's microseconds to Ttick nanoseconds */
     Ttick = 1000000 * maxval(common_ticktime__,1);
-    
+
     memset (&sigev, 0, sizeof (struct sigevent));
     sigev.sigev_value.sival_int = 0;
     sigev.sigev_notify = SIGEV_THREAD;
     sigev.sigev_notify_attributes = NULL;
     sigev.sigev_notify_function = PLC_timer_notify;
 
+    pthread_mutex_init(&debug_wait_mutex);
+    pthread_mutex_init(&python_wait_mutex);
+
     pthread_mutex_lock(&debug_wait_mutex);
     pthread_mutex_lock(&python_wait_mutex);
 
     timer_create (CLOCK_REALTIME, &sigev, &PLC_timer);
     if(  __init(argc,argv) == 0 ){
         PLC_SetTimer(Ttick,Ttick);
-        
+
         /* install signal handler for manual break */
 //        signal(SIGTERM, catch_signal);
         signal(SIGINT, catch_signal);
@@ -118,6 +121,9 @@
     __cleanup();
     __debug_tick = -1;
     pthread_mutex_unlock(&debug_wait_mutex);
+    pthread_mutex_destroy(&debug_wait_mutex);
+    pthread_mutex_unlock(&python_wait_mutex);
+    pthread_mutex_destroy(&python_wait_mutex);
 }
 
 extern int __tick;
@@ -125,10 +131,10 @@
 int WaitDebugData()
 {
     /* Wait signal from PLC thread */
-    pthread_mutex_lock(&debug_wait_mutex);
+    if(pthread_mutex_lock(&debug_wait_mutex)) return -1;
     return __debug_tick;
 }
- 
+
 /* Called by PLC thread when debug_publish finished
  * This is supposed to unlock debugger thread in WaitDebugData*/
 void InitiateDebugTransfer()
@@ -157,9 +163,9 @@
 int WaitPythonCommands(void)
 {
     /* Wait signal from PLC thread */
-    pthread_mutex_lock(&python_wait_mutex);
+    return pthread_mutex_lock(&python_wait_mutex);
 }
- 
+
 /* Called by PLC thread on each new python command*/
 void UnBlockPythonCommands(void)
 {
--- a/targets/Win32/plc_Win32_main.c	Tue Mar 24 17:33:46 2009 +0100
+++ b/targets/Win32/plc_Win32_main.c	Mon Mar 30 17:04:30 2009 +0200
@@ -1,6 +1,6 @@
 /**
  * Win32 specific code
- **/ 
+ **/
 
 #include <stdio.h>
 #include <sys/timeb.h>
@@ -19,7 +19,7 @@
 void PLC_GetTime(IEC_TIME *CURRENT_TIME)
 {
 	_ftime(&timetmp);
-	
+
 	(*CURRENT_TIME).tv_sec = timetmp.time;
 	(*CURRENT_TIME).tv_nsec = timetmp.millitm * 1000000;
 }
@@ -36,11 +36,11 @@
 	LARGE_INTEGER liDueTime;
 	/* arg 2 of SetWaitableTimer take 100 ns interval*/
 	liDueTime.QuadPart =  next / (-100);
-	
+
 	/*
 	printf("SetTimer(%lld,%lld)\n",next, period);
 	*/
-	
+
 	if (!SetWaitableTimer(PLC_timer, &liDueTime, common_ticktime__, NULL, NULL, 0))
     {
         printf("SetWaitableTimer failed (%d)\n", GetLastError());
@@ -66,9 +66,9 @@
 
 HANDLE PLC_thread;
 HANDLE debug_sem;
-HANDLE debug_wait_sem; 
+HANDLE debug_wait_sem;
 HANDLE python_sem;
-HANDLE python_wait_sem; 
+HANDLE python_wait_sem;
 
 #define maxval(a,b) ((a>b)?a:b)
 int startPLC(int argc,char **argv)
@@ -77,54 +77,54 @@
 	/* Translate PLC's microseconds to Ttick nanoseconds */
 	Ttick = 1000000 * maxval(common_ticktime__,1);
 
-	debug_sem = CreateSemaphore( 
+	debug_sem = CreateSemaphore(
 							NULL,           // default security attributes
 					        1,  			// initial count
 					        1,  			// maximum count
 					        NULL);          // unnamed semaphore
-    if (debug_sem == NULL) 
+    if (debug_sem == NULL)
     {
         printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError());
         return;
     }
-    
-	debug_wait_sem = CreateSemaphore( 
+
+	debug_wait_sem = CreateSemaphore(
 					        NULL,           // default security attributes
 					        0,  			// initial count
 					        1,  			// maximum count
 					        NULL);          // unnamed semaphore
 
-    if (debug_wait_sem == NULL) 
+    if (debug_wait_sem == NULL)
     {
         printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError());
         return;
     }
 
-	python_sem = CreateSemaphore( 
+	python_sem = CreateSemaphore(
 					        NULL,           // default security attributes
 					        1,  			// initial count
 					        1,  			// maximum count
 					        NULL);          // unnamed semaphore
 
-    if (python_sem == NULL) 
+    if (python_sem == NULL)
     {
         printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError());
         return;
     }
-	python_wait_sem = CreateSemaphore( 
+	python_wait_sem = CreateSemaphore(
 					        NULL,           // default security attributes
 					        0,  			// initial count
 					        1,  			// maximum count
 					        NULL);          // unnamed semaphore
 
 
-    if (python_wait_sem == NULL) 
+    if (python_wait_sem == NULL)
     {
         printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError());
         return;
     }
 
-	
+
 	/* Create a waitable timer */
     PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer");
     if(NULL == PLC_timer)
@@ -172,10 +172,10 @@
 /* from plc_debugger.c */
 int WaitDebugData()
 {
-	WaitForSingleObject(debug_wait_sem, INFINITE);
+	if(WaitForSingleObject(debug_wait_sem, INFINITE) != WAIT_OBJECT_0) return -1;
 	return __debug_tick;
 }
- 
+
 /* Called by PLC thread when debug_publish finished
  * This is supposed to unlock debugger thread in WaitDebugData*/
 void InitiateDebugTransfer()
@@ -190,7 +190,7 @@
 {
 	__DEBUG = 0;
     /* Prevent PLC to enter debug code */
-	WaitForSingleObject(debug_sem, INFINITE);  
+	WaitForSingleObject(debug_sem, INFINITE);
 }
 
 void resumeDebug()
@@ -204,9 +204,9 @@
 int WaitPythonCommands(void)
 {
     /* Wait signal from PLC thread */
-	WaitForSingleObject(python_wait_sem, INFINITE);
-}
- 
+	return WaitForSingleObject(python_wait_sem, INFINITE);
+}
+
 /* Called by PLC thread on each new python command*/
 void UnBlockPythonCommands(void)
 {
--- a/targets/Xenomai/__init__.py	Tue Mar 24 17:33:46 2009 +0100
+++ b/targets/Xenomai/__init__.py	Mon Mar 30 17:04:30 2009 +0200
@@ -5,7 +5,7 @@
     extension = ".so"
     def getXenoConfig(self):
         """ Get xeno-config from target parameters """
-        return self.PuginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"].getXenoConfig()
+        return self.PluginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"].getXenoConfig()
     
     def getBuilderLDFLAGS(self):
         # get xeno-config from target parameters
--- a/targets/plc_python.c	Tue Mar 24 17:33:46 2009 +0100
+++ b/targets/plc_python.c	Mon Mar 30 17:04:30 2009 +0200
@@ -1,17 +1,17 @@
 /*
  * Python Asynchronous execution code
- * 
+ *
  * PLC put python commands in a fifo, respecting execution order
- * with the help of C pragmas inserted in python_eval FB code 
- * 
- * Buffer content is read asynchronously, (from non real time part), 
+ * with the help of C pragmas inserted in python_eval FB code
+ *
+ * Buffer content is read asynchronously, (from non real time part),
  * commands are executed and result stored for later use by PLC.
- * 
+ *
  * In this implementation, fifo is a list of pointer to python_eval
  * function blocks structures. Some local variables have been added in
  * python_eval interface. We use those local variables as buffer and state
  * flags.
- * 
+ *
  * */
 
 #include "iec_types_all.h"
@@ -30,7 +30,7 @@
 #define PYTHON_LOCKED_BY_PLC 1
 #define PYTHON_MUSTWAKEUP 2
 #define PYTHON_FINISHED 4
- 
+
 /* Each python_eval FunctionBlock have it own state */
 #define PYTHON_FB_FREE 0
 #define PYTHON_FB_REQUESTED 1
@@ -62,12 +62,12 @@
 
 void __retrieve_python()
 {
-	/* Check Python thread is not being 
+	/* Check Python thread is not being
 	 * modifying internal python_eval data */
-	PythonState = TryLockPython() ? 
-	                PYTHON_LOCKED_BY_PLC : 
+	PythonState = TryLockPython() ?
+	                PYTHON_LOCKED_BY_PLC :
 	                PYTHON_LOCKED_BY_PYTHON;
-	/* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON 
+	/* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
 	 * and python_eval will no do anything */
 }
 
@@ -83,13 +83,13 @@
 	}
 }
 /**
- * Called by the PLC, each time a python_eval 
+ * Called by the PLC, each time a python_eval
  * FB instance is executed
  */
 void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
 {
-	/* detect rising edge on TRIG to trigger evaluation */ 
-	if(((data__->TRIG && !data__->TRIGM1) || 
+	/* detect rising edge on TRIG to trigger evaluation */
+	if(((data__->TRIG && !data__->TRIGM1) ||
 	   /* polling is equivalent to trig on value rather than on rising edge*/
 	    (poll && data__->TRIG )) &&
 	    /* trig only if not already trigged */
@@ -122,12 +122,12 @@
 		}
 		/* got the order to act ?*/
 		if(data__->TRIGGED == 1 &&
-		   /* and not already being processed */ 
-		   data__->STATE == PYTHON_FB_FREE) 
+		   /* and not already being processed */
+		   data__->STATE == PYTHON_FB_FREE)
 		{
 			/* Enter the block in the fifo
 			/* Don't have to check if fifo cell is free
-			 * as fifo size == FB count, and a FB cannot 
+			 * as fifo size == FB count, and a FB cannot
 			 * be requested twice */
 			EvalFBs[Current_PLC_EvalFB] = data__;
 			/* copy into BUFFER local*/
@@ -186,14 +186,14 @@
 		//printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
 	}
 	/* while next slot is empty */
-	while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || 
-	 	  /* or doesn't contain command */ 
+	while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
+	 	  /* or doesn't contain command */
 	      data__->STATE != PYTHON_FB_REQUESTED)
 	{
 		UnLockPython();
 		/* wait next FB to eval */
 		//printf("PythonIterator wait\n");
-		WaitPythonCommands();
+		if(WaitPythonCommands()) return NULL;
 		/*emergency exit*/
 		if(PythonState & PYTHON_FINISHED) return NULL;
 		LockPython();