# HG changeset patch # User edouard # Date 1297933864 -3600 # Node ID 427bf9130d12fe26f60b404ac65e530feefe9f65 # Parent 46abd6b2f639c8837577168cfa222ffed76b9c46 Debug switch (file in CWD). LPC : better MD5 handling, Run button in boot mode, handling data feedback in boot protocol diff -r 46abd6b2f639 -r 427bf9130d12 Beremiz.py --- a/Beremiz.py Thu Feb 03 18:23:24 2011 +0100 +++ b/Beremiz.py Thu Feb 17 10:11:04 2011 +0100 @@ -65,7 +65,12 @@ projectOpen = None buildpath = None - app = wx.PySimpleApp() + if os.path.exists("BEREMIZ_DEBUG"): + __builtins__.BMZ_DBG = True + else : + __builtins__.BMZ_DBG = False + + app = wx.PySimpleApp(redirect=BMZ_DBG) app.SetAppName('beremiz') wx.InitAllImageHandlers() diff -r 46abd6b2f639 -r 427bf9130d12 LPCBeremiz.py --- a/LPCBeremiz.py Thu Feb 03 18:23:24 2011 +0100 +++ b/LPCBeremiz.py Thu Feb 17 10:11:04 2011 +0100 @@ -42,7 +42,12 @@ usage() sys.exit() -app = wx.PySimpleApp() + if os.path.exists("LPC_DEBUG"): + __builtins__.BMZ_DBG = True + else : + __builtins__.BMZ_DBG = False + +app = wx.PySimpleApp(redirect=BMZ_DBG) app.SetAppName('beremiz') wx.InitAllImageHandlers() @@ -370,7 +375,7 @@ elif os.path.isfile(srcpath): shutil.copy2(srcpath, dstpath) -[SIMULATION_MODE, TRANSFER_MODE] = range(2) +[SIMULATION_MODE, ONLINE_MODE] = range(2) class LPCPluginsRoot(PluginsRoot): @@ -489,19 +494,20 @@ if self.StatusTimer and not self.StatusTimer.IsRunning(): # Start the status Timer - self.StatusTimer.Start(milliseconds=500, oneShot=False) + self.StatusTimer.Start(milliseconds=1000, oneShot=False) if self.previous_plcstate=="Started": if self.DebugAvailable() and self.GetIECProgramsAndVariables(): self.logger.write(_("Debug connect matching running PLC\n")) - self._connect_debug() + #TODO re-enable + #self._connect_debug() else: self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n")) elif self.StatusTimer and self.StatusTimer.IsRunning(): self.StatusTimer.Stop() - if self.CurrentMode == TRANSFER_MODE: + if self.CurrentMode == ONLINE_MODE: if self.OnlineMode == "BOOTLOADER": self.BeginTransfer() @@ -607,7 +613,7 @@ ("_build", True), ("_Transfer", True)], "Connected" : [("_Simulate", not simulating), - ("_Run", False), + ("_Run", True), ("_Stop", simulating), ("_build", True), ("_Transfer", True)], @@ -780,9 +786,16 @@ # warns controller that program match self.ProgramTransferred() + def GetLastBuildMD5(self): + builder=self.GetBuilder() + if builder is not None: + return builder.GetBinaryCodeMD5(self.OnlineMode) + else: + return None + def _Transfer(self): if self.CurrentMode is None and self.OnlineMode != "OFF": - self.CurrentMode = TRANSFER_MODE + self.CurrentMode = ONLINE_MODE PluginsRoot._build(self) @@ -814,6 +827,19 @@ self.AbortTransferTimer = None event.Skip() + def _Run(self): + """ + Start PLC + """ + if self.GetIECProgramsAndVariables(): + self._connector.StartPLC() + self.logger.write(_("Starting PLC\n")) + #TODO re-enable + #self._connect_debug() + else: + self.logger.write_error(_("Couldn't start PLC !\n")) + self.UpdateMethodsFromPLCStatus() + #------------------------------------------------------------------------------- # LPCBeremiz Class #------------------------------------------------------------------------------- @@ -1090,6 +1116,8 @@ if idx != -1: line = self.Buffer[:idx+1] self.Buffer = self.Buffer[idx+1:] + if BMZ_DBG: + print "command >"+line return line return "" @@ -1132,8 +1160,8 @@ return eval_res # Command log for debug, for viewing from wxInspector - __builtins__.cmdlog = [] - #cmdlogf=open("bmzcmdlog.txt","w") + if BMZ_DBG: + __builtins__.cmdlog = [] class LPCBeremiz_Cmd(cmd.Cmd): @@ -1421,19 +1449,13 @@ sys.stdout.flush() return - #cmdlogf.write(str((function,line))+'\n') - #cmdlogf.flush() - func = getattr(self, function) res = evaluator(func,*args) - # Keep log for debug - #cmdlogf.write("--->"+str(res)+'\n') - #cmdlogf.flush() - - cmdlog.append((function,line,res)) - if len(cmdlog) > 100: #prevent debug log to grow too much - cmdlog.pop(0) + if BMZ_DBG: + cmdlog.append((function,line,res)) + if len(cmdlog) > 100: #prevent debug log to grow too much + cmdlog.pop(0) if isinstance(res, (StringType, UnicodeType)): self.Log.write(res) diff -r 46abd6b2f639 -r 427bf9130d12 connectors/LPC/LPCAppProto.py --- a/connectors/LPC/LPCAppProto.py Thu Feb 03 18:23:24 2011 +0100 +++ b/connectors/LPC/LPCAppProto.py Thu Feb 17 10:11:04 2011 +0100 @@ -96,6 +96,7 @@ ExchangeData = LPCAppTransaction.GetData if __name__ == "__main__": + __builtins__.BMZ_DBG = True TestConnection = LPCAppProto(6,115200,2) # TestConnection.HandleTransaction(GET_PLCIDTransaction()) TestConnection.HandleTransaction(STARTTransaction()) diff -r 46abd6b2f639 -r 427bf9130d12 connectors/LPC/LPCBootObject.py --- a/connectors/LPC/LPCBootObject.py Thu Feb 03 18:23:24 2011 +0100 +++ b/connectors/LPC/LPCBootObject.py Thu Feb 17 10:11:04 2011 +0100 @@ -37,12 +37,16 @@ self.HandleSerialTransaction(KEEPBOOTINGTransaction()) self.PLCStatus = "Stopped" + def StartPLC(self, debug=False): + self.HandleSerialTransaction(STARTTransaction()) + def NewPLC(self, md5sum, data, extrafiles): self.successfully_transfered = self.HandleSerialTransaction(LOADTransaction(data, self.PLCprint)) return self.successfully_transfered def MatchMD5(self, MD5): - return self.successfully_transfered + res = self.HandleSerialTransaction(CHECKMD5Transaction(MD5)) + return "".join(res).find('FAILED') == -1 def SetTraceVariablesList(self, idxs): diff -r 46abd6b2f639 -r 427bf9130d12 connectors/LPC/LPCBootProto.py --- a/connectors/LPC/LPCBootProto.py Thu Feb 03 18:23:24 2011 +0100 +++ b/connectors/LPC/LPCBootProto.py Thu Feb 17 10:11:04 2011 +0100 @@ -18,27 +18,31 @@ def SetPseudoFile(self, pseudofile): self.pseudofile = pseudofile - def SendData(self): - res = self.pseudofile.write(self.OptData) - return True - - def GetData(self): - pass # not impl - def ExchangeData(self): - pass + self.pseudofile.write(self.OptData) + return map(lambda x:self.pseudofile.readline(), xrange(self.expectedlines)) class KEEPBOOTINGTransaction(LPCBootTransaction): def __init__(self): + self.expectedlines = 2 LPCBootTransaction.__init__(self, "md5\n") - ExchangeData = LPCBootTransaction.SendData + +class STARTTransaction(LPCBootTransaction): + def __init__(self): + self.expectedlines = 0 + LPCBootTransaction.__init__(self, "go\n") + +class CHECKMD5Transaction(LPCBootTransaction): + def __init__(self, md5ref): + self.expectedlines = 5 + LPCBootTransaction.__init__(self, md5ref+"md5\n") class LOADTransaction(LPCBootTransaction): def __init__(self, data, PLCprint): self.PLCprint = PLCprint LPCBootTransaction.__init__(self, data) - def sendDataHook(self): + def ExchangeData(self): #file("fw.bin","w").write(self.OptData) data = self.OptData loptdata = len(self.OptData) @@ -54,9 +58,9 @@ self.PLCprint(".") self.PLCprint("\n") return True - ExchangeData = sendDataHook if __name__ == "__main__": + __builtins__.BMZ_DBG = True TestConnection = LPCBootProto(2,115200,1200) mystr=file("fw.bin").read() def mylog(blah): diff -r 46abd6b2f639 -r 427bf9130d12 connectors/LPC/LPCProto.py --- a/connectors/LPC/LPCProto.py Thu Feb 03 18:23:24 2011 +0100 +++ b/connectors/LPC/LPCProto.py Thu Feb 17 10:11:04 2011 +0100 @@ -1,6 +1,7 @@ import serial import exceptions from threading import Lock +import time class LPCProtoError(exceptions.Exception): """Exception class""" @@ -14,29 +15,45 @@ def __init__(self, port, rate, timeout): # serialize access lock self.TransactionLock = Lock() - # open serial port -# self.serialPort = serial.Serial( port, rate, timeout = timeout ) - # Debugging serial stuff - self.serialPort = serial.Serial( port, rate, timeout = timeout ) -# class myser: -# def read(self_,cnt): -# res = self._serialPort.read(cnt) -# if len(res) > 16: -# print "Recv :", map(hex,map(ord,res[:16])), "[...]" -# else: -# print "Recv :", map(hex,map(ord,res)) -# -# return res -# def write(self_, str): -# if len(str) > 16: -# print "Send :", map(hex,map(ord,str[:16])), "[...]" -# else: -# print "Send :", map(hex,map(ord,str)) -# self._serialPort.write(str) -# def flush(self_): -# self._serialPort.flush() -# self.serialPort = myser() - # start with empty + if BMZ_DBG: + # Debugging serial stuff + self._serialPort = serial.Serial( port, rate, timeout = timeout, writeTimeout = timeout ) + class myser: + def readline(self_): + res = self._serialPort.readline() + print 'Recv :"', res, '"' + return res + + def read(self_,cnt): + res = self._serialPort.read(cnt) + if len(res) > 16: + print "Recv :", map(hex,map(ord,res[:16])), "[...]" + else: + print "Recv :", map(hex,map(ord,res)) + + return res + def write(self_, string): + lstr=len(string) + if lstr > 16: + print "Send :", map(hex,map(ord,string[:16])), "[...]" + else: + print "Send :", map(hex,map(ord,string)) + return self._serialPort.write(string) + # while len(string)>0: + # i = self._serialPort.write(string[:4096]) + # print ".", + # string = string[i:] + # print + #return lstr + def flush(self_): + return self._serialPort.flush() + def close(self_): + self._serialPort.close() + self.serialPort = myser() + else: + # open serial port + self.serialPort = serial.Serial( port, rate, timeout = timeout ) + # start with empty buffer self.serialPort.flush() def __del__(self): diff -r 46abd6b2f639 -r 427bf9130d12 targets/LPC/__init__.py --- a/targets/LPC/__init__.py Thu Feb 03 18:23:24 2011 +0100 +++ b/targets/LPC/__init__.py Thu Feb 17 10:11:04 2011 +0100 @@ -1,22 +1,56 @@ -import os -from subprocess import Popen,PIPE -from .. import toolchain_makefile -import hashlib - -class LPC_target(toolchain_makefile): - extension = ".ld" - DebugEnabled = False - - def GetBinaryCode(self): - """Returns ready to send signed + sized intel formated hex program""" - try: - size = int(Popen( - ['arm-elf-size','-B',os.path.join(self.buildpath,"ArmPLC_rom.elf")], - stdout=PIPE).communicate()[0].splitlines()[1].split()[0]) - res = "&" + hashlib.md5(open(os.path.join(self.buildpath, "ArmPLC_rom.bin"), "rb").read(size)).hexdigest() + '\n' +\ - "$" + str(size) + '\n' +\ - open(os.path.join(self.buildpath, "ArmPLC_rom.hex"), "r").read() - return res - except Exception, e: - return None - +import os +from subprocess import Popen,PIPE +from .. import toolchain_makefile +import hashlib + +class LPC_target(toolchain_makefile): + #extension = ".ld" + #DebugEnabled = False + def __init__(self, PluginsRootInstance): + self.binmd5key = None + toolchain_makefile.__init__(self, PluginsRootInstance) + + def _GetBinMD5FileName(self): + return os.path.join(self.buildpath, "lastbuildPLCbin.md5") + + def _get_md5_header(self): + """Returns signature header""" + size = int(Popen( + ['arm-elf-size','-B',os.path.join(self.buildpath,"ArmPLC_rom.elf")], + stdout=PIPE).communicate()[0].splitlines()[1].split()[0]) + res = "&" + hashlib.md5(open(os.path.join(self.buildpath, "ArmPLC_rom.bin"), "rb").read(size)).hexdigest() + '\n' +\ + "$" + str(size) + '\n' + return res + + def GetBinaryCode(self): + """Returns ready to send signed + sized intel formated hex program""" + try: + res = self._get_md5_header() +\ + open(os.path.join(self.buildpath, "ArmPLC_rom.hex"), "r").read() + return res + except Exception, e: + return None + + def _get_cached_md5_header(self): + if self.binmd5key is not None: + return self.binmd5key + else: + try: + return open(self._GetMD5FileName(), "r").read() + except IOError, e: + return None + + def GetBinaryCodeMD5(self, mode): + if mode == "BOOTLOADER": + return self._get_cached_md5_header() + else: + return toolchain_makefile.GetBinaryCodeMD5(self) + + def build(self): + res = toolchain_makefile.build(self) + self.binmd5key = self._get_md5_header() + f = open(self._GetBinMD5FileName(), "w") + f.write(self.binmd5key) + f.close() + return res + diff -r 46abd6b2f639 -r 427bf9130d12 targets/toolchain_makefile.py --- a/targets/toolchain_makefile.py Thu Feb 03 18:23:24 2011 +0100 +++ b/targets/toolchain_makefile.py Thu Feb 17 10:11:04 2011 +0100 @@ -1,74 +1,74 @@ -import os, re -from wxPopen import ProcessLogger -import hashlib - -import time - -includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*') - -class toolchain_makefile(): - def __init__(self, PluginsRootInstance): - self.PluginsRootInstance = PluginsRootInstance - self.md5key = None - self.buildpath = None - self.SetBuildPath(self.PluginsRootInstance._getBuildPath()) - - def SetBuildPath(self, buildpath): - self.buildpath = buildpath - - def GetBinaryCode(self): - 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: - 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() - props = self.PluginsRootInstance.GetProjectProperties() - self.md5key += '#'.join([props[key] for key in ['companyName', - 'projectName', - 'productName']]) - self.md5key += '#'+','.join(map(str,time.localtime())) - # 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), - "md5": '"'+self.md5key+'"' - } - - target = self.PluginsRootInstance.GetTarget().getcontent()["value"] - command = target.getCommand().split(' ') +\ - [target.getBuildPath()] +\ - [arg % beremizcommand for arg in target.getArguments().split(' ')] +\ - target.getRule().split(' ') - - # Call Makefile to build PLC code and link it with target specific code - status, result, err_result = ProcessLogger(self.PluginsRootInstance.logger, - command).spin() - if status : - self.PluginsRootInstance.logger.write_error(_("C compilation of %s failed.\n")) - return False - return True +import os, re +from wxPopen import ProcessLogger +import hashlib + +import time + +includes_re = re.compile('\s*#include\s*["<]([^">]*)[">].*') + +class toolchain_makefile(): + def __init__(self, PluginsRootInstance): + self.PluginsRootInstance = PluginsRootInstance + self.md5key = None + self.buildpath = None + self.SetBuildPath(self.PluginsRootInstance._getBuildPath()) + + def SetBuildPath(self, buildpath): + self.buildpath = buildpath + + def GetBinaryCode(self): + 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 IOError, e: + return None + + def build(self): + srcfiles= [] + cflags = [] + for Location, CFilesAndCFLAGS, DoCalls in self.PluginsRootInstance.LocationCFilesAndCFLAGS: + 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() + props = self.PluginsRootInstance.GetProjectProperties() + self.md5key += '#'.join([props[key] for key in ['companyName', + 'projectName', + 'productName']]) + self.md5key += '#' #+','.join(map(str,time.localtime())) + # 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), + "md5": '"'+self.md5key+'"' + } + + target = self.PluginsRootInstance.GetTarget().getcontent()["value"] + command = target.getCommand().split(' ') +\ + [target.getBuildPath()] +\ + [arg % beremizcommand for arg in target.getArguments().split(' ')] +\ + target.getRule().split(' ') + + # Call Makefile to build PLC code and link it with target specific code + status, result, err_result = ProcessLogger(self.PluginsRootInstance.logger, + command).spin() + if status : + self.PluginsRootInstance.logger.write_error(_("C compilation of %s failed.\n")) + return False + return True