targets/plc_python.c
changeset 329 22e65b8e20f4
parent 300 7f7912ae5ee8
equal deleted inserted replaced
328:c23daa6996c2 329:22e65b8e20f4
     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 */