# HG changeset patch
# User edouard
# Date 1260317508 -3600
# Node ID bc26c42d2eecf6133c9aa616fa5180a75db8c430
# Parent  7c83eb6a55bd081c7b2a912567a917000c88f592# Parent  28d47c1df46f46840964b94e8949298df4a7c3e8
fixed greg's crap in win32, enhanced debug stability, implemented preliminary retain

diff -r 28d47c1df46f -r bc26c42d2eec connectors/LPC/LPCProto.py
--- a/connectors/LPC/LPCProto.py	Tue Dec 08 17:09:25 2009 +0100
+++ b/connectors/LPC/LPCProto.py	Wed Dec 09 01:11:48 2009 +0100
@@ -4,6 +4,8 @@
 import time
 from threading import Lock
 
+MAX_PACKET_SIZE=64
+
 LPC_STATUS=dict(STARTED = 0x01,
                 STOPPED = 0x02,
                 DEBUG = 0x03)
@@ -84,8 +86,21 @@
         length = len(self.OptData)
         # transform length into a byte string
         # we presuppose endianess of LPC same as PC
-        lengthstr = ctypes.string_at(ctypes.pointer(ctypes.c_int(length)),4) 
-        self.pseudofile.write(lengthstr + self.OptData)
+        lengthstr = ctypes.string_at(ctypes.pointer(ctypes.c_int(length)),4)
+        buffer = lengthstr + self.OptData
+        ###################################################################
+        # TO BE REMOVED AS SOON AS USB IS FIXED IN CONTROLLER
+        ###################################################################
+        length += 4
+        cursor = 0
+        while cursor < length:
+            next_cursor = cursor + MAX_PACKET_SIZE
+            # sent just enough bytes to not crash controller
+            self.pseudofile.write(buffer[cursor:next_cursor])
+            # if sent quantity was 128
+            if next_cursor <= length:
+                self.GetCommandAck()
+            cursor = next_cursor
 
     def GetData(self):
         lengthstr = self.pseudofile.read(4)
@@ -130,14 +145,14 @@
 
 if __name__ == "__main__":
     TestConnection = LPCProto(6,115200,2)
-    #TestConnection.HandleTransaction(GET_PLCIDTransaction())
+#    TestConnection.HandleTransaction(GET_PLCIDTransaction())
     TestConnection.HandleTransaction(STARTTransaction())
-    TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
-           "\x03\x00\x00\x00"))
-    TestConnection.HandleTransaction(STARTTransaction())
+#    TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
+#           "\x03\x00\x00\x00"*200))
+#    TestConnection.HandleTransaction(STARTTransaction())
     while True:
-        time.sleep(0.5)
+        #time.sleep(0.5)
         TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
-           "\x01\x00\x00\x00"*31))
+           "\x01\x00\x00\x00"*200))
    #print map(hex,map(ord,TestConnection.HandleTransaction(GET_TRACE_VARIABLETransaction())))
     #TestConnection.HandleTransaction(STOPTransaction())
diff -r 28d47c1df46f -r bc26c42d2eec plugger.py
--- a/plugger.py	Tue Dec 08 17:09:25 2009 +0100
+++ b/plugger.py	Wed Dec 09 01:11:48 2009 +0100
@@ -1799,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):
diff -r 28d47c1df46f -r bc26c42d2eec plugins/python/plc_python.c
--- a/plugins/python/plc_python.c	Tue Dec 08 17:09:25 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 */
diff -r 28d47c1df46f -r bc26c42d2eec runtime/PLCObject.py
--- a/runtime/PLCObject.py	Tue Dec 08 17:09:25 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
@@ -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
 
diff -r 28d47c1df46f -r bc26c42d2eec targets/LPC/plc_LPC_main.c
--- a/targets/LPC/plc_LPC_main.c	Tue Dec 08 17:09:25 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)
+{
+}
diff -r 28d47c1df46f -r bc26c42d2eec targets/Linux/plc_Linux_main.c
--- a/targets/Linux/plc_Linux_main.c	Tue Dec 08 17:09:25 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)
+{
+}
diff -r 28d47c1df46f -r bc26c42d2eec targets/Win32/plc_Win32_main.c
--- a/targets/Win32/plc_Win32_main.c	Tue Dec 08 17:09:25 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)
+{
+}
+
diff -r 28d47c1df46f -r bc26c42d2eec targets/plc_debug.c
--- a/targets/plc_debug.c	Tue Dec 08 17:09:25 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);
     }
 }