etisserant@280: /** etisserant@280: * Win32 specific code greg@329: **/ etisserant@280: greg@205: #include greg@205: #include greg@205: #include greg@205: #include edouard@568: #include greg@205: etisserant@280: /* provided by POUS.C */ edouard@518: extern unsigned long long common_ticktime__; etisserant@280: greg@244: long AtomicCompareExchange(long* atomicvar, long compared, long exchange) greg@205: { greg@205: return InterlockedCompareExchange(atomicvar, exchange, compared); greg@205: } greg@205: greg@205: struct _timeb timetmp; greg@205: void PLC_GetTime(IEC_TIME *CURRENT_TIME) greg@205: { greg@205: _ftime(&timetmp); greg@329: greg@205: (*CURRENT_TIME).tv_sec = timetmp.time; greg@205: (*CURRENT_TIME).tv_nsec = timetmp.millitm * 1000000; greg@205: } greg@205: greg@205: void PLC_timer_notify() greg@205: { greg@205: PLC_GetTime(&__CURRENT_TIME); greg@205: __run(); greg@205: } greg@205: greg@205: HANDLE PLC_timer = NULL; edouard@518: void PLC_SetTimer(unsigned long long next, unsigned long long period) greg@205: { greg@229: LARGE_INTEGER liDueTime; greg@205: /* arg 2 of SetWaitableTimer take 100 ns interval*/ greg@205: liDueTime.QuadPart = next / (-100); greg@329: Edouard@685: if (!SetWaitableTimer(PLC_timer, &liDueTime, period<1000000?1:period/1000000, NULL, NULL, 0)) greg@205: { greg@205: printf("SetWaitableTimer failed (%d)\n", GetLastError()); greg@205: } greg@229: } greg@229: greg@229: /* Variable used to stop plcloop thread */ greg@229: void PlcLoop() greg@229: { edouard@483: while(WaitForSingleObject(PLC_timer, INFINITE) == WAIT_OBJECT_0) edouard@483: { edouard@483: PLC_timer_notify(); edouard@483: } greg@205: } greg@205: greg@229: HANDLE PLC_thread; greg@244: HANDLE debug_sem; greg@329: HANDLE debug_wait_sem; etisserant@280: HANDLE python_sem; greg@329: HANDLE python_wait_sem; etisserant@280: etisserant@280: #define maxval(a,b) ((a>b)?a:b) greg@229: int startPLC(int argc,char **argv) greg@205: { greg@229: unsigned long thread_id = 0; edouard@568: setlocale(LC_NUMERIC, "C"); laurent@397: /* Define Ttick to 1ms if common_ticktime not defined */ laurent@397: Ttick = common_ticktime__?common_ticktime__:1000000; greg@205: edouard@483: debug_sem = CreateSemaphore( edouard@483: NULL, // default security attributes edouard@483: 1, // initial count edouard@483: 1, // maximum count edouard@483: NULL); // unnamed semaphore greg@329: if (debug_sem == NULL) greg@244: { etisserant@280: printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError()); greg@244: return; greg@244: } greg@329: edouard@483: debug_wait_sem = CreateSemaphore( edouard@483: NULL, // default security attributes edouard@483: 0, // initial count edouard@483: 1, // maximum count edouard@483: NULL); // unnamed semaphore etisserant@280: greg@329: if (debug_wait_sem == NULL) etisserant@280: { etisserant@280: printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError()); etisserant@280: return; etisserant@280: } etisserant@280: edouard@483: python_sem = CreateSemaphore( edouard@483: NULL, // default security attributes edouard@483: 1, // initial count edouard@483: 1, // maximum count edouard@483: NULL); // unnamed semaphore etisserant@280: greg@329: if (python_sem == NULL) etisserant@280: { etisserant@280: printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError()); etisserant@280: return; etisserant@280: } edouard@483: python_wait_sem = CreateSemaphore( edouard@483: NULL, // default security attributes edouard@483: 0, // initial count edouard@483: 1, // maximum count edouard@483: NULL); // unnamed semaphore etisserant@280: etisserant@280: greg@329: if (python_wait_sem == NULL) etisserant@280: { etisserant@280: printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError()); etisserant@280: return; etisserant@280: } etisserant@280: greg@329: edouard@483: /* Create a waitable timer */ Edouard@685: timeBeginPeriod(1); greg@205: PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer"); greg@205: if(NULL == PLC_timer) greg@205: { greg@205: printf("CreateWaitableTimer failed (%d)\n", GetLastError()); greg@205: return 1; greg@205: } greg@205: if( __init(argc,argv) == 0 ) greg@205: { edouard@483: PLC_SetTimer(Ttick,Ttick); edouard@483: PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id); greg@205: } greg@229: else{ edouard@483: return 1; greg@229: } greg@205: return 0; greg@205: } laurent@397: static unsigned long __debug_tick; greg@244: greg@244: int TryEnterDebugSection(void) greg@244: { greg@244: //printf("TryEnterDebugSection\n"); edouard@469: if(WaitForSingleObject(debug_sem, 0) == WAIT_OBJECT_0){ edouard@469: /* Only enter if debug active */ edouard@469: if(__DEBUG){ edouard@469: return 1; edouard@469: } edouard@483: ReleaseSemaphore(debug_sem, 1, NULL); edouard@483: } edouard@469: return 0; greg@244: } greg@244: greg@244: void LeaveDebugSection(void) greg@244: { greg@244: ReleaseSemaphore(debug_sem, 1, NULL); greg@244: //printf("LeaveDebugSection\n"); greg@244: } greg@229: greg@229: int stopPLC() greg@229: { edouard@483: CloseHandle(PLC_timer); edouard@483: WaitForSingleObject(PLC_thread, INFINITE); edouard@483: __cleanup(); edouard@483: CloseHandle(debug_wait_sem); edouard@483: CloseHandle(debug_sem); edouard@483: CloseHandle(python_wait_sem); edouard@483: CloseHandle(python_sem); edouard@483: CloseHandle(PLC_thread); greg@229: } greg@229: greg@229: /* from plc_debugger.c */ ed@446: int WaitDebugData(unsigned long *tick) greg@229: { laurent@709: DWORD res; laurent@709: res = WaitForSingleObject(debug_wait_sem, INFINITE); ed@446: *tick = __debug_tick; ed@446: /* Wait signal from PLC thread */ laurent@709: return res != WAIT_OBJECT_0; greg@229: } greg@329: etisserant@280: /* Called by PLC thread when debug_publish finished greg@229: * This is supposed to unlock debugger thread in WaitDebugData*/ greg@229: void InitiateDebugTransfer() greg@229: { greg@244: /* remember tick */ greg@244: __debug_tick = __tick; greg@244: /* signal debugger thread it can read data */ etisserant@280: ReleaseSemaphore(debug_wait_sem, 1, NULL); greg@229: } greg@244: Edouard@614: int suspendDebug(int disable) edouard@469: { greg@244: /* Prevent PLC to enter debug code */ edouard@483: WaitForSingleObject(debug_sem, INFINITE); edouard@469: __DEBUG = !disable; Lolitech@484: if(disable) Lolitech@484: ReleaseSemaphore(debug_sem, 1, NULL); Edouard@614: return 0; greg@244: } greg@244: greg@244: void resumeDebug() greg@244: { etisserant@290: __DEBUG = 1; greg@244: /* Let PLC enter debug code */ greg@244: ReleaseSemaphore(debug_sem, 1, NULL); greg@244: } etisserant@280: etisserant@280: /* from plc_python.c */ etisserant@280: int WaitPythonCommands(void) etisserant@280: { etisserant@280: /* Wait signal from PLC thread */ greg@329: return WaitForSingleObject(python_wait_sem, INFINITE); greg@329: } greg@329: etisserant@280: /* Called by PLC thread on each new python command*/ etisserant@280: void UnBlockPythonCommands(void) etisserant@280: { etisserant@280: /* signal debugger thread it can read data */ etisserant@280: ReleaseSemaphore(python_wait_sem, 1, NULL); etisserant@280: } etisserant@280: etisserant@280: int TryLockPython(void) etisserant@280: { etisserant@280: return WaitForSingleObject(python_sem, 0) == WAIT_OBJECT_0; etisserant@280: } etisserant@280: etisserant@280: void UnLockPython(void) etisserant@280: { etisserant@280: ReleaseSemaphore(python_sem, 1, NULL); etisserant@280: } etisserant@280: etisserant@280: void LockPython(void) etisserant@280: { etisserant@280: WaitForSingleObject(python_sem, INFINITE); etisserant@280: } etisserant@280: edouard@521: int CheckRetainBuffer(void) edouard@521: { edouard@521: return 1; edouard@521: } edouard@521: edouard@580: void ValidateRetainBuffer(void) edouard@580: { edouard@580: } edouard@580: edouard@580: void InValidateRetainBuffer(void) edouard@580: { edouard@580: } edouard@580: edouard@483: void Retain(unsigned int offset, unsigned int count, void * p) edouard@483: { Edouard@681: /* edouard@483: unsigned int position; edouard@483: for(position=0; position