# HG changeset patch # User greg # Date 1238425470 -7200 # Node ID 22e65b8e20f4df94b4a5da82d843adf28506d329 # Parent c23daa6996c2410f8cb653ff44bb5dc7891cd529 add autostart plc feature for beremiz_service diff -r c23daa6996c2 -r 22e65b8e20f4 runtime/PLCObject.py --- 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() diff -r c23daa6996c2 -r 22e65b8e20f4 targets/Linux/plc_Linux_main.c --- 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 #include #include #include #include -#include +#include /* 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) { diff -r c23daa6996c2 -r 22e65b8e20f4 targets/Win32/plc_Win32_main.c --- 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 #include @@ -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) { diff -r c23daa6996c2 -r 22e65b8e20f4 targets/Xenomai/__init__.py --- 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 diff -r c23daa6996c2 -r 22e65b8e20f4 targets/plc_python.c --- 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();