1 /* |
1 /* |
2 * Python Asynchronous execution code |
2 * Python Asynchronous execution code |
3 * |
3 * |
4 * PLC put python commands in a fifo, respecting execution order |
4 * PLC put python commands in a fifo, respecting execution order |
5 * with the help of C pragmas inserted in python_eval FB code |
5 * with the help of C pragmas inserted in python_eval FB code |
6 * |
6 * |
7 * Buffer content is read asynchronously, (from non real time part), |
7 * Buffer content is read asynchronously, (from non real time part), |
8 * commands are executed and result stored for later use by PLC. |
8 * commands are executed and result stored for later use by PLC. |
9 * |
9 * |
10 * In this implementation, fifo is a list of pointer to python_eval |
10 * In this implementation, fifo is a list of pointer to python_eval |
11 * function blocks structures. Some local variables have been added in |
11 * function blocks structures. Some local variables have been added in |
12 * python_eval interface. We use those local variables as buffer and state |
12 * python_eval interface. We use those local variables as buffer and state |
13 * flags. |
13 * flags. |
14 * |
14 * |
15 * */ |
15 * */ |
16 |
16 |
17 #include "iec_types_all.h" |
17 #include "iec_types_all.h" |
18 #include "POUS.h" |
18 #include "POUS.h" |
19 #include <string.h> |
19 #include <string.h> |
28 static int PythonState; |
28 static int PythonState; |
29 #define PYTHON_LOCKED_BY_PYTHON 0 |
29 #define PYTHON_LOCKED_BY_PYTHON 0 |
30 #define PYTHON_LOCKED_BY_PLC 1 |
30 #define PYTHON_LOCKED_BY_PLC 1 |
31 #define PYTHON_MUSTWAKEUP 2 |
31 #define PYTHON_MUSTWAKEUP 2 |
32 #define PYTHON_FINISHED 4 |
32 #define PYTHON_FINISHED 4 |
33 |
33 |
34 /* Each python_eval FunctionBlock have it own state */ |
34 /* Each python_eval FunctionBlock have it own state */ |
35 #define PYTHON_FB_FREE 0 |
35 #define PYTHON_FB_FREE 0 |
36 #define PYTHON_FB_REQUESTED 1 |
36 #define PYTHON_FB_REQUESTED 1 |
37 #define PYTHON_FB_PROCESSING 2 |
37 #define PYTHON_FB_PROCESSING 2 |
38 #define PYTHON_FB_ANSWERED 3 |
38 #define PYTHON_FB_ANSWERED 3 |
60 UnBlockPythonCommands(); |
60 UnBlockPythonCommands(); |
61 } |
61 } |
62 |
62 |
63 void __retrieve_python() |
63 void __retrieve_python() |
64 { |
64 { |
65 /* Check Python thread is not being |
65 /* Check Python thread is not being |
66 * modifying internal python_eval data */ |
66 * modifying internal python_eval data */ |
67 PythonState = TryLockPython() ? |
67 PythonState = TryLockPython() ? |
68 PYTHON_LOCKED_BY_PLC : |
68 PYTHON_LOCKED_BY_PLC : |
69 PYTHON_LOCKED_BY_PYTHON; |
69 PYTHON_LOCKED_BY_PYTHON; |
70 /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON |
70 /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON |
71 * and python_eval will no do anything */ |
71 * and python_eval will no do anything */ |
72 } |
72 } |
73 |
73 |
74 void __publish_python() |
74 void __publish_python() |
75 { |
75 { |
81 } |
81 } |
82 UnLockPython(); |
82 UnLockPython(); |
83 } |
83 } |
84 } |
84 } |
85 /** |
85 /** |
86 * Called by the PLC, each time a python_eval |
86 * Called by the PLC, each time a python_eval |
87 * FB instance is executed |
87 * FB instance is executed |
88 */ |
88 */ |
89 void __PythonEvalFB(int poll, PYTHON_EVAL* data__) |
89 void __PythonEvalFB(int poll, PYTHON_EVAL* data__) |
90 { |
90 { |
91 /* detect rising edge on TRIG to trigger evaluation */ |
91 /* detect rising edge on TRIG to trigger evaluation */ |
92 if(((data__->TRIG && !data__->TRIGM1) || |
92 if(((data__->TRIG && !data__->TRIGM1) || |
93 /* polling is equivalent to trig on value rather than on rising edge*/ |
93 /* polling is equivalent to trig on value rather than on rising edge*/ |
94 (poll && data__->TRIG )) && |
94 (poll && data__->TRIG )) && |
95 /* trig only if not already trigged */ |
95 /* trig only if not already trigged */ |
96 data__->TRIGGED == 0){ |
96 data__->TRIGGED == 0){ |
97 /* mark as trigged */ |
97 /* mark as trigged */ |
120 /* when in polling, no answer == ack down */ |
120 /* when in polling, no answer == ack down */ |
121 data__->ACK = 0; |
121 data__->ACK = 0; |
122 } |
122 } |
123 /* got the order to act ?*/ |
123 /* got the order to act ?*/ |
124 if(data__->TRIGGED == 1 && |
124 if(data__->TRIGGED == 1 && |
125 /* and not already being processed */ |
125 /* and not already being processed */ |
126 data__->STATE == PYTHON_FB_FREE) |
126 data__->STATE == PYTHON_FB_FREE) |
127 { |
127 { |
128 /* Enter the block in the fifo |
128 /* Enter the block in the fifo |
129 /* Don't have to check if fifo cell is free |
129 /* Don't have to check if fifo cell is free |
130 * as fifo size == FB count, and a FB cannot |
130 * as fifo size == FB count, and a FB cannot |
131 * be requested twice */ |
131 * be requested twice */ |
132 EvalFBs[Current_PLC_EvalFB] = data__; |
132 EvalFBs[Current_PLC_EvalFB] = data__; |
133 /* copy into BUFFER local*/ |
133 /* copy into BUFFER local*/ |
134 data__->BUFFER = data__->PREBUFFER; |
134 data__->BUFFER = data__->PREBUFFER; |
135 /* Set ACK pin to low so that we can set a rising edge on result */ |
135 /* Set ACK pin to low so that we can set a rising edge on result */ |
184 /* Get a new line */ |
184 /* Get a new line */ |
185 Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d; |
185 Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d; |
186 //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB); |
186 //printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB); |
187 } |
187 } |
188 /* while next slot is empty */ |
188 /* while next slot is empty */ |
189 while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || |
189 while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || |
190 /* or doesn't contain command */ |
190 /* or doesn't contain command */ |
191 data__->STATE != PYTHON_FB_REQUESTED) |
191 data__->STATE != PYTHON_FB_REQUESTED) |
192 { |
192 { |
193 UnLockPython(); |
193 UnLockPython(); |
194 /* wait next FB to eval */ |
194 /* wait next FB to eval */ |
195 //printf("PythonIterator wait\n"); |
195 //printf("PythonIterator wait\n"); |
196 WaitPythonCommands(); |
196 if(WaitPythonCommands()) return NULL; |
197 /*emergency exit*/ |
197 /*emergency exit*/ |
198 if(PythonState & PYTHON_FINISHED) return NULL; |
198 if(PythonState & PYTHON_FINISHED) return NULL; |
199 LockPython(); |
199 LockPython(); |
200 } |
200 } |
201 /* Mark block as processing */ |
201 /* Mark block as processing */ |