--- a/plugger.py Wed Dec 09 00:56:18 2009 +0100
+++ b/plugger.py Wed Dec 09 01:11:48 2009 +0100
@@ -681,12 +681,8 @@
from plcopen.structures import IEC_KEYWORDS, TypeHierarchy_list
# Construct debugger natively supported types
-DebugTypes = [t for t in zip(*TypeHierarchy_list)[0] if not t.startswith("ANY")] + \
- ["STEP","TRANSITION","ACTION"]
+DebugTypes = [t for t in zip(*TypeHierarchy_list)[0] if not t.startswith("ANY")] DebugTypesSize = {"BOOL" : 1,
@@ -1712,7 +1708,7 @@
#print weakcallable, value, args, kwargs
function = getattr(weakcallable, function_name, None)
+ if status == "Forced" and cargs[1] == fvalue: function(*(cargs + (True,) + args), **kwargs)
function(*(cargs + args), **kwargs)
@@ -1803,12 +1799,13 @@
+ if self._connector is not None and not self._connector.StopPLC(): + self.logger.write_error(_("Couldn't stop PLC !\n")) if self.DebugThread is not None:
self.logger.write(_("Stopping debug\n"))
- if self._connector is not None and not self._connector.StopPLC():
- self.logger.write_error(_("Couldn't stop PLC !\n"))
self.UpdateMethodsFromPLCStatus()
--- a/plugins/python/plc_python.c Wed Dec 09 00:56:18 2009 +0100
+++ b/plugins/python/plc_python.c Wed Dec 09 01:11:48 2009 +0100
@@ -157,6 +157,8 @@
//printf("PythonIterator result %%s\n", result);
+ if(PythonState & PYTHON_FINISHED) return NULL; /* take python mutex to prevent changing PLC data while PLC running */
--- a/runtime/PLCObject.py Wed Dec 09 00:56:18 2009 +0100
+++ b/runtime/PLCObject.py Wed Dec 09 01:11:48 2009 +0100
@@ -86,7 +86,6 @@
Declare all functions, arguments and return values
self._PLClibraryHandle = dlopen(self._GetLibFileName())
self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle)
@@ -103,11 +102,7 @@
self._PythonIterator.restype = ctypes.c_char_p
self._PythonIterator.argtypes = [ctypes.c_char_p]
- self.PLClibraryLock.acquire()
- self.PLClibraryLock.release()
+ self._stopPLC = self._stopPLC_real # If python plugin is not enabled, we reuse _PythonIterator
# as a call that block pythonthread until StopPLC
@@ -119,13 +114,11 @@
self._PythonIterator = PythonIterator
- self.PLClibraryLock.acquire()
self.PythonIteratorLock.release()
- self.PLClibraryLock.release()
+ self._stopPLC = __StopPLC - self._stopPLC = StopPLCLock
self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables
self._ResetDebugVariables.restype = None
@@ -163,7 +156,7 @@
self._startPLC = lambda:None
self._stopPLC = lambda:None
self._ResetDebugVariables = lambda:None
- self._RegisterDebugVariable = lambda x:None
+ self._RegisterDebugVariable = lambda x, y:None self._IterDebugData = lambda x,y:None
self._FreeDebugData = lambda:None
self._GetDebugData = lambda:-1
@@ -217,7 +210,6 @@
self.python_threads_vars = None
def PythonThreadProc(self):
- PLCprint("PythonThreadProc started")
c_argv = ctypes.c_char_p * len(self.argv)
@@ -248,7 +240,6 @@
PLCprint("Problem %s PLC"%error)
self.PLCStatus = "Broken"
- PLCprint("PythonThreadProc interrupted")
@@ -260,6 +251,7 @@
if self.PLCStatus == "Started":
+ self.PLCStatus = "Stopped" @@ -384,30 +376,31 @@
if self.PLCStatus == "Started":
- self.PLClibraryLock.acquire()
buffer = ctypes.c_void_p()
- if self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 :
- 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)
- PLCprint("Debug error - " + iectype + " not supported !")
- PLCprint("Debug error - buffer too small !")
- self.PLClibraryLock.release()
+ if self.PLClibraryLock.acquire(False) and \ + self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 : + 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) + PLCprint("Debug error - " + iectype + " not supported !") + PLCprint("Debug error - buffer too small !") + self.PLClibraryLock.release() if offset and offset == size.value:
return self.PLCStatus, tick.value, res
- PLCprint("Debug error - bad buffer unpack !")
+ PLCprint("Debug error - wrong buffer unpack !") return self.PLCStatus, None, None
--- a/targets/LPC/plc_LPC_main.c Wed Dec 09 00:56:18 2009 +0100
+++ b/targets/LPC/plc_LPC_main.c Wed Dec 09 01:11:48 2009 +0100
@@ -92,3 +92,11 @@
+void Retain(unsigned int offset, unsigned int count, void *p) +void Remind(unsigned int offset, unsigned int count, void *p) --- a/targets/Linux/plc_Linux_main.c Wed Dec 09 00:56:18 2009 +0100
+++ b/targets/Linux/plc_Linux_main.c Wed Dec 09 01:11:48 2009 +0100
@@ -111,8 +111,8 @@
+ pthread_mutex_unlock(&debug_mutex); - pthread_mutex_unlock(&debug_mutex);
@@ -127,12 +127,10 @@
timer_delete (PLC_timer);
- pthread_mutex_unlock(&debug_mutex);
- pthread_mutex_unlock(&debug_wait_mutex);
pthread_mutex_destroy(&debug_wait_mutex);
- pthread_mutex_unlock(&python_wait_mutex);
+ pthread_mutex_destroy(&debug_mutex); pthread_mutex_destroy(&python_wait_mutex);
+ pthread_mutex_destroy(&python_mutex); @@ -198,3 +196,11 @@
pthread_mutex_lock(&python_mutex);
+void Retain(unsigned int offset, unsigned int count, void *p) +void Remind(unsigned int offset, unsigned int count, void *p) --- a/targets/Win32/plc_Win32_main.c Wed Dec 09 00:56:18 2009 +0100
+++ b/targets/Win32/plc_Win32_main.c Wed Dec 09 01:11:48 2009 +0100
@@ -37,31 +37,19 @@
/* arg 2 of SetWaitableTimer take 100 ns interval*/
liDueTime.QuadPart = next / (-100);
- printf("SetTimer(%lld,%lld)\n",next, period);
- if (!SetWaitableTimer(PLC_timer, &liDueTime, common_ticktime__, NULL, NULL, 0))
+ if (!SetWaitableTimer(PLC_timer, &liDueTime, period/1000000, NULL, NULL, 0)) printf("SetWaitableTimer failed (%d)\n", GetLastError());
/* Variable used to stop plcloop thread */
- PLC_SetTimer(Ttick,Ttick);
- if (WaitForSingleObject(PLC_timer, INFINITE) != WAIT_OBJECT_0)
- printf("WaitForSingleObject failed (%d)\n", GetLastError());
+ while(WaitForSingleObject(PLC_timer, INFINITE) == WAIT_OBJECT_0) @@ -77,22 +65,22 @@
/* Define Ttick to 1ms if common_ticktime not defined */
Ttick = common_ticktime__?common_ticktime__:1000000;
- debug_sem = CreateSemaphore(
- NULL, // default security attributes
- NULL); // unnamed semaphore
+ debug_sem = CreateSemaphore( + NULL, // default security attributes + NULL); // unnamed semaphore printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError());
- debug_wait_sem = CreateSemaphore(
- NULL, // default security attributes
- NULL); // unnamed semaphore
+ debug_wait_sem = CreateSemaphore( + NULL, // default security attributes + NULL); // unnamed semaphore if (debug_wait_sem == NULL)
@@ -100,22 +88,22 @@
- python_sem = CreateSemaphore(
- NULL, // default security attributes
- NULL); // unnamed semaphore
+ python_sem = CreateSemaphore( + NULL, // default security attributes + NULL); // unnamed semaphore printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError());
- python_wait_sem = CreateSemaphore(
- NULL, // default security attributes
- NULL); // unnamed semaphore
+ python_wait_sem = CreateSemaphore( + NULL, // default security attributes + NULL); // unnamed semaphore if (python_wait_sem == NULL)
@@ -125,7 +113,7 @@
- /* Create a waitable timer */
+ /* Create a waitable timer */ PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer");
@@ -134,11 +122,11 @@
if( __init(argc,argv) == 0 )
- printf("Tick Time : %d ms\n", common_ticktime__);
- PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id);
+ PLC_SetTimer(Ttick,Ttick); + PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id);
@@ -152,9 +140,9 @@
- ReleaseSemaphore(debug_sem, 1, NULL);
+ ReleaseSemaphore(debug_sem, 1, NULL);
void LeaveDebugSection(void)
@@ -165,15 +153,14 @@
- WaitForSingleObject(PLC_thread, INFINITE);
- ReleaseSemaphore(debug_wait_sem, 1, NULL);
- CloseHandle(debug_sem);
- CloseHandle(debug_wait_sem);
- CloseHandle(PLC_timer);
- CloseHandle(PLC_thread);
+ CloseHandle(PLC_timer); + WaitForSingleObject(PLC_thread, INFINITE); + CloseHandle(debug_wait_sem); + CloseHandle(debug_sem); + CloseHandle(python_wait_sem); + CloseHandle(python_sem); + CloseHandle(PLC_thread); /* from plc_debugger.c */
@@ -197,7 +184,7 @@
void suspendDebug(int disable)
/* Prevent PLC to enter debug code */
- WaitForSingleObject(debug_sem, INFINITE);
+ WaitForSingleObject(debug_sem, INFINITE); /*__DEBUG is protected by this mutex */
@@ -238,3 +225,15 @@
WaitForSingleObject(python_sem, INFINITE);
+void Retain(unsigned int offset, unsigned int count, void * p) + for(position=0; position<count; position++ ){ + printf("%d : 0x%2.2x\n", offset+position, ((char*)p)[position]); +void Remind(unsigned int offset, unsigned int count, void *p) --- a/targets/plc_debug.c Wed Dec 09 00:56:18 2009 +0100
+++ b/targets/plc_debug.c Wed Dec 09 01:11:48 2009 +0100
@@ -29,7 +29,7 @@
static char* buffer_cursor = debug_buffer;
+static unsigned int retain_offset = 0; @@ -56,42 +56,20 @@
- buffer_state = BUFFER_FREE;
-void __cleanup_debug(void)
-void __retrieve_debug(void)
-extern int TryEnterDebugSection(void);
-extern void LeaveDebugSection(void);
-extern long AtomicCompareExchange(long*, long, long);
-extern void InitiateDebugTransfer(void);
-extern unsigned long __tick;
#define __BufferDebugDataIterator_case_t(TYPENAME) \
- flags = ((__IEC_##TYPENAME##_t *)varp)->flags;\
- ptrvalue = &((__IEC_##TYPENAME##_t *)varp)->value;\
+ *flags = ((__IEC_##TYPENAME##_t *)varp)->flags;\ + *ptrvalue = &((__IEC_##TYPENAME##_t *)varp)->value;\ #define __BufferDebugDataIterator_case_p(TYPENAME)\
case TYPENAME##_P_ENUM :\
- flags = ((__IEC_##TYPENAME##_p *)varp)->flags;\
- ptrvalue = ((__IEC_##TYPENAME##_p *)varp)->value;\
+ *flags = ((__IEC_##TYPENAME##_p *)varp)->flags;\ + *ptrvalue = ((__IEC_##TYPENAME##_p *)varp)->value;\ -void BufferDebugDataIterator(void* varp, __IEC_types_enum vartype)
+void UnpackVar(void* varp, __IEC_types_enum vartype, void **ptrvalue, char *flags)
ANY(__BufferDebugDataIterator_case_t)
@@ -99,26 +77,114 @@
- if(flags && __IEC_DEBUG_FLAG){
+void Remind(unsigned int offset, unsigned int count, void * p); +void RemindIterator(void* varp, __IEC_types_enum vartype) + UnpackVar(varp, vartype, &ptrvalue, &flags); + if(flags && __IEC_RETAIN_FLAG){ USINT size = __get_type_enum_size(vartype);
/* compute next cursor positon*/
- char* next_cursor = buffer_cursor + size;
+ unsigned int next_retain_offset = retain_offset + size; - if(next_cursor <= debug_buffer + BUFFER_SIZE)
- /* copy data to the buffer */
- memcpy(buffer_cursor, ptrvalue, size);
- /* increment cursor according size*/
- buffer_cursor = next_cursor;
- /*TODO : signal overflow*/
+ Remind(retain_offset, size, ptrvalue); + /* increment cursor according size*/ + retain_offset = next_retain_offset; + /* init local static vars */ + buffer_cursor = debug_buffer; + buffer_state = BUFFER_FREE; + /* Iterate over all variables to fill debug buffer */ + __for_each_variable_do(RemindIterator); +extern void InitiateDebugTransfer(void); +extern unsigned long __tick; +void __cleanup_debug(void) + buffer_cursor = debug_buffer; + InitiateDebugTransfer(); +void __retrieve_debug(void) +void DoDebug(void *ptrvalue, char flags, USINT size) + /* compute next cursor positon*/ + char* next_cursor = buffer_cursor + size; + /* if buffer not full */ + if(next_cursor <= debug_buffer + BUFFER_SIZE) + /* copy data to the buffer */ + memcpy(buffer_cursor, ptrvalue, size); + /* increment cursor according size*/ + buffer_cursor = next_cursor; + /*TODO : signal overflow*/ +void Retain(unsigned int offset, unsigned int count, void * p); +void DoRetain(void *ptrvalue, char flags, USINT size){ + /* compute next cursor positon*/ + unsigned int next_retain_offset = retain_offset + size; + /* if buffer not full */ + Retain(retain_offset, size, ptrvalue); + /* increment cursor according size*/ + retain_offset = next_retain_offset; +void BufferDebugDataIterator(void* varp, __IEC_types_enum vartype) + UnpackVar(varp, vartype, &ptrvalue, &flags); + /* For optimization purpose we do retain and debug in the same pass */ + if(flags & (__IEC_DEBUG_FLAG | __IEC_RETAIN_FLAG)){ + USINT size = __get_type_enum_size(vartype); + if(flags & __IEC_DEBUG_FLAG){ + DoDebug(ptrvalue, flags, size); + if(flags & __IEC_RETAIN_FLAG){ + DoRetain(ptrvalue, flags, size); +void RetainIterator(void* varp, __IEC_types_enum vartype) + UnpackVar(varp, vartype, &ptrvalue, &flags); + if(flags & __IEC_RETAIN_FLAG){ + USINT size = __get_type_enum_size(vartype); + DoRetain(ptrvalue, flags, size); +extern int TryEnterDebugSection(void); +extern long AtomicCompareExchange(long*, long, long); +extern void LeaveDebugSection(void); void __publish_debug(void)
/* Check there is no running debugger re-configuration */
if(TryEnterDebugSection()){
@@ -141,6 +207,9 @@
InitiateDebugTransfer(); /* size */
+ /* when not debugging, do only retain */ + __for_each_variable_do(RetainIterator);