lbessard@321: /** Edouard@954: * Xenomai Linux specific code greg@336: **/ lbessard@321: lbessard@321: #include Edouard@615: #include lbessard@321: #include lbessard@321: #include lbessard@321: #include lbessard@321: #include lbessard@321: #include greg@342: #include lbessard@321: Edouard@1974: #include Edouard@1974: #include Edouard@1974: #include Edouard@1974: #include lbessard@321: lbessard@321: unsigned int PLC_state = 0; Edouard@615: #define PLC_STATE_TASK_CREATED 1 Edouard@615: #define PLC_STATE_DEBUG_FILE_OPENED 2 Edouard@615: #define PLC_STATE_DEBUG_PIPE_CREATED 4 Edouard@615: #define PLC_STATE_PYTHON_FILE_OPENED 8 Edouard@615: #define PLC_STATE_PYTHON_PIPE_CREATED 16 Edouard@615: #define PLC_STATE_WAITDEBUG_FILE_OPENED 32 Edouard@615: #define PLC_STATE_WAITDEBUG_PIPE_CREATED 64 Edouard@615: #define PLC_STATE_WAITPYTHON_FILE_OPENED 128 Edouard@615: #define PLC_STATE_WAITPYTHON_PIPE_CREATED 256 Edouard@615: Edouard@615: #define WAITDEBUG_PIPE_DEVICE "/dev/rtp0" Edouard@615: #define WAITDEBUG_PIPE_MINOR 0 Edouard@615: #define DEBUG_PIPE_DEVICE "/dev/rtp1" Edouard@615: #define DEBUG_PIPE_MINOR 1 Edouard@615: #define WAITPYTHON_PIPE_DEVICE "/dev/rtp2" Edouard@615: #define WAITPYTHON_PIPE_MINOR 2 Edouard@615: #define PYTHON_PIPE_DEVICE "/dev/rtp3" Edouard@615: #define PYTHON_PIPE_MINOR 3 Edouard@615: #define PIPE_SIZE 1 lbessard@321: Edouard@1990: // rt-pipes commands Edouard@1990: Edouard@1990: #define PYTHON_PENDING_COMMAND 1 Edouard@1990: #define PYTHON_FINISH 2 Edouard@1990: Edouard@1990: #define DEBUG_FINISH 2 Edouard@1990: Edouard@1990: #define DEBUG_PENDING_DATA 1 Edouard@1990: #define DEBUG_UNLOCK 1 lbessard@321: lbessard@321: long AtomicCompareExchange(long* atomicvar,long compared, long exchange) lbessard@321: { lbessard@321: return __sync_val_compare_and_swap(atomicvar, compared, exchange); lbessard@321: } Edouard@954: long long AtomicCompareExchange64(long long* atomicvar, long long compared, long long exchange) Edouard@954: { Edouard@954: return __sync_val_compare_and_swap(atomicvar, compared, exchange); Edouard@954: } lbessard@321: lbessard@321: void PLC_GetTime(IEC_TIME *CURRENT_TIME) lbessard@321: { lbessard@321: RTIME current_time = rt_timer_read(); lbessard@321: CURRENT_TIME->tv_sec = current_time / 1000000000; lbessard@321: CURRENT_TIME->tv_nsec = current_time % 1000000000; lbessard@321: } lbessard@321: lbessard@321: RT_TASK PLC_task; greg@342: RT_PIPE WaitDebug_pipe; Edouard@615: RT_PIPE WaitPython_pipe; Edouard@615: RT_PIPE Debug_pipe; Edouard@615: RT_PIPE Python_pipe; Edouard@615: int WaitDebug_pipe_fd; Edouard@615: int WaitPython_pipe_fd; Edouard@615: int Debug_pipe_fd; Edouard@615: int Python_pipe_fd; Edouard@615: lbessard@321: int PLC_shutdown = 0; lbessard@321: Edouard@615: void PLC_SetTimer(unsigned long long next, unsigned long long period) lbessard@321: { lbessard@321: RTIME current_time = rt_timer_read(); lbessard@321: rt_task_set_periodic(&PLC_task, current_time + next, rt_timer_ns2ticks(period)); lbessard@321: } lbessard@321: lbessard@321: void PLC_task_proc(void *arg) lbessard@321: { Edouard@1428: PLC_SetTimer(common_ticktime__, common_ticktime__); greg@336: Edouard@695: while (!PLC_shutdown) { lbessard@321: PLC_GetTime(&__CURRENT_TIME); lbessard@321: __run(); lbessard@321: if (PLC_shutdown) break; lbessard@321: rt_task_wait_period(NULL); lbessard@321: } Edouard@1990: /* since xenomai 3 it is not enough to close() Edouard@1990: file descriptor to unblock read()... */ Edouard@1990: { Edouard@1990: /* explicitely finish python thread */ Edouard@1990: char msg = PYTHON_FINISH; Edouard@1990: rt_pipe_write(&WaitPython_pipe, &msg, sizeof(msg), P_NORMAL); Edouard@1990: } Edouard@1990: { Edouard@1990: /* explicitely finish debug thread */ Edouard@1990: char msg = DEBUG_FINISH; Edouard@1990: rt_pipe_write(&WaitDebug_pipe, &msg, sizeof(msg), P_NORMAL); Edouard@1990: } lbessard@321: } lbessard@321: laurent@397: static unsigned long __debug_tick; lbessard@321: lbessard@321: void PLC_cleanup_all(void) lbessard@321: { lbessard@321: if (PLC_state & PLC_STATE_TASK_CREATED) { lbessard@321: rt_task_delete(&PLC_task); lbessard@321: PLC_state &= ~PLC_STATE_TASK_CREATED; lbessard@321: } lbessard@321: Edouard@615: if (PLC_state & PLC_STATE_WAITDEBUG_PIPE_CREATED) { Edouard@615: rt_pipe_delete(&WaitDebug_pipe); Edouard@615: PLC_state &= ~PLC_STATE_WAITDEBUG_PIPE_CREATED; Edouard@615: } Edouard@615: Edouard@615: if (PLC_state & PLC_STATE_WAITDEBUG_FILE_OPENED) { Edouard@615: close(WaitDebug_pipe_fd); Edouard@615: PLC_state &= ~PLC_STATE_WAITDEBUG_FILE_OPENED; Edouard@615: } Edouard@615: Edouard@615: if (PLC_state & PLC_STATE_WAITPYTHON_PIPE_CREATED) { Edouard@615: rt_pipe_delete(&WaitPython_pipe); laurent@745: PLC_state &= ~PLC_STATE_WAITPYTHON_PIPE_CREATED; laurent@745: } laurent@745: laurent@745: if (PLC_state & PLC_STATE_WAITPYTHON_FILE_OPENED) { Edouard@615: close(WaitPython_pipe_fd); Edouard@615: PLC_state &= ~PLC_STATE_WAITPYTHON_FILE_OPENED; lbessard@321: } greg@336: greg@342: if (PLC_state & PLC_STATE_DEBUG_PIPE_CREATED) { Edouard@615: rt_pipe_delete(&Debug_pipe); greg@342: PLC_state &= ~PLC_STATE_DEBUG_PIPE_CREATED; greg@342: } greg@342: greg@342: if (PLC_state & PLC_STATE_DEBUG_FILE_OPENED) { Edouard@615: close(Debug_pipe_fd); greg@342: PLC_state &= ~PLC_STATE_DEBUG_FILE_OPENED; lbessard@321: } lbessard@321: Edouard@615: if (PLC_state & PLC_STATE_PYTHON_PIPE_CREATED) { Edouard@615: rt_pipe_delete(&Python_pipe); laurent@745: PLC_state &= ~PLC_STATE_PYTHON_PIPE_CREATED; laurent@745: } laurent@745: laurent@745: if (PLC_state & PLC_STATE_PYTHON_FILE_OPENED) { Edouard@615: close(Python_pipe_fd); Edouard@615: PLC_state &= ~PLC_STATE_PYTHON_FILE_OPENED; Edouard@615: } Edouard@615: lbessard@321: } lbessard@321: lbessard@321: int stopPLC() lbessard@321: { laurent@745: /* Stop the PLC */ lbessard@321: PLC_shutdown = 1; laurent@745: laurent@745: /* Wait until PLC task stops */ laurent@745: rt_task_join(&PLC_task); laurent@745: laurent@745: PLC_cleanup_all(); greg@342: __cleanup(); lbessard@321: __debug_tick = -1; Edouard@615: return 0; lbessard@321: } lbessard@321: lbessard@321: // lbessard@321: void catch_signal(int sig) lbessard@321: { lbessard@321: stopPLC(); lbessard@321: // signal(SIGTERM, catch_signal); lbessard@321: signal(SIGINT, catch_signal); lbessard@321: printf("Got Signal %d\n",sig); lbessard@321: exit(0); lbessard@321: } lbessard@321: Edouard@1981: #define _startPLCLog(text) \ Edouard@1981: {\ Edouard@1981: char mstr[] = text;\ Edouard@1981: LogMessage(LOG_CRITICAL, mstr, sizeof(mstr));\ Edouard@1981: goto error;\ Edouard@1981: } Edouard@1981: Edouard@1981: #define FO "Failed opening " Edouard@1981: lbessard@321: #define max_val(a,b) ((a>b)?a:b) lbessard@321: int startPLC(int argc,char **argv) lbessard@321: { lbessard@321: signal(SIGINT, catch_signal); greg@336: Edouard@615: /* no memory swapping for that process */ lbessard@321: mlockall(MCL_CURRENT | MCL_FUTURE); greg@336: laurent@745: PLC_shutdown = 0; laurent@745: Edouard@615: /*** RT Pipes creation and opening ***/ Edouard@615: /* create Debug_pipe */ Edouard@1980: if(rt_pipe_create(&Debug_pipe, "Debug_pipe", DEBUG_PIPE_MINOR, PIPE_SIZE) < 0) Edouard@1981: _startPLCLog(FO "Debug_pipe real-time end"); Edouard@615: PLC_state |= PLC_STATE_DEBUG_PIPE_CREATED; Edouard@615: Edouard@615: /* open Debug_pipe*/ Edouard@1981: if((Debug_pipe_fd = open(DEBUG_PIPE_DEVICE, O_RDWR)) == -1) Edouard@1981: _startPLCLog(FO DEBUG_PIPE_DEVICE); Edouard@615: PLC_state |= PLC_STATE_DEBUG_FILE_OPENED; Edouard@615: Edouard@615: /* create Python_pipe */ Edouard@1980: if(rt_pipe_create(&Python_pipe, "Python_pipe", PYTHON_PIPE_MINOR, PIPE_SIZE) < 0) Edouard@1981: _startPLCLog(FO "Python_pipe real-time end"); Edouard@615: PLC_state |= PLC_STATE_PYTHON_PIPE_CREATED; Edouard@615: Edouard@615: /* open Python_pipe*/ Edouard@1981: if((Python_pipe_fd = open(PYTHON_PIPE_DEVICE, O_RDWR)) == -1) Edouard@1981: _startPLCLog(FO PYTHON_PIPE_DEVICE); Edouard@615: PLC_state |= PLC_STATE_PYTHON_FILE_OPENED; greg@336: greg@342: /* create WaitDebug_pipe */ Edouard@1980: if(rt_pipe_create(&WaitDebug_pipe, "WaitDebug_pipe", WAITDEBUG_PIPE_MINOR, PIPE_SIZE) < 0) Edouard@1981: _startPLCLog(FO "WaitDebug_pipe real-time end"); Edouard@615: PLC_state |= PLC_STATE_WAITDEBUG_PIPE_CREATED; greg@342: greg@342: /* open WaitDebug_pipe*/ Edouard@1981: if((WaitDebug_pipe_fd = open(WAITDEBUG_PIPE_DEVICE, O_RDWR)) == -1) Edouard@1981: _startPLCLog(FO WAITDEBUG_PIPE_DEVICE); Edouard@615: PLC_state |= PLC_STATE_WAITDEBUG_FILE_OPENED; Edouard@615: Edouard@615: /* create WaitPython_pipe */ Edouard@1980: if(rt_pipe_create(&WaitPython_pipe, "WaitPython_pipe", WAITPYTHON_PIPE_MINOR, PIPE_SIZE) < 0) Edouard@1981: _startPLCLog(FO "WaitPython_pipe real-time end"); Edouard@615: PLC_state |= PLC_STATE_WAITPYTHON_PIPE_CREATED; Edouard@615: Edouard@615: /* open WaitPython_pipe*/ Edouard@1981: if((WaitPython_pipe_fd = open(WAITPYTHON_PIPE_DEVICE, O_RDWR)) == -1) Edouard@1981: _startPLCLog(FO WAITPYTHON_PIPE_DEVICE); Edouard@615: PLC_state |= PLC_STATE_WAITPYTHON_FILE_OPENED; Edouard@615: Edouard@615: /*** create PLC task ***/ Edouard@1981: if(rt_task_create(&PLC_task, "PLC_task", 0, 50, T_JOINABLE)) Edouard@1981: _startPLCLog("Failed creating PLC task"); lbessard@321: PLC_state |= PLC_STATE_TASK_CREATED; greg@336: Edouard@615: if(__init(argc,argv)) goto error; Edouard@615: Edouard@615: /* start PLC task */ Edouard@1981: if(rt_task_start(&PLC_task, &PLC_task_proc, NULL)) Edouard@1981: _startPLCLog("Failed starting PLC task"); lbessard@321: lbessard@321: return 0; lbessard@321: lbessard@321: error: Edouard@616: lbessard@321: PLC_cleanup_all(); lbessard@321: return 1; lbessard@321: } lbessard@321: Edouard@615: #define DEBUG_FREE 0 Edouard@615: #define DEBUG_BUSY 1 Edouard@615: static long debug_state = DEBUG_FREE; Edouard@615: lbessard@321: int TryEnterDebugSection(void) lbessard@321: { Edouard@616: if(AtomicCompareExchange( Edouard@615: &debug_state, Edouard@615: DEBUG_FREE, Edouard@616: DEBUG_BUSY) == DEBUG_FREE){ Edouard@616: if(__DEBUG){ Edouard@616: return 1; Edouard@616: } Edouard@616: AtomicCompareExchange( &debug_state, DEBUG_BUSY, DEBUG_FREE); Edouard@616: } Edouard@616: return 0; Edouard@615: } Edouard@615: lbessard@321: void LeaveDebugSection(void) lbessard@321: { Edouard@615: if(AtomicCompareExchange( &debug_state, Edouard@615: DEBUG_BUSY, DEBUG_FREE) == DEBUG_BUSY){ Edouard@615: char msg = DEBUG_UNLOCK; Edouard@615: /* signal to NRT for wakeup */ Edouard@615: rt_pipe_write(&Debug_pipe, &msg, sizeof(msg), P_NORMAL); Edouard@615: } lbessard@321: } lbessard@321: laurent@397: extern unsigned long __tick; Edouard@615: ed@446: int WaitDebugData(unsigned long *tick) lbessard@321: { Edouard@615: char cmd; greg@345: int res; laurent@745: if (PLC_shutdown) return -1; lbessard@321: /* Wait signal from PLC thread */ Edouard@615: res = read(WaitDebug_pipe_fd, &cmd, sizeof(cmd)); Edouard@617: if (res == sizeof(cmd) && cmd == DEBUG_PENDING_DATA){ Edouard@617: *tick = __debug_tick; Edouard@615: return 0; Edouard@617: } greg@345: return -1; lbessard@321: } greg@336: lbessard@321: /* Called by PLC thread when debug_publish finished lbessard@321: * This is supposed to unlock debugger thread in WaitDebugData*/ lbessard@321: void InitiateDebugTransfer() lbessard@321: { Edouard@615: char msg = DEBUG_PENDING_DATA; lbessard@321: /* remember tick */ lbessard@321: __debug_tick = __tick; lbessard@321: /* signal debugger thread it can read data */ Edouard@615: rt_pipe_write(&WaitDebug_pipe, &msg, sizeof(msg), P_NORMAL); Edouard@615: } Edouard@615: Edouard@615: int suspendDebug(int disable) Edouard@615: { Edouard@615: char cmd = DEBUG_UNLOCK; laurent@745: if (PLC_shutdown) return -1; Edouard@615: while(AtomicCompareExchange( Edouard@615: &debug_state, Edouard@615: DEBUG_FREE, Edouard@615: DEBUG_BUSY) != DEBUG_FREE && Edouard@615: cmd == DEBUG_UNLOCK){ Edouard@616: if(read(Debug_pipe_fd, &cmd, sizeof(cmd)) != sizeof(cmd)){ Edouard@615: return -1; Edouard@615: } Edouard@615: } Edouard@615: __DEBUG = !disable; Edouard@617: if (disable) Edouard@617: AtomicCompareExchange( &debug_state, DEBUG_BUSY, DEBUG_FREE); Edouard@615: return 0; lbessard@321: } lbessard@321: lbessard@321: void resumeDebug(void) lbessard@321: { Edouard@615: AtomicCompareExchange( &debug_state, DEBUG_BUSY, DEBUG_FREE); Edouard@615: } Edouard@615: Edouard@615: #define PYTHON_FREE 0 Edouard@615: #define PYTHON_BUSY 1 Edouard@615: static long python_state = PYTHON_FREE; Edouard@615: lbessard@321: int WaitPythonCommands(void) Edouard@615: { Edouard@615: char cmd; laurent@745: if (PLC_shutdown) return -1; lbessard@321: /* Wait signal from PLC thread */ Edouard@615: if(read(WaitPython_pipe_fd, &cmd, sizeof(cmd))==sizeof(cmd) && cmd==PYTHON_PENDING_COMMAND){ Edouard@615: return 0; greg@345: } greg@345: return -1; lbessard@321: } greg@336: lbessard@321: /* Called by PLC thread on each new python command*/ lbessard@321: void UnBlockPythonCommands(void) lbessard@321: { Edouard@615: char msg = PYTHON_PENDING_COMMAND; Edouard@615: rt_pipe_write(&WaitPython_pipe, &msg, sizeof(msg), P_NORMAL); lbessard@321: } lbessard@321: lbessard@321: int TryLockPython(void) lbessard@321: { Edouard@615: return AtomicCompareExchange( Edouard@615: &python_state, Edouard@615: PYTHON_FREE, Edouard@615: PYTHON_BUSY) == PYTHON_FREE; Edouard@615: } Edouard@615: Edouard@615: #define UNLOCK_PYTHON 1 Edouard@615: void LockPython(void) Edouard@615: { Edouard@615: char cmd = UNLOCK_PYTHON; laurent@745: if (PLC_shutdown) return; Edouard@615: while(AtomicCompareExchange( Edouard@615: &python_state, Edouard@615: PYTHON_FREE, Edouard@615: PYTHON_BUSY) != PYTHON_FREE && Edouard@615: cmd == UNLOCK_PYTHON){ Edouard@615: read(Python_pipe_fd, &cmd, sizeof(cmd)); Edouard@615: } lbessard@321: } lbessard@321: lbessard@321: void UnLockPython(void) lbessard@321: { Edouard@615: if(AtomicCompareExchange( Edouard@615: &python_state, Edouard@615: PYTHON_BUSY, Edouard@615: PYTHON_FREE) == PYTHON_BUSY){ Edouard@615: if(rt_task_self()){/*is that the real time task ?*/ Edouard@615: char cmd = UNLOCK_PYTHON; Edouard@615: rt_pipe_write(&Python_pipe, &cmd, sizeof(cmd), P_NORMAL); Edouard@615: }/* otherwise, no signaling from non real time */ Edouard@615: } /* as plc does not wait for lock. */ Edouard@615: } Edouard@615: Edouard@1903: #ifndef HAVE_RETAIN wuyangtang@1717: int CheckRetainBuffer(void) wuyangtang@1717: { wuyangtang@1717: return 1; wuyangtang@1717: } wuyangtang@1717: wuyangtang@1717: void ValidateRetainBuffer(void) wuyangtang@1717: { wuyangtang@1717: } wuyangtang@1717: wuyangtang@1717: void InValidateRetainBuffer(void) wuyangtang@1717: { wuyangtang@1717: } wuyangtang@1717: wuyangtang@1717: void Retain(unsigned int offset, unsigned int count, void *p) wuyangtang@1717: { wuyangtang@1717: } wuyangtang@1717: wuyangtang@1717: void Remind(unsigned int offset, unsigned int count, void *p) wuyangtang@1717: { wuyangtang@1717: } wuyangtang@1717: wuyangtang@1717: void CleanupRetain(void) wuyangtang@1717: { wuyangtang@1717: } wuyangtang@1717: wuyangtang@1717: void InitRetain(void) wuyangtang@1717: { wuyangtang@1717: } Edouard@1903: #endif // !HAVE_RETAIN