fixed greg's crap in win32, enhanced debug stability, implemented preliminary retain
authoredouard
Wed, 09 Dec 2009 01:11:48 +0100
changeset 483 bc26c42d2eec
parent 482 7c83eb6a55bd (current diff)
parent 481 28d47c1df46f (diff)
child 484 3d0c06e2648c
child 485 8b2da4b9d408
fixed greg's crap in win32, enhanced debug stability, implemented preliminary retain
plugger.py
plugins/python/plc_python.c
runtime/PLCObject.py
targets/LPC/plc_LPC_main.c
targets/Linux/plc_Linux_main.c
targets/Win32/plc_Win32_main.c
targets/plc_debug.c
--- 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,
-                   "STEP" :       1,
-                   "TRANSITION" : 1,
-                   "ACTION" :     1,
                    "SINT" :       1,
                    "USINT" :      1,
                    "BYTE" :       1,
@@ -1712,7 +1708,7 @@
                 #print weakcallable, value, args, kwargs
                 function = getattr(weakcallable, function_name, None)
                 if function is not None:
-                    if status == "Forced":
+                    if status == "Forced" and cargs[1] == fvalue:
                         function(*(cargs + (True,) + args), **kwargs)
                     else:
                         function(*(cargs + args), **kwargs)
@@ -1803,12 +1799,13 @@
         """
         Stop PLC
         """
+        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"))
             self.KillDebugThread()
         
-        if self._connector is not None and not self._connector.StopPLC():
-            self.logger.write_error(_("Couldn't stop PLC !\n"))
         self.UpdateMethodsFromPLCStatus()
 
     def _Connect(self):
--- 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 @@
 	char* next_command;
 	PYTHON_EVAL* data__;
 	//printf("PythonIterator result %%s\n", result);
+    /*emergency exit*/
+    if(PythonState & PYTHON_FINISHED) return NULL;
 	/* take python mutex to prevent changing PLC data while PLC running */
 	LockPython();
 	/* Get current FB */
--- 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 @@
         Load PLC library
         Declare all functions, arguments and return values
         """
-        PLCprint("Load PLC")
         try:
             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]
                 
-                def StopPLCLock():
-                    self.PLClibraryLock.acquire()
-                    self._stopPLC_real()
-                    self.PLClibraryLock.release()
-                
+                self._stopPLC = self._stopPLC_real
             else:
                 # If python plugin is not enabled, we reuse _PythonIterator
                 # as a call that block pythonthread until StopPLC 
@@ -119,13 +114,11 @@
                     return None
                 self._PythonIterator = PythonIterator
                 
-                def StopPLCLock():
-                    self.PLClibraryLock.acquire()
+                def __StopPLC():
                     self._stopPLC_real()
                     self.PythonIteratorLock.release()
-                    self.PLClibraryLock.release()
-            
-            self._stopPLC = StopPLCLock
+                self._stopPLC = __StopPLC
+            
     
             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)
         error = None
         if self._LoadNewPLC():
@@ -248,7 +240,6 @@
             PLCprint("Problem %s PLC"%error)
             self.PLCStatus = "Broken"
         self._FreePLC()
-        PLCprint("PythonThreadProc interrupted")
     
     def StartPLC(self):
         PLCprint("StartPLC")
@@ -260,6 +251,7 @@
     def StopPLC(self):
         PLCprint("StopPLC")
         if self.PLCStatus == "Started":
+            self.PLCStatus = "Stopped"
             self._stopPLC()
             return True
         return False
@@ -384,30 +376,31 @@
         """
         if self.PLCStatus == "Started":
             res=[]
-            self.PLClibraryLock.acquire()
             tick = ctypes.c_uint32()
             size = ctypes.c_uint32()
             buffer = ctypes.c_void_p()
             offset = 0
-            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)
-                    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 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:
                 return self.PLCStatus, tick.value, res
-            else:
-                PLCprint("Debug error - bad buffer unpack !")
+            elif size.value:
+                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 LockPython(void)
 {
 }
+
+void Retain(unsigned int offset, unsigned int count, void *p)
+{t
+}
+
+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 @@
         if(__DEBUG){
             return 1;
         }
+        pthread_mutex_unlock(&debug_mutex);
     }
-    pthread_mutex_unlock(&debug_mutex);
     return 0;
 }
 
@@ -127,12 +127,10 @@
     PLC_SetTimer(0,0);
     timer_delete (PLC_timer);
     __cleanup();
-    __debug_tick = -1;
-    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);
     return 0;
 }
 
@@ -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 */
-int runplcloop;
 void PlcLoop()
 {
-	runplcloop = 1;
-	while(runplcloop)
-	{
-	// Set a timer
-	PLC_SetTimer(Ttick,Ttick);
-	if (WaitForSingleObject(PLC_timer, INFINITE) != WAIT_OBJECT_0)
-	{
-		printf("WaitForSingleObject failed (%d)\n", GetLastError());
-	}
-	PLC_timer_notify();
-	}
+    while(WaitForSingleObject(PLC_timer, INFINITE) == WAIT_OBJECT_0)
+    {
+        PLC_timer_notify();
+    }
 }
 
 HANDLE PLC_thread;
@@ -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
-					        1,  			// initial count
-					        1,  			// maximum count
-					        NULL);          // unnamed semaphore
+    debug_sem = CreateSemaphore(
+                            NULL,           // default security attributes
+                            1,  			// initial count
+                            1,  			// maximum count
+                            NULL);          // unnamed semaphore
     if (debug_sem == NULL)
     {
         printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError());
         return;
     }
 
-	debug_wait_sem = CreateSemaphore(
-					        NULL,           // default security attributes
-					        0,  			// initial count
-					        1,  			// maximum count
-					        NULL);          // unnamed semaphore
+    debug_wait_sem = CreateSemaphore(
+                            NULL,           // default security attributes
+                            0,  			// initial count
+                            1,  			// maximum count
+                            NULL);          // unnamed semaphore
 
     if (debug_wait_sem == NULL)
     {
@@ -100,22 +88,22 @@
         return;
     }
 
-	python_sem = CreateSemaphore(
-					        NULL,           // default security attributes
-					        1,  			// initial count
-					        1,  			// maximum count
-					        NULL);          // unnamed semaphore
+    python_sem = CreateSemaphore(
+                            NULL,           // default security attributes
+                            1,  			// initial count
+                            1,  			// maximum count
+                            NULL);          // unnamed semaphore
 
     if (python_sem == NULL)
     {
         printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError());
         return;
     }
-	python_wait_sem = CreateSemaphore(
-					        NULL,           // default security attributes
-					        0,  			// initial count
-					        1,  			// maximum count
-					        NULL);          // unnamed semaphore
+    python_wait_sem = CreateSemaphore(
+                            NULL,           // default security attributes
+                            0,  			// initial count
+                            1,  			// maximum count
+                            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");
     if(NULL == PLC_timer)
     {
@@ -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);
     }
     else{
-    	return 1;
+        return 1;
     }
     return 0;
 }
@@ -152,9 +140,9 @@
         if(__DEBUG){
             return 1;
         }
-    ReleaseSemaphore(debug_sem, 1, NULL);
+        ReleaseSemaphore(debug_sem, 1, NULL);
+    }
     return 0;
-    }
 }
 
 void LeaveDebugSection(void)
@@ -165,15 +153,14 @@
 
 int stopPLC()
 {
-	runplcloop = 0;
-	WaitForSingleObject(PLC_thread, INFINITE);
-	__cleanup();
-	__debug_tick = -1;
-	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);
+    __cleanup();
+    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 */
     __DEBUG = !disable;
 }
@@ -238,3 +225,15 @@
 	WaitForSingleObject(python_sem, INFINITE);
 }
 
+void Retain(unsigned int offset, unsigned int count, void * p)
+{
+    unsigned int position;
+    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 @@
 
 /* Buffer's cursor*/
 static char* buffer_cursor = debug_buffer;
-
+static unsigned int retain_offset = 0;
 /***
  * Declare programs 
  **/
@@ -56,42 +56,20 @@
     }
 }
 
-void __init_debug(void)
-{
-    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) \
         case TYPENAME##_ENUM :\
-            flags = ((__IEC_##TYPENAME##_t *)varp)->flags;\
-            ptrvalue = &((__IEC_##TYPENAME##_t *)varp)->value;\
+            *flags = ((__IEC_##TYPENAME##_t *)varp)->flags;\
+            *ptrvalue = &((__IEC_##TYPENAME##_t *)varp)->value;\
             break;
 
 #define __BufferDebugDataIterator_case_p(TYPENAME)\
         case TYPENAME##_P_ENUM :\
-            flags = ((__IEC_##TYPENAME##_p *)varp)->flags;\
-            ptrvalue = ((__IEC_##TYPENAME##_p *)varp)->value;\
-            break;
-
-void BufferDebugDataIterator(void* varp, __IEC_types_enum vartype)
-{
-    void *ptrvalue = NULL;
-    char flags = 0;
+            *flags = ((__IEC_##TYPENAME##_p *)varp)->flags;\
+            *ptrvalue = ((__IEC_##TYPENAME##_p *)varp)->value;\
+            break;
+
+void UnpackVar(void* varp, __IEC_types_enum vartype, void **ptrvalue, char *flags)
+{
     /* find data to copy*/
     switch(vartype){
         ANY(__BufferDebugDataIterator_case_t)
@@ -99,26 +77,114 @@
     default:
         break;
     }
-    if(flags && __IEC_DEBUG_FLAG){
+}
+
+void Remind(unsigned int offset, unsigned int count, void * p);
+
+void RemindIterator(void* varp, __IEC_types_enum vartype)
+{
+    void *ptrvalue = NULL;
+    char flags = 0;
+    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 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;
-        }else{
-            /*TODO : signal overflow*/
+        Remind(retain_offset, size, ptrvalue);
+        /* increment cursor according size*/
+        retain_offset = next_retain_offset;
+    }
+}
+
+void __init_debug(void)
+{
+    /* init local static vars */
+    buffer_cursor = debug_buffer;
+    retain_offset = 0;
+    buffer_state = BUFFER_FREE;
+    /* Iterate over all variables to fill debug buffer */
+    __for_each_variable_do(RemindIterator);
+    retain_offset = 0;
+}
+
+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;
+    }else{
+        /*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)
+{
+    void *ptrvalue = NULL;
+    char flags = 0;
+    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)
+{
+    void *ptrvalue = NULL;
+    char flags = 0;
+    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)
 {
+    retain_offset = 0;
     /* Check there is no running debugger re-configuration */
     if(TryEnterDebugSection()){
         /* Lock buffer */
@@ -141,6 +207,9 @@
             InitiateDebugTransfer(); /* size */
         }
         LeaveDebugSection();
+    }else{
+        /* when not debugging, do only retain */
+        __for_each_variable_do(RetainIterator);
     }
 }