--- a/py_ext/PythonFileCTNMixin.py Wed May 15 08:20:17 2013 +0200
+++ b/py_ext/PythonFileCTNMixin.py Wed May 15 17:13:49 2013 +0900
@@ -55,21 +55,28 @@
def CTNGenerate_C(self, buildpath, locations):
- current_location = self.GetCurrentLocation()
- # define a unique name for the generated C file
- location_str = "_".join(map(lambda x:str(x), current_location))
-
-
- # Generate Beremiz python runtime variables code
- config = self.GetCTRoot().GetProjectConfigNames()[0]
- variables_str = ""
- for variable in self.CodeFile.variables.variable:
- global_name = "%s_%s" % (config.upper(), variable.getname().upper())
- variables_str += "# global_var:%s python_var:%s type:%s initial:%s\n" % (
- global_name,
- variable.getname(),
- variable.gettype(),
- str(variable.getinitial()))
+ # location string for that CTN
+ location_str = "_".join(map(lambda x:str(x),
+ self.GetCurrentLocation()))
+ configname = self.GetCTRoot().GetProjectConfigNames()[0]
+
+
+ # python side PLC global variables access stub
+ globalstubs = "\n".join(["""\
+_%(name)s_ctype, _%(name)s_unpack, _%(name)s_pack = \\
+ TypeTranslator["%(IECtype)s"]
+_PySafeGetPLCGlob_%(name)s = PLCBinary.__SafeGetPLCGlob_%(name)s
+_PySafeGetPLCGlob_%(name)s.restype = _%(name)s_ctype
+_PySafeGetPLCGlob_%(name)s.argtypes = []
+_PySafeSetPLCGlob_%(name)s = PLCBinary.__SafeSetPLCGlob_%(name)s
+_PySafeSetPLCGlob_%(name)s.restype = None
+_PySafeSetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)]
+""" % { "name": variable.getname(),
+ "configname": configname.upper(),
+ "uppername": variable.getname().upper(),
+ "IECtype": variable.gettype(),
+ "initial" : str(variable.getinitial())}
+ for variable in self.CodeFile.variables.variable])
# Runtime calls (start, stop, init, and cleanup)
rtcalls = ""
@@ -82,76 +89,117 @@
sectiontext.strip().replace('\n', '\n ')+"\n"
else:
rtcalls += " pass\n\n"
-
- text = """\
+
+ globalsection = self.GetSection("globals")
+
+ PyFileContent = """\
#!/usr/bin/env python
# -*- coding: utf-8 -*-
## Code generated by Beremiz python mixin confnode
##
## Code for PLC global variable access
-%s
+from targets.typemapping import TypeTranslator
+import ctypes
+%(globalstubs)s
## User code in "global" scope
-%s
+%(globalsection)s
## Beremiz python runtime calls
-%s
-
-"""%( # variables
- variables_str,
- # globals
- self.GetSection("globals"),
- # Beremiz python runtime functions
- rtcalls)
-
+%(rtcalls)s
+
+""" % locals()
+
+ # write generated content to python file
runtimefile_path = os.path.join(buildpath,
"runtime_%s.py"%location_str)
runtimefile = open(runtimefile_path, 'w')
- runtimefile.write(text.encode('utf-8'))
+ runtimefile.write(PyFileContent.encode('utf-8'))
runtimefile.close()
- text = """\
+ # C code for safe global variables access
+
+ vardecfmt = """\
+extern __%(IECtype)s_t %(configname)s__%(uppername)s;
+%(IECtype)s __%(name)s_rbuffer = %(initial)s;
+%(IECtype)s __%(name)s_wbuffer;
+long __%(name)s_rlock = 0;
+long __%(name)s_wlock = 0;
+int __%(name)s_wbuffer_written = 0;
+%(IECtype)s __SafeGetPLCGlob_%(name)s(){
+ %(IECtype)s res;
+ while(AtomicCompareExchange(&__%(name)s_rlock, 0, 1));
+ res = __%(name)s_rbuffer;
+ AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
+ return res;
+}
+__SafeSetPLCGlob_%(name)s(%(IECtype)s *value){
+ while(AtomicCompareExchange(&__%(name)s_wlock, 0, 1));
+ __%(name)s_wbuffer = *value;
+ __%(name)s_wbuffer_written = 1;
+ AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
+}
+
+"""
+ varretfmt = """\
+ if(!AtomicCompareExchange(&__%(name)s_wlock, 0, 1)){
+ if(__%(name)s_wbuffer_written == 1){
+ %(configname)s__%(uppername)s.value = __%(name)s_wbuffer;
+ __%(name)s_wbuffer_written = 0;
+ }
+ AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
+ }
+"""
+ varpubfmt = """\
+ if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
+ __%(name)s_rbuffer = %(configname)s__%(uppername)s.value;
+ AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
+ }
+"""
+
+ vardec, varret, varpub = map("\n".join, zip(*[
+ map(lambda f : f % varinfo,
+ (vardecfmt, varretfmt, varpubfmt))
+ for varinfo in map(lambda variable : {
+ "name": variable.getname(),
+ "configname": configname.upper(),
+ "uppername": variable.getname().upper(),
+ "IECtype": "IEC_%s"%variable.gettype(),
+ "initial" : str(variable.getinitial())},
+ self.CodeFile.variables.variable)]))
+
+ PyCFileContent = """\
/*
* Code generated by Beremiz py_ext confnode
* for safe global variables access
*/
#include "iec_types_all.h"
-"""
-
- # Adding variables
- text += "/* User variables reference */\n"
- for variable in self.CodeFile.variables.variable:
- var_infos = {
- "name": variable.getname(),
- "global": "%s__%s" % (config.upper(),
- variable.getname().upper()),
- "type": "__IEC_%s_t" % variable.gettype()}
- text += "extern %(type)s %(global)s;\n" % var_infos
- text += "%(type)s __buffer_%(name)s;\n" % var_infos
- text += "\n"
-
- # Adding Beremiz confnode functions
- text += "/* Beremiz confnode functions */\n"
- text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
- text += "/*TODO*/\n"
- text += " return 0;\n}\n\n"
-
- text += "void __cleanup_%s(void)\n{\n"%location_str
- text += "/*TODO*/\n"
- text += "\n}\n\n"
-
- text += "void __retrieve_%s(void)\n{\n"%location_str
- text += "/*TODO*/\n"
- text += "\n}\n\n"
-
- text += "void __publish_%s(void)\n{\n"%location_str
- text += "/*TODO*/\n"
- text += "\n}\n\n"
+#include "beremiz.h"
+
+/* User variables reference */
+%(vardec)s
+
+/* Beremiz confnode functions */
+int __init_%(location_str)s(int argc,char **argv){
+ return 0;
+}
+
+void __cleanup_%(location_str)s(void){
+}
+
+void __retrieve_%(location_str)s(void){
+%(varret)s
+}
+
+void __publish_%(location_str)s(void){
+%(varpub)s
+}
+""" % locals()
Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c"%location_str)
pycfile = open(Gen_PyCfile_path,'w')
- pycfile.write(text)
+ pycfile.write(PyCFileContent)
pycfile.close()
matiec_flags = '"-I%s"'%os.path.abspath(
--- a/runtime/PLCObject.py Wed May 15 08:20:17 2013 +0200
+++ b/runtime/PLCObject.py Wed May 15 17:13:49 2013 +0900
@@ -264,6 +264,14 @@
self.python_runtime_vars["_runtime_%s"%methodname] = []
self.python_runtime_vars["PLCObject"] = self
self.python_runtime_vars["PLCBinary"] = self.PLClibraryHandle
+ class PLCSafeGlobals:
+ def __getattr__(self, name):
+ r = globals()["_PySafeGetPLCGlob_"+name]()
+ return globals()["_"+name+"_unpack"](r)
+ def __setattr__(self, name, value):
+ v = globals()["_"+name+"_pack"](c_type,value)
+ globals()["_PySafeSetPLCGlob_"+name](ctypes.byref(v))
+ self.python_runtime_vars["PLCGlobals"] = PLCSafeGlobals()
try:
for filename in os.listdir(self.workingdir):
name, ext = os.path.splitext(filename)