greg@556: /* greg@556: This file is part of CanFestival, a library implementing CanOpen Stack. greg@556: greg@556: Copyright (C): Edouard TISSERANT and Francis DUPIN greg@556: Copyright (C) Win32 Port Leonid Tochinski greg@556: greg@556: See COPYING file for copyrights details. greg@556: greg@556: This library is free software; you can redistribute it and/or greg@556: modify it under the terms of the GNU Lesser General Public greg@556: License as published by the Free Software Foundation; either greg@556: version 2.1 of the License, or (at your option) any later version. greg@556: greg@556: This library is distributed in the hope that it will be useful, greg@556: but WITHOUT ANY WARRANTY; without even the implied warranty of greg@556: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU greg@556: Lesser General Public License for more details. greg@556: greg@556: You should have received a copy of the GNU Lesser General Public greg@556: License along with this library; if not, write to the Free Software greg@556: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA greg@556: */ greg@556: greg@556: #include greg@556: #include greg@556: #include greg@556: greg@591: #ifdef __cplusplus greg@591: extern "C" { greg@591: #endif greg@591: greg@556: #include "applicfg.h" greg@556: #include "can_driver.h" Edouard@801: #include "timers.h" greg@556: #include "timers_driver.h" greg@591: greg@591: #ifdef __cplusplus greg@577: }; greg@591: #endif greg@556: ct@680: DWORD timebuffer; greg@556: greg@556: /* Synchronization Object Implementation */ greg@556: CRITICAL_SECTION CanFestival_mutex; greg@556: HANDLE timer_thread = NULL; greg@556: HANDLE timer = NULL; greg@556: JaFojtik@697: volatile int stop_timer=0; greg@556: greg@556: static TimerCallback_t init_callback; greg@556: greg@556: greg@556: void EnterMutex(void) greg@556: { greg@556: EnterCriticalSection(&CanFestival_mutex); greg@556: } greg@556: greg@556: void LeaveMutex(void) greg@556: { greg@556: LeaveCriticalSection(&CanFestival_mutex); greg@556: } greg@556: greg@556: // --------------- CAN Receive Thread Implementation --------------- greg@556: greg@556: void CreateReceiveTask(CAN_HANDLE fd0, TASK_HANDLE* Thread, void* ReceiveLoopPtr) greg@556: { greg@556: unsigned long thread_id = 0; greg@556: *Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReceiveLoopPtr, fd0, 0, &thread_id); greg@556: } greg@556: greg@556: void WaitReceiveTaskEnd(TASK_HANDLE *Thread) greg@556: { gregory@600: if(WaitForSingleObject(*Thread, 1000) == WAIT_TIMEOUT) gregory@600: { gregory@600: TerminateThread(*Thread, -1); gregory@600: } greg@556: CloseHandle(*Thread); greg@556: } greg@556: edouard@629: #if !defined(WIN32) || defined(__CYGWIN__) greg@556: int TimerThreadLoop(void) edouard@629: #else edouard@629: DWORD TimerThreadLoop(LPVOID arg) edouard@629: #endif greg@556: { greg@605: greg@556: greg@571: while(!stop_timer) greg@556: { greg@571: WaitForSingleObject(timer, INFINITE); greg@571: if(stop_timer) greg@571: break; greg@556: EnterMutex(); ct@680: timebuffer = GetTickCount(); greg@556: TimeDispatch(); greg@556: LeaveMutex(); greg@556: } greg@556: return 0; greg@556: } greg@556: greg@556: void TimerInit(void) greg@556: { greg@556: LARGE_INTEGER liDueTime; greg@556: liDueTime.QuadPart = 0; greg@556: greg@556: InitializeCriticalSection(&CanFestival_mutex); greg@556: greg@571: timer = CreateWaitableTimer(NULL, FALSE, NULL); greg@556: if(NULL == timer) greg@556: { greg@556: printf("CreateWaitableTimer failed (%d)\n", GetLastError()); greg@556: } greg@556: greg@556: // Take first absolute time ref in milliseconds. ct@680: timebuffer = GetTickCount(); greg@556: } greg@556: greg@556: void TimerCleanup(void) greg@556: { greg@556: DeleteCriticalSection(&CanFestival_mutex); greg@556: } greg@556: greg@556: void StopTimerLoop(TimerCallback_t exitfunction) greg@556: { greg@556: EnterMutex(); greg@556: exitfunction(NULL,0); greg@556: LeaveMutex(); greg@556: greg@556: stop_timer = 1; greg@571: setTimer(0); edouard@599: if(WaitForSingleObject(timer_thread,1000) == WAIT_TIMEOUT) edouard@599: { edouard@599: TerminateThread(timer_thread, -1); edouard@599: } greg@556: CloseHandle(timer); greg@556: CloseHandle(timer_thread); greg@556: } greg@556: greg@556: void StartTimerLoop(TimerCallback_t _init_callback) greg@556: { greg@556: unsigned long timer_thread_id; greg@556: stop_timer = 0; greg@556: init_callback = _init_callback; greg@605: EnterMutex(); greg@605: // At first, TimeDispatch will call init_callback. greg@605: SetAlarm(NULL, 0, init_callback, 0, 0); greg@605: LeaveMutex(); greg@556: timer_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TimerThreadLoop, NULL, 0, &timer_thread_id); greg@556: } greg@556: greg@556: /* Set the next alarm */ greg@556: void setTimer(TIMEVAL value) greg@556: { greg@556: if(value == TIMEVAL_MAX) greg@556: CancelWaitableTimer(timer); greg@556: else greg@556: { greg@556: LARGE_INTEGER liDueTime; greg@556: greg@556: /* arg 2 of SetWaitableTimer take 100 ns interval */ ct@680: liDueTime.QuadPart = ((long long) (-1) * value * 10000); greg@556: //printf("SetTimer(%llu)\n", value); greg@556: greg@556: if (!SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, FALSE)) greg@556: { greg@556: printf("SetWaitableTimer failed (%d)\n", GetLastError()); greg@556: } greg@556: } greg@556: } greg@556: greg@556: /* Get the elapsed time since the last occured alarm */ greg@556: TIMEVAL getElapsedTime(void) greg@556: { ct@680: DWORD timetmp = GetTickCount(); ct@680: return (timetmp - timebuffer); greg@556: } greg@556: