fixed greg's crap in win32, enhanced debug stability, implemented preliminary retain
--- 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);
}
}