72 } |
83 } |
73 } |
84 } |
74 |
85 |
75 static unsigned long __debug_tick; |
86 static unsigned long __debug_tick; |
76 |
87 |
77 RT_SEM python_wait_sem; |
|
78 RT_MUTEX python_mutex; |
|
79 RT_MUTEX debug_mutex; |
|
80 |
|
81 void PLC_cleanup_all(void) |
88 void PLC_cleanup_all(void) |
82 { |
89 { |
83 if (PLC_state & PLC_STATE_TASK_CREATED) { |
90 if (PLC_state & PLC_STATE_TASK_CREATED) { |
84 rt_task_delete(&PLC_task); |
91 rt_task_delete(&PLC_task); |
85 PLC_state &= ~PLC_STATE_TASK_CREATED; |
92 PLC_state &= ~PLC_STATE_TASK_CREATED; |
86 } |
93 } |
87 |
94 |
88 if (PLC_state & PLC_STATE_PYTHON_WAIT_SEM_CREATED) { |
95 if (PLC_state & PLC_STATE_WAITDEBUG_PIPE_CREATED) { |
89 rt_sem_v(&python_wait_sem); |
96 rt_pipe_delete(&WaitDebug_pipe); |
90 rt_sem_delete(&python_wait_sem); |
97 PLC_state &= ~PLC_STATE_WAITDEBUG_PIPE_CREATED; |
91 PLC_state &= ~ PLC_STATE_PYTHON_WAIT_SEM_CREATED; |
98 } |
92 } |
99 |
93 |
100 if (PLC_state & PLC_STATE_WAITDEBUG_FILE_OPENED) { |
94 if (PLC_state & PLC_STATE_PYTHON_MUTEX_CREATED) { |
101 close(WaitDebug_pipe_fd); |
95 rt_mutex_delete(&python_mutex); |
102 PLC_state &= ~PLC_STATE_WAITDEBUG_FILE_OPENED; |
96 PLC_state &= ~ PLC_STATE_PYTHON_MUTEX_CREATED; |
103 } |
|
104 |
|
105 if (PLC_state & PLC_STATE_WAITPYTHON_PIPE_CREATED) { |
|
106 rt_pipe_delete(&WaitPython_pipe); |
|
107 PLC_state &= ~PLC_STATE_WAITDEBUG_PIPE_CREATED; |
|
108 } |
|
109 |
|
110 if (PLC_state & PLC_STATE_WAITPYTHON_PIPE_CREATED) { |
|
111 close(WaitPython_pipe_fd); |
|
112 PLC_state &= ~PLC_STATE_WAITPYTHON_FILE_OPENED; |
97 } |
113 } |
98 |
114 |
99 if (PLC_state & PLC_STATE_DEBUG_PIPE_CREATED) { |
115 if (PLC_state & PLC_STATE_DEBUG_PIPE_CREATED) { |
100 rt_pipe_delete(&WaitDebug_pipe); |
116 rt_pipe_delete(&Debug_pipe); |
101 PLC_state &= ~PLC_STATE_DEBUG_PIPE_CREATED; |
117 PLC_state &= ~PLC_STATE_DEBUG_PIPE_CREATED; |
102 } |
118 } |
103 |
119 |
104 if (PLC_state & PLC_STATE_DEBUG_FILE_OPENED) { |
120 if (PLC_state & PLC_STATE_DEBUG_FILE_OPENED) { |
105 close(WaitDebug_pipe_fd); |
121 close(Debug_pipe_fd); |
106 PLC_state &= ~PLC_STATE_DEBUG_FILE_OPENED; |
122 PLC_state &= ~PLC_STATE_DEBUG_FILE_OPENED; |
107 } |
123 } |
108 |
124 |
109 if (PLC_state & PLC_STATE_DEBUG_MUTEX_CREATED) { |
125 if (PLC_state & PLC_STATE_PYTHON_PIPE_CREATED) { |
110 rt_mutex_delete(&debug_mutex); |
126 rt_pipe_delete(&Python_pipe); |
111 PLC_state &= ~ PLC_STATE_DEBUG_MUTEX_CREATED; |
127 PLC_state &= ~PLC_STATE_DEBUG_PIPE_CREATED; |
112 } |
128 } |
|
129 |
|
130 if (PLC_state & PLC_STATE_PYTHON_PIPE_CREATED) { |
|
131 close(Python_pipe_fd); |
|
132 PLC_state &= ~PLC_STATE_PYTHON_FILE_OPENED; |
|
133 } |
|
134 |
113 } |
135 } |
114 |
136 |
115 int stopPLC() |
137 int stopPLC() |
116 { |
138 { |
117 PLC_shutdown = 1; |
139 PLC_shutdown = 1; |
118 /* Stop the PLC */ |
140 /* Stop the PLC */ |
119 PLC_SetTimer(0, 0); |
141 PLC_SetTimer(0, 0); |
120 __cleanup(); |
142 __cleanup(); |
121 PLC_cleanup_all(); |
143 PLC_cleanup_all(); |
122 __debug_tick = -1; |
144 __debug_tick = -1; |
|
145 return 0; |
123 } |
146 } |
124 |
147 |
125 // |
148 // |
126 void catch_signal(int sig) |
149 void catch_signal(int sig) |
127 { |
150 { |
133 } |
156 } |
134 |
157 |
135 #define max_val(a,b) ((a>b)?a:b) |
158 #define max_val(a,b) ((a>b)?a:b) |
136 int startPLC(int argc,char **argv) |
159 int startPLC(int argc,char **argv) |
137 { |
160 { |
138 int ret = 0; |
|
139 |
|
140 signal(SIGINT, catch_signal); |
161 signal(SIGINT, catch_signal); |
141 |
162 |
142 /* ne-memory-swapping for this program */ |
163 /* no memory swapping for that process */ |
143 mlockall(MCL_CURRENT | MCL_FUTURE); |
164 mlockall(MCL_CURRENT | MCL_FUTURE); |
144 |
165 |
145 /* Define Ttick to 1ms if common_ticktime not defined */ |
166 /* Define Ttick to 1ms if common_ticktime not defined */ |
146 Ttick = common_ticktime__?common_ticktime__:1000000; |
167 Ttick = common_ticktime__?common_ticktime__:1000000; |
147 |
168 |
148 /* create python_wait_sem */ |
169 /*** RT Pipes creation and opening ***/ |
149 ret = rt_sem_create(&python_wait_sem, "python_wait_sem", 0, S_FIFO); |
170 /* create Debug_pipe */ |
150 if (ret) goto error; |
171 if(rt_pipe_create(&Debug_pipe, "Debug_pipe", DEBUG_PIPE_MINOR, PIPE_SIZE)) |
151 PLC_state |= PLC_STATE_PYTHON_WAIT_SEM_CREATED; |
172 goto error; |
152 |
173 PLC_state |= PLC_STATE_DEBUG_PIPE_CREATED; |
153 /* create python_mutex */ |
174 |
154 ret = rt_mutex_create(&python_mutex, "python_mutex"); |
175 /* open Debug_pipe*/ |
155 if (ret) goto error; |
176 if((Debug_pipe_fd = open(DEBUG_PIPE_DEVICE, O_RDWR)) == -1) goto error; |
156 PLC_state |= PLC_STATE_PYTHON_MUTEX_CREATED; |
177 PLC_state |= PLC_STATE_DEBUG_FILE_OPENED; |
|
178 |
|
179 /* create Python_pipe */ |
|
180 if(rt_pipe_create(&Python_pipe, "Python_pipe", PYTHON_PIPE_MINOR, PIPE_SIZE)) |
|
181 goto error; |
|
182 PLC_state |= PLC_STATE_PYTHON_PIPE_CREATED; |
|
183 |
|
184 /* open Python_pipe*/ |
|
185 if((Python_pipe_fd = open(PYTHON_PIPE_DEVICE, O_RDWR)) == -1) goto error; |
|
186 PLC_state |= PLC_STATE_PYTHON_FILE_OPENED; |
157 |
187 |
158 /* create WaitDebug_pipe */ |
188 /* create WaitDebug_pipe */ |
159 ret = rt_pipe_create(&WaitDebug_pipe, "WaitDebug_pipe", WAITDEBUG_PIPE_MINOR, |
189 if(rt_pipe_create(&WaitDebug_pipe, "Debug_pipe", WAITDEBUG_PIPE_MINOR, PIPE_SIZE)) |
160 WAITDEBUG_PIPE_SIZE * sizeof(char)); |
190 goto error; |
161 if (ret) goto error; |
191 PLC_state |= PLC_STATE_WAITDEBUG_PIPE_CREATED; |
162 PLC_state |= PLC_STATE_DEBUG_PIPE_CREATED; |
|
163 |
192 |
164 /* open WaitDebug_pipe*/ |
193 /* open WaitDebug_pipe*/ |
165 WaitDebug_pipe_fd = open(WAITDEBUG_PIPE_DEVICE, O_RDWR); |
194 if((WaitDebug_pipe_fd = open(WAITDEBUG_PIPE_DEVICE, O_RDWR)) == -1) goto error; |
166 if (WaitDebug_pipe_fd == -1) { |
195 PLC_state |= PLC_STATE_WAITDEBUG_FILE_OPENED; |
167 ret = -EBADF; |
196 |
|
197 /* create WaitPython_pipe */ |
|
198 if(rt_pipe_create(&WaitPython_pipe, "Python_pipe", WAITPYTHON_PIPE_MINOR, PIPE_SIZE)) |
168 goto error; |
199 goto error; |
169 } |
200 PLC_state |= PLC_STATE_WAITPYTHON_PIPE_CREATED; |
170 PLC_state |= PLC_STATE_DEBUG_FILE_OPENED; |
201 |
171 |
202 /* open WaitPython_pipe*/ |
172 /* create debug_mutex */ |
203 if((WaitPython_pipe_fd = open(WAITPYTHON_PIPE_DEVICE, O_RDWR)) == -1) goto error; |
173 ret = rt_mutex_create(&debug_mutex, "debug_mutex"); |
204 PLC_state |= PLC_STATE_WAITPYTHON_FILE_OPENED; |
174 if (ret) goto error; |
205 |
175 PLC_state |= PLC_STATE_DEBUG_MUTEX_CREATED; |
206 /*** create PLC task ***/ |
176 |
207 if(rt_task_create(&PLC_task, "PLC_task", 0, 50, 0)) goto error; |
177 /* create can_driver_task */ |
|
178 ret = rt_task_create(&PLC_task, "PLC_task", 0, 50, 0); |
|
179 if (ret) goto error; |
|
180 PLC_state |= PLC_STATE_TASK_CREATED; |
208 PLC_state |= PLC_STATE_TASK_CREATED; |
181 |
209 |
182 ret = __init(argc,argv); |
210 if(__init(argc,argv)) goto error; |
183 if (ret) goto error; |
211 |
184 |
212 /* start PLC task */ |
185 /* start can_driver_task */ |
213 if(rt_task_start(&PLC_task, &PLC_task_proc, NULL)) goto error; |
186 ret = rt_task_start(&PLC_task, &PLC_task_proc, NULL); |
|
187 if (ret) goto error; |
|
188 |
214 |
189 return 0; |
215 return 0; |
190 |
216 |
191 error: |
217 error: |
192 PLC_cleanup_all(); |
218 PLC_cleanup_all(); |
193 return 1; |
219 return 1; |
194 } |
220 } |
195 |
221 |
|
222 #define DEBUG_FREE 0 |
|
223 #define DEBUG_BUSY 1 |
|
224 static long debug_state = DEBUG_FREE; |
|
225 |
196 int TryEnterDebugSection(void) |
226 int TryEnterDebugSection(void) |
197 { |
227 { |
198 return rt_mutex_acquire(&debug_mutex, TM_NONBLOCK) == 0; |
228 long old_debug_state = AtomicCompareExchange( |
199 } |
229 &debug_state, |
200 |
230 DEBUG_FREE, |
|
231 DEBUG_BUSY); |
|
232 return old_debug_state == DEBUG_FREE; |
|
233 } |
|
234 |
|
235 #define DEBUG_UNLOCK 1 |
201 void LeaveDebugSection(void) |
236 void LeaveDebugSection(void) |
202 { |
237 { |
203 rt_mutex_release(&debug_mutex); |
238 if(AtomicCompareExchange( &debug_state, |
|
239 DEBUG_BUSY, DEBUG_FREE) == DEBUG_BUSY){ |
|
240 char msg = DEBUG_UNLOCK; |
|
241 /* signal to NRT for wakeup */ |
|
242 rt_pipe_write(&Debug_pipe, &msg, sizeof(msg), P_NORMAL); |
|
243 } |
204 } |
244 } |
205 |
245 |
206 extern unsigned long __tick; |
246 extern unsigned long __tick; |
207 /* from plc_debugger.c */ |
247 |
|
248 #define DEBUG_PENDING_DATA 1 |
208 int WaitDebugData(unsigned long *tick) |
249 int WaitDebugData(unsigned long *tick) |
209 { |
250 { |
210 char message; |
251 char cmd; |
211 int res; |
252 int res; |
212 *tick = __debug_tick; |
253 *tick = __debug_tick; |
213 /* Wait signal from PLC thread */ |
254 /* Wait signal from PLC thread */ |
214 if (PLC_state & PLC_STATE_DEBUG_FILE_OPENED) { |
255 res = read(WaitDebug_pipe_fd, &cmd, sizeof(cmd)); |
215 res = read(WaitDebug_pipe_fd, &message, sizeof(char)); |
256 if (res == sizeof(cmd) && cmd == DEBUG_PENDING_DATA) |
216 if (res == sizeof(char)) |
257 return 0; |
217 return 0; |
|
218 } |
|
219 return -1; |
258 return -1; |
220 } |
259 } |
221 |
260 |
222 /* Called by PLC thread when debug_publish finished |
261 /* Called by PLC thread when debug_publish finished |
223 * This is supposed to unlock debugger thread in WaitDebugData*/ |
262 * This is supposed to unlock debugger thread in WaitDebugData*/ |
224 void InitiateDebugTransfer() |
263 void InitiateDebugTransfer() |
225 { |
264 { |
226 char message = 1; |
265 char msg = DEBUG_PENDING_DATA; |
227 /* remember tick */ |
266 /* remember tick */ |
228 __debug_tick = __tick; |
267 __debug_tick = __tick; |
229 /* signal debugger thread it can read data */ |
268 /* signal debugger thread it can read data */ |
230 if (PLC_state & PLC_STATE_DEBUG_PIPE_CREATED) |
269 rt_pipe_write(&WaitDebug_pipe, &msg, sizeof(msg), P_NORMAL); |
231 rt_pipe_write(&WaitDebug_pipe, &message, sizeof(char), P_NORMAL); |
270 } |
232 } |
271 |
233 |
272 int suspendDebug(int disable) |
234 void suspendDebug(void) |
273 { |
235 { |
274 char cmd = DEBUG_UNLOCK; |
236 __DEBUG = 0; |
275 while(AtomicCompareExchange( |
237 if (PLC_state & PLC_STATE_DEBUG_MUTEX_CREATED) { |
276 &debug_state, |
238 rt_task_shadow(&SuspendDebug_task, "SuspendDebug_task", 0, 0); |
277 DEBUG_FREE, |
239 /* Prevent PLC to enter debug code */ |
278 DEBUG_BUSY) != DEBUG_FREE && |
240 rt_mutex_acquire(&debug_mutex, TM_INFINITE); |
279 cmd == DEBUG_UNLOCK){ |
241 } |
280 if(read(Debug_pipe_fd, &cmd, sizeof(cmd)) == sizeof(cmd)){ |
|
281 return -1; |
|
282 } |
|
283 } |
|
284 __DEBUG = !disable; |
|
285 return 0; |
242 } |
286 } |
243 |
287 |
244 void resumeDebug(void) |
288 void resumeDebug(void) |
245 { |
289 { |
246 __DEBUG = 1; |
290 AtomicCompareExchange( &debug_state, DEBUG_BUSY, DEBUG_FREE); |
247 if (PLC_state & PLC_STATE_DEBUG_MUTEX_CREATED) { |
291 } |
248 rt_task_shadow(&ResumeDebug_task, "ResumeDebug_task", 0, 0); |
292 |
249 /* Let PLC enter debug code */ |
293 #define PYTHON_PENDING_COMMAND 1 |
250 rt_mutex_release(&debug_mutex); |
294 |
251 } |
295 #define PYTHON_FREE 0 |
252 } |
296 #define PYTHON_BUSY 1 |
253 |
297 static long python_state = PYTHON_FREE; |
254 /* from plc_python.c */ |
298 |
255 int WaitPythonCommands(void) |
299 int WaitPythonCommands(void) |
256 { |
300 { |
|
301 char cmd; |
257 /* Wait signal from PLC thread */ |
302 /* Wait signal from PLC thread */ |
258 if (PLC_state & PLC_STATE_PYTHON_WAIT_SEM_CREATED) { |
303 if(read(WaitPython_pipe_fd, &cmd, sizeof(cmd))==sizeof(cmd) && cmd==PYTHON_PENDING_COMMAND){ |
259 rt_task_shadow(&WaitPythonCommand_task, "WaitPythonCommand_task", 0, 0); |
304 return 0; |
260 return rt_sem_p(&python_wait_sem, TM_INFINITE); |
|
261 } |
305 } |
262 return -1; |
306 return -1; |
263 } |
307 } |
264 |
308 |
265 /* Called by PLC thread on each new python command*/ |
309 /* Called by PLC thread on each new python command*/ |
266 void UnBlockPythonCommands(void) |
310 void UnBlockPythonCommands(void) |
267 { |
311 { |
268 /* signal debugger thread it can read data */ |
312 char msg = PYTHON_PENDING_COMMAND; |
269 rt_sem_v(&python_wait_sem); |
313 rt_pipe_write(&WaitPython_pipe, &msg, sizeof(msg), P_NORMAL); |
270 } |
314 } |
271 |
315 |
272 int TryLockPython(void) |
316 int TryLockPython(void) |
273 { |
317 { |
274 return rt_mutex_acquire(&python_mutex, TM_NONBLOCK) == 0; |
318 return AtomicCompareExchange( |
|
319 &python_state, |
|
320 PYTHON_FREE, |
|
321 PYTHON_BUSY) == PYTHON_FREE; |
|
322 } |
|
323 |
|
324 #define UNLOCK_PYTHON 1 |
|
325 void LockPython(void) |
|
326 { |
|
327 char cmd = UNLOCK_PYTHON; |
|
328 while(AtomicCompareExchange( |
|
329 &python_state, |
|
330 PYTHON_FREE, |
|
331 PYTHON_BUSY) != PYTHON_FREE && |
|
332 cmd == UNLOCK_PYTHON){ |
|
333 read(Python_pipe_fd, &cmd, sizeof(cmd)); |
|
334 } |
275 } |
335 } |
276 |
336 |
277 void UnLockPython(void) |
337 void UnLockPython(void) |
278 { |
338 { |
279 if (PLC_state & PLC_STATE_PYTHON_MUTEX_CREATED) { |
339 if(AtomicCompareExchange( |
280 rt_task_shadow(&UnLockPython_task, "UnLockPython_task", 0, 0); |
340 &python_state, |
281 rt_mutex_release(&python_mutex); |
341 PYTHON_BUSY, |
282 } |
342 PYTHON_FREE) == PYTHON_BUSY){ |
283 } |
343 if(rt_task_self()){/*is that the real time task ?*/ |
284 |
344 char cmd = UNLOCK_PYTHON; |
285 void LockPython(void) |
345 rt_pipe_write(&Python_pipe, &cmd, sizeof(cmd), P_NORMAL); |
286 { |
346 }/* otherwise, no signaling from non real time */ |
287 if (PLC_state & PLC_STATE_PYTHON_MUTEX_CREATED) { |
347 } /* as plc does not wait for lock. */ |
288 rt_task_shadow(&LockPython_task, "LockPython_task", 0, 0); |
348 } |
289 rt_mutex_acquire(&python_mutex, TM_INFINITE); |
349 |
290 } |
|
291 } |
|