Debug switch (file in CWD). LPC : better MD5 handling, Run button in boot mode, handling data feedback in boot protocol
authoredouard
Thu, 17 Feb 2011 10:11:04 +0100
changeset 571 427bf9130d12
parent 570 46abd6b2f639
child 572 c965548cb6f7
Debug switch (file in CWD). LPC : better MD5 handling, Run button in boot mode, handling data feedback in boot protocol
Beremiz.py
LPCBeremiz.py
connectors/LPC/LPCAppProto.py
connectors/LPC/LPCBootObject.py
connectors/LPC/LPCBootProto.py
connectors/LPC/LPCProto.py
targets/LPC/__init__.py
targets/toolchain_makefile.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()
     
--- 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)
--- 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())
--- 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):
--- 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):
--- 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):
--- 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
+
--- 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