--- a/plugger.py Tue Dec 23 19:31:28 2008 +0100
+++ b/plugger.py Tue Dec 23 19:37:44 2008 +0100
@@ -1078,6 +1078,23 @@
+ def Generate_plc_python(self): + Generate trace/debug code out of PLC variable list + self.GetIECProgramsAndVariables() + python_eval_fb_list = [] + for v in self._VariablesList : + if v["vartype"] == "FB" and v["type"] == "PYTHON_EVAL": + python_eval_fb_list.append(v) + python_eval_fb_count = len(python_eval_fb_list) + python_code = targets.code("plc_python") % { + "python_eval_fb_count": python_eval_fb_count} def Generate_plc_common_main(self):
Use plugins layout given in LocationCFilesAndCFLAGS to
@@ -1175,6 +1192,8 @@
for generator, filename, name in [
(self.Generate_plc_debugger, "plc_debugger.c", "Debugger"),
+ # IEC<->python gateway code + (self.Generate_plc_python, "plc_python.c", "IEC-Python gateway"), # init/cleanup/retrieve/publish, run and align code
(self.Generate_plc_common_main,"plc_common_main.c","Common runtime")]:
@@ -1408,7 +1427,7 @@
# This will block thread if more than one call is waiting
elif debug_vars is not None:
wx.CallAfter(self.logger.write_warning,
- "debug data not coherent %d != %d"%(len(debug_vars), len(self.TracedIECPath)))
+ "Debug data not coherent %d != %d\n"%(len(debug_vars), len(self.TracedIECPath))) #wx.CallAfter(self.logger.write, "Debugger unavailable\n")
--- a/runtime/PLCObject.py Tue Dec 23 19:31:28 2008 +0100
+++ b/runtime/PLCObject.py Tue Dec 23 19:37:44 2008 +0100
@@ -23,8 +23,9 @@
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-from threading import Timer
+from threading import Timer, Thread import ctypes, os, commands
if os.name in ("nt", "ce"):
from _ctypes import LoadLibrary as dlopen
@@ -107,6 +108,10 @@
self._resumeDebug = self.PLClibraryHandle.resumeDebug
self._resumeDebug.restype = None
+ self._PythonIterator = self.PLClibraryHandle.PythonIterator + self._PythonIterator.restype = ctypes.c_char_p + self._PythonIterator.argtypes = [ctypes.c_char_p] @@ -128,6 +133,7 @@
self._WaitDebugData = lambda:-1
self._suspendDebug = lambda:None
self._resumeDebug = lambda:None
+ self._PythonIterator = lambda:"" self.PLClibraryHandle = None
# Unload library explicitely
if getattr(self,"_PLClibraryHandle",None) is not None:
@@ -163,6 +169,18 @@
+ def PythonThreadProc(self): + print "PythonThreadProc started" + while self.PLCStatus == "Started": + cmd = self._PythonIterator(res) + print "_PythonIterator(", res, ") -> ", cmd + res = "#EXCEPTION : "+str(e) + print "PythonThreadProc finished" def StartPLC(self, debug=False):
@@ -174,6 +192,8 @@
self.PLCStatus = "Started"
if self.statuschange is not None:
self.statuschange(self.PLCStatus)
+ self.PythonThread = Thread(target=self.PythonThreadProc) + self.PythonThread.start() print "_StartPLC did not return 0 !"
@@ -270,6 +290,13 @@
self._RegisterDebugVariable(idx)
+ class IEC_STRING(ctypes.Structure): + Must be changed according to changes in iec_types.h + _fields_ = [("len", ctypes.c_uint8), + ("body", ctypes.c_char * 40)] TypeTranslator = {"BOOL" : (ctypes.c_uint8, lambda x:x.value!=0),
"STEP" : (ctypes.c_uint8, lambda x:x.value),
@@ -278,7 +305,7 @@
"SINT" : (ctypes.c_int8, lambda x:x.value),
"USINT" : (ctypes.c_uint8, lambda x:x.value),
"BYTE" : (ctypes.c_uint8, lambda x:x.value),
- "STRING" : (None, None),#TODO
+ "STRING" : (IEC_STRING, lambda x:x.body[:x.len]), "INT" : (ctypes.c_int16, lambda x:x.value),
"UINT" : (ctypes.c_uint16, lambda x:x.value),
"WORD" : (ctypes.c_uint16, lambda x:x.value),
--- a/targets/Linux/plc_Linux_main.c Tue Dec 23 19:31:28 2008 +0100
+++ b/targets/Linux/plc_Linux_main.c Tue Dec 23 19:37:44 2008 +0100
@@ -1,3 +1,7 @@
@@ -5,16 +9,14 @@
+/* provided by POUS.C */ +extern int common_ticktime__; long AtomicCompareExchange(long* atomicvar,long compared, long exchange)
return __sync_val_compare_and_swap(atomicvar, compared, exchange);
-//long AtomicExchange(long* atomicvar,long exchange)
-// return __sync_lock_test_and_set(atomicvar, exchange);
void PLC_GetTime(IEC_TIME *CURRENT_TIME)
clock_gettime(CLOCK_REALTIME, CURRENT_TIME);
@@ -64,9 +66,12 @@
-static pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t python_wait_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t python_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t debug_wait_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define maxval(a,b) ((a>b)?a:b) int startPLC(int argc,char **argv)
@@ -79,7 +84,8 @@
sigev.sigev_notify_attributes = NULL;
sigev.sigev_notify_function = PLC_timer_notify;
- pthread_mutex_lock(&wait_mutex);
+ pthread_mutex_lock(&debug_wait_mutex); + pthread_mutex_lock(&python_wait_mutex); timer_create (CLOCK_REALTIME, &sigev, &PLC_timer);
if( __init(argc,argv) == 0 ){
@@ -111,7 +117,7 @@
timer_delete (PLC_timer);
- pthread_mutex_unlock(&wait_mutex);
+ pthread_mutex_unlock(&debug_wait_mutex); @@ -119,7 +125,7 @@
/* Wait signal from PLC thread */
- pthread_mutex_lock(&wait_mutex);
+ pthread_mutex_lock(&debug_wait_mutex); @@ -127,25 +133,49 @@
* This is supposed to unlock debugger thread in WaitDebugData*/
void InitiateDebugTransfer()
- /* Leave debugger section */
- pthread_mutex_unlock(&debug_mutex);
/* signal debugger thread it can read data */
- pthread_mutex_unlock(&wait_mutex);
+ pthread_mutex_unlock(&debug_wait_mutex);
/* Prevent PLC to enter debug code */
pthread_mutex_lock(&debug_mutex);
/* Let PLC enter debug code */
pthread_mutex_unlock(&debug_mutex);
+int WaitPythonCommands(void) + /* Wait signal from PLC thread */ + pthread_mutex_lock(&python_wait_mutex); +/* Called by PLC thread on each new python command*/ +void UnBlockPythonCommands(void) + /* signal debugger thread it can read data */ + pthread_mutex_unlock(&python_wait_mutex); + return pthread_mutex_trylock(&python_mutex) == 0; + pthread_mutex_unlock(&python_mutex); + pthread_mutex_lock(&python_mutex); --- a/targets/Win32/plc_Win32_main.c Tue Dec 23 19:31:28 2008 +0100
+++ b/targets/Win32/plc_Win32_main.c Tue Dec 23 19:37:44 2008 +0100
@@ -1,18 +1,20 @@
+/* provided by POUS.C */ +extern int common_ticktime__; long AtomicCompareExchange(long* atomicvar, long compared, long exchange)
return InterlockedCompareExchange(atomicvar, exchange, compared);
-//long AtomicExchange(long* atomicvar,long exchange)
-// return InterlockedExchange(atomicvar, exchange);
void PLC_GetTime(IEC_TIME *CURRENT_TIME)
@@ -64,9 +66,11 @@
+#define maxval(a,b) ((a>b)?a:b) int startPLC(int argc,char **argv)
unsigned long thread_id = 0;
@@ -76,25 +80,50 @@
debug_sem = CreateSemaphore(
NULL, // default security attributes
- MAX_SEM_COUNT, // maximum count
NULL); // unnamed semaphore
- printf("CreateMutex error: %d\n", GetLastError());
+ printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError()); - wait_sem = CreateSemaphore(
+ debug_wait_sem = CreateSemaphore( NULL, // default security attributes
- MAX_SEM_COUNT, // maximum count
+ NULL); // unnamed semaphore + if (debug_wait_sem == NULL) + printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError()); + python_sem = CreateSemaphore( + NULL, // default security attributes NULL); // unnamed semaphore
+ if (python_sem == NULL) - printf("CreateMutex error: %d\n", GetLastError());
+ printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError()); + python_wait_sem = CreateSemaphore( + NULL, // default security attributes + NULL); // unnamed semaphore + if (python_wait_sem == NULL) + printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError()); /* Create a waitable timer */
PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer");
@@ -133,9 +162,9 @@
WaitForSingleObject(PLC_thread, INFINITE);
- ReleaseSemaphore(wait_sem, 1, NULL);
+ ReleaseSemaphore(debug_wait_sem, 1, NULL);
+ CloseHandle(debug_wait_sem); @@ -143,30 +172,58 @@
/* from plc_debugger.c */
- WaitForSingleObject(wait_sem, INFINITE);
+ WaitForSingleObject(debug_wait_sem, INFINITE); -/* Called by PLC thread when debug_pu//blish finished
+/* Called by PLC thread when debug_publish finished * This is supposed to unlock debugger thread in WaitDebugData*/
void InitiateDebugTransfer()
/* signal debugger thread it can read data */
- ReleaseSemaphore(wait_sem, 1, NULL);
+ ReleaseSemaphore(debug_wait_sem, 1, NULL);
/* Prevent PLC to enter debug code */
WaitForSingleObject(debug_sem, INFINITE);
/* Let PLC enter debug code */
ReleaseSemaphore(debug_sem, 1, NULL);
+int WaitPythonCommands(void) + /* Wait signal from PLC thread */ + WaitForSingleObject(python_wait_sem, INFINITE); +/* Called by PLC thread on each new python command*/ +void UnBlockPythonCommands(void) + /* signal debugger thread it can read data */ + ReleaseSemaphore(python_wait_sem, 1, NULL); + return WaitForSingleObject(python_sem, 0) == WAIT_OBJECT_0; + ReleaseSemaphore(python_sem, 1, NULL); + WaitForSingleObject(python_sem, INFINITE); --- a/targets/plc_common_main.c Tue Dec 23 19:31:28 2008 +0100
+++ b/targets/plc_common_main.c Tue Dec 23 19:37:44 2008 +0100
@@ -1,41 +1,35 @@
- * Prototypes for function provided by arch-specific code (main)
- * concatained after this template
+ * Code common to all C targets
- * Functions and variables provied by generated C softPLC
-extern int common_ticktime__;
- * Functions and variables provied by plc.c
-void run(long int tv_sec, long int tv_nsec);
-#define maxval(a,b) ((a>b)?a:b)
-/*#include "stdio.h" /* For debug */
- * Functions and variables provied by generated C softPLC
+ * Prototypes of functions provied by generated C softPLC void config_run__(int tick);
void config_init__(void);
-void __init_debug(void);
-void __cleanup_debug(void);
- * Functions and variables to export to generated C softPLC and plugins
+ * Prototypes of functions provied by generated target C code +void __init_debug(void); +void __cleanup_debug(void); +/*void __retrieve_debug(void);*/ +void __publish_debug(void); +void __init_python(void); +void __cleanup_python(void); +void __retrieve_python(void); +void __publish_python(void); + * Variables used by generated C softPLC and plugins
+/* Help to quit cleanly when init fail at a certain level */ static int init_level = 0;
@@ -52,10 +46,14 @@
@@ -169,3 +167,8 @@
+ * Prototypes for function provided by arch-specific code (main) + * is concatained hereafter \ No newline at end of file
--- a/targets/plc_debug.c Tue Dec 23 19:31:28 2008 +0100
+++ b/targets/plc_debug.c Tue Dec 23 19:37:44 2008 +0100
@@ -53,10 +53,7 @@
%(variables_pointer_type_table_initializer)s
+ buffer_state = BUFFER_FREE;