# 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"]