lbessard@321: /** lbessard@321: * 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: lbessard@321: #include lbessard@321: #include lbessard@321: #include lbessard@321: #include greg@342: #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: lbessard@321: /* provided by POUS.C */ laurent@397: extern unsigned long common_ticktime__; 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: } 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: { lbessard@321: PLC_SetTimer(Ttick, Ttick); greg@336: lbessard@321: while (1) { lbessard@321: PLC_GetTime(&__CURRENT_TIME); lbessard@321: __run(); lbessard@321: if (PLC_shutdown) break; lbessard@321: rt_task_wait_period(NULL); lbessard@321: } 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); Edouard@615: PLC_state &= ~PLC_STATE_WAITDEBUG_PIPE_CREATED; Edouard@615: } Edouard@615: Edouard@615: if (PLC_state & PLC_STATE_WAITPYTHON_PIPE_CREATED) { 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); Edouard@615: PLC_state &= ~PLC_STATE_DEBUG_PIPE_CREATED; Edouard@615: } Edouard@615: Edouard@615: if (PLC_state & PLC_STATE_PYTHON_PIPE_CREATED) { 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: { lbessard@321: PLC_shutdown = 1; lbessard@321: /* Stop the PLC */ lbessard@321: PLC_SetTimer(0, 0); greg@342: __cleanup(); lbessard@321: PLC_cleanup_all(); 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: 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@397: /* Define Ttick to 1ms if common_ticktime not defined */ laurent@397: Ttick = common_ticktime__?common_ticktime__:1000000; greg@336: Edouard@615: /*** RT Pipes creation and opening ***/ Edouard@615: /* create Debug_pipe */ Edouard@615: if(rt_pipe_create(&Debug_pipe, "Debug_pipe", DEBUG_PIPE_MINOR, PIPE_SIZE)) Edouard@615: goto error; Edouard@615: PLC_state |= PLC_STATE_DEBUG_PIPE_CREATED; Edouard@615: Edouard@615: /* open Debug_pipe*/ Edouard@615: if((Debug_pipe_fd = open(DEBUG_PIPE_DEVICE, O_RDWR)) == -1) goto error; Edouard@615: PLC_state |= PLC_STATE_DEBUG_FILE_OPENED; Edouard@615: Edouard@615: /* create Python_pipe */ Edouard@615: if(rt_pipe_create(&Python_pipe, "Python_pipe", PYTHON_PIPE_MINOR, PIPE_SIZE)) Edouard@615: goto error; Edouard@615: PLC_state |= PLC_STATE_PYTHON_PIPE_CREATED; Edouard@615: Edouard@615: /* open Python_pipe*/ Edouard@615: if((Python_pipe_fd = open(PYTHON_PIPE_DEVICE, O_RDWR)) == -1) goto error; Edouard@615: PLC_state |= PLC_STATE_PYTHON_FILE_OPENED; greg@336: greg@342: /* create WaitDebug_pipe */ Edouard@616: if(rt_pipe_create(&WaitDebug_pipe, "WaitDebug_pipe", WAITDEBUG_PIPE_MINOR, PIPE_SIZE)) Edouard@615: goto error; Edouard@615: PLC_state |= PLC_STATE_WAITDEBUG_PIPE_CREATED; greg@342: greg@342: /* open WaitDebug_pipe*/ Edouard@615: if((WaitDebug_pipe_fd = open(WAITDEBUG_PIPE_DEVICE, O_RDWR)) == -1) goto error; Edouard@615: PLC_state |= PLC_STATE_WAITDEBUG_FILE_OPENED; Edouard@615: Edouard@615: /* create WaitPython_pipe */ Edouard@616: if(rt_pipe_create(&WaitPython_pipe, "WaitPython_pipe", WAITPYTHON_PIPE_MINOR, PIPE_SIZE)) greg@342: goto error; Edouard@615: PLC_state |= PLC_STATE_WAITPYTHON_PIPE_CREATED; Edouard@615: Edouard@615: /* open WaitPython_pipe*/ Edouard@615: if((WaitPython_pipe_fd = open(WAITPYTHON_PIPE_DEVICE, O_RDWR)) == -1) goto error; Edouard@615: PLC_state |= PLC_STATE_WAITPYTHON_FILE_OPENED; Edouard@615: Edouard@615: /*** create PLC task ***/ Edouard@615: if(rt_task_create(&PLC_task, "PLC_task", 0, 50, 0)) goto error; 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@615: if(rt_task_start(&PLC_task, &PLC_task_proc, NULL)) goto error; 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: Edouard@615: #define DEBUG_UNLOCK 1 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: Edouard@615: #define DEBUG_PENDING_DATA 1 ed@446: int WaitDebugData(unsigned long *tick) lbessard@321: { Edouard@615: char cmd; greg@345: int res; ed@446: *tick = __debug_tick; lbessard@321: /* Wait signal from PLC thread */ Edouard@615: res = read(WaitDebug_pipe_fd, &cmd, sizeof(cmd)); Edouard@615: if (res == sizeof(cmd) && cmd == DEBUG_PENDING_DATA) Edouard@615: return 0; 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; 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@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_PENDING_COMMAND 1 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; 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; 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@616: int CheckRetainBuffer(void) Edouard@616: { Edouard@616: return 1; Edouard@616: } Edouard@616: Edouard@616: void ValidateRetainBuffer(void) Edouard@616: { Edouard@616: } Edouard@616: Edouard@616: void InValidateRetainBuffer(void) Edouard@616: { Edouard@616: } Edouard@616: Edouard@616: void Retain(unsigned int offset, unsigned int count, void *p) Edouard@616: { Edouard@616: } Edouard@616: Edouard@616: void Remind(unsigned int offset, unsigned int count, void *p) Edouard@616: { Edouard@616: } Edouard@616: