--- a/Beremiz.py Thu Aug 28 15:08:41 2008 +0200
+++ b/Beremiz.py Thu Aug 28 16:34:48 2008 +0200
@@ -369,7 +369,8 @@
"%s %s -p %s -i localhost %s"%(sys.executable,
Bpath("Beremiz_service.py"),
- self.local_runtime_tmpdir))
+ self.local_runtime_tmpdir), # Add beremiz's icon in top left corner of the frame
self.SetIcon(wx.Icon(Bpath( "images", "brz.ico"), wx.BITMAP_TYPE_ICO))
--- a/plugins/svgui/svgui.py Thu Aug 28 15:08:41 2008 +0200
+++ b/plugins/svgui/svgui.py Thu Aug 28 16:34:48 2008 +0200
@@ -201,8 +201,8 @@
Gen_C_file = os.path.join(buildpath, progname+".cpp" )
if wx.Platform == '__WXMSW__':
- cxx_flags = "-I..\\..\\wxPython-src-2.8.7.1\\bld\\lib\\wx\\include\\msw-unicode-release-2.8 -I..\\..\\wxPython-src-2.8.7.1\\include -I..\\..\\wxPython-src-2.8.7.1\\contrib\\include -I..\\..\\matiec\\lib -DWXUSINGDLL -D__WXMSW__ -mthreads"
- libs = "\"..\\lib\\libwxsvg.a\" \"..\\lib\\libwxsvg_agg.a\" \"..\\lib\\libagg.a\" \"..\\lib\\libaggplatformwin32.a\" \"..\\lib\\libaggfontwin32tt.a\" -L..\\..\\wxPython-src-2.8.7.1\\bld\\lib -mno-cygwin -mwindows -mthreads -mno-cygwin -mwindows -Wl,--subsystem,windows -mwindows -lwx_mswu_richtext-2.8 -lwx_mswu_aui-2.8 -lwx_mswu_xrc-2.8 -lwx_mswu_qa-2.8 -lwx_mswu_html-2.8 -lwx_mswu_adv-2.8 -lwx_mswu_core-2.8 -lwx_baseu_xml-2.8 -lwx_baseu_net-2.8 -lwx_baseu-2.8"
+ cxx_flags = "-I..\\..\\wxPython-src-2.8.8.1\\bld\\lib\\wx\\include\\msw-unicode-release-2.8 -I..\\..\\wxPython-src-2.8.8.1\\include -I..\\..\\wxPython-src-2.8.8.1\\contrib\\include -I..\\..\\matiec\\lib -DWXUSINGDLL -D__WXMSW__ -mthreads" + libs = "\"..\\lib\\libwxsvg.a\" \"..\\lib\\libwxsvg_agg.a\" \"..\\lib\\libagg.a\" \"..\\lib\\libaggplatformwin32.a\" \"..\\lib\\libaggfontwin32tt.a\" -L..\\..\\wxPython-src-2.8.8.1\\bld\\lib -mno-cygwin -mwindows -mthreads -mno-cygwin -mwindows -Wl,--subsystem,windows -mwindows -lwx_mswu_richtext-2.8 -lwx_mswu_aui-2.8 -lwx_mswu_xrc-2.8 -lwx_mswu_qa-2.8 -lwx_mswu_html-2.8 -lwx_mswu_adv-2.8 -lwx_mswu_core-2.8 -lwx_baseu_xml-2.8 -lwx_baseu_net-2.8 -lwx_baseu-2.8" status, result, err_result = ProcessLogger(self.logger, "wx-config --cxxflags", no_stdout=True).spin()
--- a/runtime/PLCObject.py Thu Aug 28 15:08:41 2008 +0200
+++ b/runtime/PLCObject.py Thu Aug 28 16:34:48 2008 +0200
@@ -1,295 +1,295 @@
-#This file is part of Beremiz, a Integrated Development Environment for
-#programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
-#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
-#See COPYING file for copyrights details.
-#This library is free software; you can redistribute it and/or
-#modify it under the terms of the GNU General Public
-#License as published by the Free Software Foundation; either
-#version 2.1 of the License, or (at your option) any later version.
-#This library is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-#General Public License for more details.
-#You should have received a copy of the GNU General Public
-#License along with this library; if not, write to the Free Software
-#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-import Pyro.core as pyro
-from threading import Timer
-import ctypes, os, commands
-if os.name == ("nt", "ce"):
- from _ctypes import LoadLibrary as dlopen
- from _ctypes import FreeLibrary as dlclose
-elif os.name == "posix":
- from _ctypes import dlopen, dlclose
- }.get(sys.platform, "")
-class PLCObject(pyro.ObjBase):
- def __init__(self, workingdir, daemon, argv):
- pyro.ObjBase.__init__(self)
- self.argv = [workingdir] + argv # force argv[0] to be "path" to exec...
- self.workingdir = workingdir
- self.PLCStatus = "Stopped"
- self.PLClibraryHandle = None
- # Creates fake C funcs proxies
- # Get the last transfered PLC if connector must be restart
- self.CurrentPLCFilename=open(
- self._GetMD5FileName(),
- "r").read().strip() + lib_ext
- self.PLCStatus = "Empty"
- self.CurrentPLCFilename=None
- def _GetMD5FileName(self):
- return os.path.join(self.workingdir, "lasttransferedPLC.md5")
- def _GetLibFileName(self):
- return os.path.join(self.workingdir,self.CurrentPLCFilename)
- Declare all functions, arguments and return values
- self._PLClibraryHandle = dlopen(self._GetLibFileName())
- self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle)
- self._startPLC = self.PLClibraryHandle.startPLC
- self._startPLC.restype = ctypes.c_int
- self._startPLC.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)]
- self._stopPLC = self.PLClibraryHandle.stopPLC
- self._stopPLC.restype = None
- self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables
- self._ResetDebugVariables.restype = None
- self._RegisterDebugVariable = self.PLClibraryHandle.ResetDebugVariables
- self._RegisterDebugVariable.restype = None
- self._IterDebugData = self.PLClibraryHandle.IterDebugData
- self._IterDebugData.restype = ctypes.c_void_p
- self._IterDebugData.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_char_p)]
- self._FreeDebugData = self.PLClibraryHandle.FreeDebugData
- self._FreeDebugData.restype = None
- self._WaitDebugData = self.PLClibraryHandle.WaitDebugData
- self._WaitDebugData.restype = ctypes.c_int
- print traceback.format_exc()
- This is also called by __init__ to create dummy C func proxies
- # Forget all refs to library
- self._startPLC = lambda:None
- self._stopPLC = lambda:None
- self._ResetDebugVariables = lambda:None
- self._RegisterDebugVariable = lambda x:None
- self._IterDebugData = lambda x,y:None
- self._FreeDebugData = lambda:None
- self.PLClibraryHandle = None
- # Unload library explicitely
- if getattr(self,"_PLClibraryHandle",None) is not None:
- dlclose(self._PLClibraryHandle)
- res = self._DetectDirtyLibs()
- self._PLClibraryHandle = None
- def _DetectDirtyLibs(self):
- # Get lib dependencies (for dirty lib detection)
- # parasiting libs listed with ldd
- badlibs = [ toks.split()[0] for toks in commands.getoutput(
- "ldd "+self._GetLibFileName()).splitlines() ]
- if badlib[:6] in ["libwx_",
- #badhandle = dlopen(badlib, dl.RTLD_NOLOAD)
- print "Dirty lib detected :" + badlib
- if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
- c_argv = ctypes.c_char_p * len(self.argv)
- if self._LoadNewPLC() and self._startPLC(len(self.argv),c_argv(*self.argv)) == 0:
- self.PLCStatus = "Started"
- print "_StartPLC did not return 0 !"
- self.PLCStatus = "Stopped"
- self.PLCStatus = "Dirty"
- if self.PLCStatus == "Started":
- self.daemon.shutdown(True)
- self.daemon.sock.close()
- os.execv(sys.executable,[sys.executable]+sys.argv[:])
- # respawn python interpreter
- Timer(0.1,self._Reload).start()
- def GetPLCstatus(self):
- def NewPLC(self, md5sum, data, extrafiles):
- print "NewPLC (%s)"%md5sum
- if self.PLCStatus in ["Stopped", "Empty", "Dirty"]:
- NewFileName = md5sum + lib_ext
- extra_files_log = os.path.join(self.workingdir,"extra_files.txt")
- os.remove(os.path.join(self.workingdir,
- self.CurrentPLCFilename))
- for filename in file(extra_files_log, "r").readlines() + extra_files_log:
- os.remove(os.path.join(self.workingdir, filename))
- open(os.path.join(self.workingdir,NewFileName),
- # Store new PLC filename based on md5 key
- open(self._GetMD5FileName(), "w").write(md5sum)
- log = file(extra_files_log, "w")
- for fname,fdata in extrafiles:
- fpath = os.path.join(self.workingdir,fname)
- open(fpath, "wb").write(fdata)
- # Store new PLC filename
- self.CurrentPLCFilename = NewFileName
- print traceback.format_exc()
- if self.PLCStatus == "Empty":
- self.PLCStatus = "Stopped"
- def MatchMD5(self, MD5):
- last_md5 = open(self._GetMD5FileName(), "r").read()
- def SetTraceVariablesList(self, idxs):
- Call ctype imported function to append
- these indexes to registred variables in PLC debugger
- # keep a copy of requested idx
- self._ResetDebugVariables()
- self._RegisterDebugVariable(idx)
- TypeTranslator = {"BOOL" : ctypes.c_uint8,
- "STEP" : ctypes.c_uint8,
- "TRANSITION" : ctypes.c_uint8,
- "ACTION" : ctypes.c_uint8,
- "SINT" : ctypes.c_int8,
- "USINT" : ctypes.c_uint8,
- "BYTE" : ctypes.c_uint8,
- "INT" : ctypes.c_int16,
- "UINT" : ctypes.c_uint16,
- "WORD" : ctypes.c_uint16,
- "WSTRING" : None, #TODO
- "DINT" : ctypes.c_int32,
- "UDINT" : ctypes.c_uint32,
- "DWORD" : ctypes.c_uint32,
- "LINT" : ctypes.c_int64,
- "ULINT" : ctypes.c_uint64,
- "LWORD" : ctypes.c_uint64,
- "REAL" : ctypes.c_float,
- "LREAL" : ctypes.c_double,
- def GetTraceVariables(self):
- Return a list of variables, corresponding to the list of requiered idx
- tick = self._WaitDebugData()
- typename = ctypes.c_char_p()
- buffer=self._IterDebugData(ctypes.byref(idx), ctypes.byref(typename))
- c_type = TypeTranslator.get(s.value, None)
- res += cast(buffer, POINTER(c_type)).value
+#This file is part of Beremiz, a Integrated Development Environment for +#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. +#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD +#See COPYING file for copyrights details. +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#General Public License for more details. +#You should have received a copy of the GNU General Public +#License along with this library; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +import Pyro.core as pyro +from threading import Timer +import ctypes, os, commands +if os.name in ("nt", "ce"): + from _ctypes import LoadLibrary as dlopen + from _ctypes import FreeLibrary as dlclose +elif os.name == "posix": + from _ctypes import dlopen, dlclose + }.get(sys.platform, "") +class PLCObject(pyro.ObjBase): + def __init__(self, workingdir, daemon, argv): + pyro.ObjBase.__init__(self) + self.argv = [workingdir] + argv # force argv[0] to be "path" to exec... + self.workingdir = workingdir + self.PLCStatus = "Stopped" + self.PLClibraryHandle = None + # Creates fake C funcs proxies + # Get the last transfered PLC if connector must be restart + self.CurrentPLCFilename=open( + self._GetMD5FileName(), + "r").read().strip() + lib_ext + self.PLCStatus = "Empty" + self.CurrentPLCFilename=None + def _GetMD5FileName(self): + return os.path.join(self.workingdir, "lasttransferedPLC.md5") + def _GetLibFileName(self): + return os.path.join(self.workingdir,self.CurrentPLCFilename) + Declare all functions, arguments and return values + self._PLClibraryHandle = dlopen(self._GetLibFileName()) + self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle) + self._startPLC = self.PLClibraryHandle.startPLC + self._startPLC.restype = ctypes.c_int + self._startPLC.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)] + self._stopPLC = self.PLClibraryHandle.stopPLC + self._stopPLC.restype = None + self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables + self._ResetDebugVariables.restype = None + self._RegisterDebugVariable = self.PLClibraryHandle.ResetDebugVariables + self._RegisterDebugVariable.restype = None + self._IterDebugData = self.PLClibraryHandle.IterDebugData + self._IterDebugData.restype = ctypes.c_void_p + self._IterDebugData.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_char_p)] + self._FreeDebugData = self.PLClibraryHandle.FreeDebugData + self._FreeDebugData.restype = None + self._WaitDebugData = self.PLClibraryHandle.WaitDebugData + self._WaitDebugData.restype = ctypes.c_int + print traceback.format_exc() + This is also called by __init__ to create dummy C func proxies + # Forget all refs to library + self._startPLC = lambda:None + self._stopPLC = lambda:None + self._ResetDebugVariables = lambda:None + self._RegisterDebugVariable = lambda x:None + self._IterDebugData = lambda x,y:None + self._FreeDebugData = lambda:None + self.PLClibraryHandle = None + # Unload library explicitely + if getattr(self,"_PLClibraryHandle",None) is not None: + dlclose(self._PLClibraryHandle) + res = self._DetectDirtyLibs() + self._PLClibraryHandle = None + def _DetectDirtyLibs(self): + # Get lib dependencies (for dirty lib detection) + # parasiting libs listed with ldd + badlibs = [ toks.split()[0] for toks in commands.getoutput( + "ldd "+self._GetLibFileName()).splitlines() ] + if badlib[:6] in ["libwx_", + #badhandle = dlopen(badlib, dl.RTLD_NOLOAD) + print "Dirty lib detected :" + badlib + if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped": + c_argv = ctypes.c_char_p * len(self.argv) + if self._LoadNewPLC() and self._startPLC(len(self.argv),c_argv(*self.argv)) == 0: + self.PLCStatus = "Started" + print "_StartPLC did not return 0 !" + self.PLCStatus = "Stopped" + self.PLCStatus = "Dirty" + if self.PLCStatus == "Started": + self.daemon.shutdown(True) + self.daemon.sock.close() + os.execv(sys.executable,[sys.executable]+sys.argv[:]) + # respawn python interpreter + Timer(0.1,self._Reload).start() + def GetPLCstatus(self): + def NewPLC(self, md5sum, data, extrafiles): + print "NewPLC (%s)"%md5sum + if self.PLCStatus in ["Stopped", "Empty", "Dirty"]: + NewFileName = md5sum + lib_ext + extra_files_log = os.path.join(self.workingdir,"extra_files.txt") + os.remove(os.path.join(self.workingdir, + self.CurrentPLCFilename)) + for filename in file(extra_files_log, "r").readlines() + extra_files_log: + os.remove(os.path.join(self.workingdir, filename)) + open(os.path.join(self.workingdir,NewFileName), + # Store new PLC filename based on md5 key + open(self._GetMD5FileName(), "w").write(md5sum) + log = file(extra_files_log, "w") + for fname,fdata in extrafiles: + fpath = os.path.join(self.workingdir,fname) + open(fpath, "wb").write(fdata) + # Store new PLC filename + self.CurrentPLCFilename = NewFileName + print traceback.format_exc() + if self.PLCStatus == "Empty": + self.PLCStatus = "Stopped" + def MatchMD5(self, MD5): + last_md5 = open(self._GetMD5FileName(), "r").read() + def SetTraceVariablesList(self, idxs): + Call ctype imported function to append + these indexes to registred variables in PLC debugger + # keep a copy of requested idx + self._ResetDebugVariables() + self._RegisterDebugVariable(idx) + TypeTranslator = {"BOOL" : ctypes.c_uint8, + "STEP" : ctypes.c_uint8, + "TRANSITION" : ctypes.c_uint8, + "ACTION" : ctypes.c_uint8, + "SINT" : ctypes.c_int8, + "USINT" : ctypes.c_uint8, + "BYTE" : ctypes.c_uint8, + "INT" : ctypes.c_int16, + "UINT" : ctypes.c_uint16, + "WORD" : ctypes.c_uint16, + "WSTRING" : None, #TODO + "DINT" : ctypes.c_int32, + "UDINT" : ctypes.c_uint32, + "DWORD" : ctypes.c_uint32, + "LINT" : ctypes.c_int64, + "ULINT" : ctypes.c_uint64, + "LWORD" : ctypes.c_uint64, + "REAL" : ctypes.c_float, + "LREAL" : ctypes.c_double, + def GetTraceVariables(self): + Return a list of variables, corresponding to the list of requiered idx + tick = self._WaitDebugData() + typename = ctypes.c_char_p() + buffer=self._IterDebugData(ctypes.byref(idx), ctypes.byref(typename)) + c_type = TypeTranslator.get(s.value, None) + res += cast(buffer, POINTER(c_type)).value --- a/targets/Linux/__init__.py Thu Aug 28 15:08:41 2008 +0200
+++ b/targets/Linux/__init__.py Thu Aug 28 16:34:48 2008 +0200
@@ -2,4 +2,4 @@
class Linux_target(toolchain_gcc):
- CustomLDFLAGS = ["-shared"]
+ CustomLDFLAGS = ["-shared", "-lrt"] --- a/targets/Win32/plc_Win32_main.c Thu Aug 28 15:08:41 2008 +0200
+++ b/targets/Win32/plc_Win32_main.c Thu Aug 28 16:34:48 2008 +0200
@@ -31,7 +31,7 @@
void PLC_SetTimer(long long next, long long period)
- LARGE_INTEGER liDueTime;
+ LARGE_INTEGER liDueTime; /* arg 2 of SetWaitableTimer take 100 ns interval*/
liDueTime.QuadPart = next / (-100);
@@ -43,18 +43,45 @@
printf("SetWaitableTimer failed (%d)\n", GetLastError());
+/* Variable used to stop plcloop thread */ + PLC_SetTimer(Ttick,Ttick); if (WaitForSingleObject(PLC_timer, INFINITE) != WAIT_OBJECT_0)
printf("WaitForSingleObject failed (%d)\n", GetLastError());
-int main(int argc,char **argv)
+int startPLC(int argc,char **argv) + unsigned long thread_id = 0; /* Translate PLC's microseconds to Ttick nanoseconds */
Ttick = 1000000 * maxval(common_ticktime__,1);
+ DebugLock = CreateMutex( + NULL, // default security attributes + FALSE, // initially not owned + NULL); // unnamed mutex + printf("CreateMutex error: %d\n", GetLastError()); /* Create a waitable timer */
PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer");
@@ -62,24 +89,40 @@
printf("CreateWaitableTimer failed (%d)\n", GetLastError());
if( __init(argc,argv) == 0 )
printf("Tick Time : %d ms\n", common_ticktime__);
- PLC_SetTimer(Ttick,Ttick);
+ PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id);
- CloseHandle(PLC_timer);
+ WaitForSingleObject(PLC_thread, INFINITE); + CloseHandle(PLC_thread); + CloseHandle(DebugLock); + CloseHandle(PLC_timer); +/* from plc_debugger.c */ + dwWaitResult = WaitForSingleObject( + DebugLock, // handle to mutex + INFINITE); // no time-out interval +/* Called by PLC thread when debug_publish finished + * This is supposed to unlock debugger thread in WaitDebugData*/ +void InitiateDebugTransfer() + /* signal debugger thread to continue*/ + ReleaseMutex(DebugLock);