# HG changeset patch # User edouard # Date 1260545960 -3600 # Node ID 73ecb803d8af717b1975171300af95e24e9e3c0c # Parent bf6f623d745006bcd44d8af6b47aa92dd68fd9d5 Revamped LPC connector and toolchain diff -r bf6f623d7450 -r 73ecb803d8af connectors/LPC/LPCObject.py --- a/connectors/LPC/LPCObject.py Fri Dec 11 13:04:22 2009 +0100 +++ b/connectors/LPC/LPCObject.py Fri Dec 11 16:39:20 2009 +0100 @@ -22,35 +22,60 @@ #License along with this library; if not, write to the Free Software #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -from threading import Timer, Thread, Lock import ctypes, os, commands, types, sys -import traceback from LPCProto import * class LPCObject(): - def __init__(self,pluginsroot): - self.PLCStatus = "Stopped" + def __init__(self,pluginsroot, location): + self.PLCStatus = "Disconnected" self.pluginsroot = pluginsroot self.PLCprint = pluginsroot.logger.write - self.SerialConnection = None - self.StorageConnection = None self._Idxs = [] - - def HandleSerialTransaction(self, transaction): - if self.SerialConnection is None: + self.UpdateLocation(location) + + def UpdateLocation(self, location): + # Is that a comport ? + if len(location) == 5 and\ + location.startswith("COM") and \ + location[3].isdigit() and \ + location[4]==":" : + self.StorageConnection = None try: - self.SerialConnection = LPCProto(6,115200,2) + comport = int(location[3]) - 1 + self.SerialConnection = LPCProto(comport,#number + 115200, #speed + 2) #timeout + # This will update status + self.HandleSerialTransaction(IDLETransaction()) except Exception,e: self.pluginsroot.logger.write_error(str(e)+"\n") self.SerialConnection = None - return "Disconnected", res - try: - return self.SerialConnection.HandleTransaction(transaction) - except LPCError,e: - #pluginsroot.logger.write_error(traceback.format_exc()) - self.pluginsroot.logger.write_error(str(e)+"\n") + self.PLCStatus = "Disconnected" + # or a drive unit ? + elif len(location)==2 and \ + location[0].isalpha() and \ + location[1] == ':' : self.SerialConnection = None - return "Disconnected", res + if os.path.exist(location): + self.StorageConnection = location + self.PLCStatus = "Stopped" + else: + self.pluginsroot.logger.write_error("Drive "+ + location+ + " do not exist !\n") + self.StorageConnection = None + self.PLCStatus = "Disconnected" + + def HandleSerialTransaction(self, transaction): + if self.SerialConnection is not None: + try: + self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction) + return res + except LPCError,e: + self.pluginsroot.logger.write_error(str(e)+"\n") + self.SerialConnection = None + self.PLCStatus = "Disconnected" + return None def StartPLC(self, debug=False): PLCprint("StartPLC") @@ -64,14 +89,14 @@ pass def GetPLCstatus(self): - status,data = self.HandleSerialTransaction(IDLETransaction()) - return status + self.HandleSerialTransaction(IDLETransaction()) + return self.PLCStatus def NewPLC(self, md5sum, data, extrafiles): pass def MatchMD5(self, MD5): - status,data = self.HandleSerialTransaction(PLCIDTransaction()) + data = self.HandleSerialTransaction(PLCIDTransaction()) return data == MD5 class IEC_STRING(ctypes.Structure): @@ -104,12 +129,6 @@ } def SetTraceVariablesList(self, idxs): - self._Idxs = idxs[:] - status,data = self.HandleSerialTransaction( - SET_TRACE_VARIABLETransaction( - ''.join(map(chr,idx)))) - - def SetTraceVariablesList(self, idxs): """ Call ctype imported function to append these indexes to registred variables in PLC debugger @@ -132,7 +151,7 @@ buff += idxstr + forced_type_size_str + forcestr else: buff += idxstr + chr(0) - status,data = self.HandleSerialTransaction( + data = self.HandleSerialTransaction( SET_TRACE_VARIABLETransaction(buff)) else: self._Idxs = [] @@ -141,33 +160,32 @@ """ Return a list of variables, corresponding to the list of required idx """ - if self.PLCStatus == "Started": - res=[] - tick = ctypes.c_uint32() - size = ctypes.c_uint32() - buffer = ctypes.c_void_p() - offset = 0 - if self.PLClibraryLock.acquire(False) and \ - self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 : - if size.value: - for idx, iectype, forced in self._Idxs: - cursor = ctypes.c_void_p(buffer.value + offset) - c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None)) - if c_type is not None and offset < size: - res.append(unpack_func(ctypes.cast(cursor, - ctypes.POINTER(c_type)).contents)) - offset += ctypes.sizeof(c_type) - else: - if c_type is None: - PLCprint("Debug error - " + iectype + " not supported !") - if offset >= size: - PLCprint("Debug error - buffer too small !") - break - self._FreeDebugData() - self.PLClibraryLock.release() - if offset and offset == size.value: + offset = 0 + strbuf = self.HandleSerialTransaction( + GET_TRACE_VARIABLETransaction()) + size = len(strbuf) - 4 + if size > 0 and self.PLCStatus == "Started": + tick = ctypes.cast( + ctypes.c_char_p(strbuf[:4]), + ctypes.POINTER(ctypes.c_int)).contents + buffer = ctypes.cast( + ctypes.c_char_p(strbuf[4:]), + ctypes.c_void_p) + for idx, iectype, forced in self._Idxs: + cursor = ctypes.c_void_p(buffer.value + offset) + c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None)) + if c_type is not None and offset < size: + res.append(unpack_func(ctypes.cast(cursor, + ctypes.POINTER(c_type)).contents)) + offset += ctypes.sizeof(c_type) + else: + if c_type is None: + PLCprint("Debug error - " + iectype + " not supported !") + if offset >= size: + PLCprint("Debug error - buffer too small !") + break + if offset and offset == size: return self.PLCStatus, tick.value, res - elif size.value: - PLCprint("Debug error - wrong buffer unpack !") + PLCprint("Debug error - wrong buffer unpack !") return self.PLCStatus, None, None diff -r bf6f623d7450 -r 73ecb803d8af connectors/LPC/LPCProto.py --- a/connectors/LPC/LPCProto.py Fri Dec 11 13:04:22 2009 +0100 +++ b/connectors/LPC/LPCProto.py Fri Dec 11 16:39:20 2009 +0100 @@ -6,9 +6,8 @@ MAX_PACKET_SIZE=64 -LPC_STATUS=dict(STARTED = 0x01, - STOPPED = 0x02, - DEBUG = 0x03) +LPC_STATUS={0x01 : "Started", + 0x02 : "Stopped"} class LPCError(exceptions.Exception): """Exception class""" @@ -40,8 +39,6 @@ self.serialPort = myser() # start with empty self.serialPort.flush() - # handshake - self.HandleTransaction(IDLETransaction()) def HandleTransaction(self, transaction): self.TransactionLock.acquire() @@ -56,7 +53,7 @@ raise LPCError("LPC transaction error - controller did not answer as expected") finally: self.TransactionLock.release() - return current_plc_status, res + return LPC_STATUS.get(current_plc_status,"Broken"), res class LPCTransaction: def __init__(self, command, optdata = ""): @@ -133,11 +130,6 @@ LPCTransaction.__init__(self, 0x05) ExchangeData = LPCTransaction.GetData -class SET_FORCED_VARIABLETransaction(LPCTransaction): - def __init__(self, data): - LPCTransaction.__init__(self, 0x06, data) - ExchangeData = LPCTransaction.SendData - class GET_PLCIDTransaction(LPCTransaction): def __init__(self): LPCTransaction.__init__(self, 0x07) @@ -150,17 +142,18 @@ # TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction( # "\x03\x00\x00\x00"*200)) # TestConnection.HandleTransaction(STARTTransaction()) - TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction( - "\x01\x00\x00\x00"+ - "\x04"+ - "\x01\x02\x02\x04"+ - "\x01\x00\x00\x00"+ - "\x08"+ - "\x01\x02\x02\x04"+ - "\x01\x02\x02\x04"+ - "\x01\x00\x00\x00"+ - "\x04"+ - "\x01\x02\x02\x04")) + while True: + TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction( + "\x01\x00\x00\x00"+ + "\x04"+ + "\x01\x02\x02\x04"+ + "\x01\x00\x00\x00"+ + "\x08"+ + "\x01\x02\x02\x04"+ + "\x01\x02\x02\x04"+ + "\x01\x00\x00\x00"+ + "\x04"+ + "\x01\x02\x02\x04")) #status,res = TestConnection.HandleTransaction(GET_TRACE_VARIABLETransaction()) #print len(res) #print "GOT : ", map(hex, map(ord, res)) diff -r bf6f623d7450 -r 73ecb803d8af connectors/LPC/__init__.py --- a/connectors/LPC/__init__.py Fri Dec 11 13:04:22 2009 +0100 +++ b/connectors/LPC/__init__.py Fri Dec 11 16:39:20 2009 +0100 @@ -18,15 +18,20 @@ #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 traceback import LPCObject +permanant_connector = None def LPC_connector_factory(uri, pluginsroot): """ This returns the connector to LPC style PLCobject """ - pluginsroot.logger.write(_("Connecting to URI : %s\n")%uri) - return LPCObject() + global permanant_connector + if permanant_connector is None: + permanant_connector = LPCObject(pluginsroot,location) + else: + servicetype, location = uri.split("://") + permanant_connector.UpdateLocation(location) + return permanant_connector diff -r bf6f623d7450 -r 73ecb803d8af targets/LPC/__init__.py --- a/targets/LPC/__init__.py Fri Dec 11 13:04:22 2009 +0100 +++ b/targets/LPC/__init__.py Fri Dec 11 16:39:20 2009 +0100 @@ -3,5 +3,3 @@ class LPC_target(toolchain_makefile): extension = ".ld" DebugEnabled = False - def getBuilderLDFLAGS(self): - return toolchain_makefile.getBuilderLDFLAGS(self) diff -r bf6f623d7450 -r 73ecb803d8af targets/XSD_toolchain_makefile --- a/targets/XSD_toolchain_makefile Fri Dec 11 13:04:22 2009 +0100 +++ b/targets/XSD_toolchain_makefile Fri Dec 11 16:39:20 2009 +0100 @@ -1,6 +1,6 @@ - + diff -r bf6f623d7450 -r 73ecb803d8af targets/toolchain_makefile.py --- a/targets/toolchain_makefile.py Fri Dec 11 13:04:22 2009 +0100 +++ b/targets/toolchain_makefile.py Fri Dec 11 16:39:20 2009 +0100 @@ -5,26 +5,63 @@ includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*') -class toolchain_makefile(toolchain_gcc): - """ - This abstract class contains GCC specific code. - It cannot be used as this and should be inherited in a target specific - class such as target_linux or target_win32 - """ +class toolchain_makefile(): + def __init__(self, PluginsRootInstance): + self.PluginsRootInstance = PluginsRootInstance + self.md5key = None + self.buildpath = None + self.SetBuildPath(self.PluginsRootInstance._getBuildPath()) + + def getTarget(self): + target = self.PluginsRootInstance.BeremizRoot.getTargetType() + if target.getcontent() is None: + target = self.PluginsRootInstance.GetDefaultTarget() + return target + + def SetBuildPath(self, buildpath): + self.buildpath = buildpath + self.exe_path = os.path.join(self.buildpath, "ArmPLC_rom.bin") + self.md5_path = os.path.join(self.buildpath, "ArmPLC.md5") + + def GetBinaryCode(self): + try: + return open(self.exe_path, "rb").read() + except Exception, e: + return None + + def _GetMD5FileName(self): + return os.path.join(self.buildpath, "lastbuildPLC.md5") + + def GetBinaryCodeMD5(self): + if self.md5key is not None: + return self.md5key + else: + try: + return open(self._GetMD5FileName(), "r").read() + except Exception, e: + return None def build(self): srcfiles= [] cflags = [] for Location, CFilesAndCFLAGS, DoCalls in self.PluginsRootInstance.LocationCFilesAndCFLAGS: - # Get CFiles list to give it to makefile + wholesrcdata = "" + # Get CFiles list to give it to makefile for CFile, CFLAGS in CFilesAndCFLAGS: CFileName = os.path.basename(CFile) + wholesrcdata += open(CFile, "r").read() srcfiles.append(CFileName) if CFLAGS not in cflags: cflags.append(CFLAGS) + self.md5key = hashlib.md5(wholesrcdata).hexdigest() + # Store new PLC filename based on md5 key + f = open(self._GetMD5FileName(), "w") + f.write(self.md5key) + f.close() beremizcommand = {"src": ' '.join(srcfiles), - "cflags": ' '.join(cflags) + "cflags": ' '.join(cflags), + "md5": self.md5key } target = self.getTarget().getcontent()["value"]