]> git.sur5r.net Git - freertos/blob - Source/include/croutine.h
Update to V5.1.2.
[freertos] / Source / include / croutine.h
1 /*\r
2         FreeRTOS.org V5.1.2 - Copyright (C) 2003-2009 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section\r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26     ***************************************************************************\r
27     ***************************************************************************\r
28     *                                                                         *\r
29     * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
30         *                                                                         *\r
31         * This is a concise, step by step, 'hands on' guide that describes both   *\r
32         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
33         * explains numerous examples that are written using the FreeRTOS API.     *\r
34         * Full source code for all the examples is provided in an accompanying    *\r
35         * .zip file.                                                              *\r
36     *                                                                         *\r
37     ***************************************************************************\r
38     ***************************************************************************\r
39 \r
40         Please ensure to read the configuration and relevant port sections of the\r
41         online documentation.\r
42 \r
43         http://www.FreeRTOS.org - Documentation, latest information, license and \r
44         contact details.\r
45 \r
46         http://www.SafeRTOS.com - A version that is certified for use in safety \r
47         critical systems.\r
48 \r
49         http://www.OpenRTOS.com - Commercial support, development, porting, \r
50         licensing and training services.\r
51 */\r
52 \r
53 #ifndef INC_FREERTOS_H\r
54         #error "#include FreeRTOS.h" must appear in source files before "#include croutine.h"\r
55 #endif\r
56 \r
57 \r
58 \r
59 \r
60 #ifndef CO_ROUTINE_H\r
61 #define CO_ROUTINE_H\r
62 \r
63 #include "list.h"\r
64 \r
65 #ifdef __cplusplus\r
66 extern "C" {\r
67 #endif\r
68 \r
69 /* Used to hide the implementation of the co-routine control block.  The\r
70 control block structure however has to be included in the header due to\r
71 the macro implementation of the co-routine functionality. */\r
72 typedef void * xCoRoutineHandle;\r
73 \r
74 /* Defines the prototype to which co-routine functions must conform. */\r
75 typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE );\r
76 \r
77 typedef struct corCoRoutineControlBlock\r
78 {\r
79         crCOROUTINE_CODE                pxCoRoutineFunction;\r
80         xListItem                               xGenericListItem;       /*< List item used to place the CRCB in ready and blocked queues. */\r
81         xListItem                               xEventListItem;         /*< List item used to place the CRCB in event lists. */\r
82         unsigned portBASE_TYPE  uxPriority;                     /*< The priority of the co-routine in relation to other co-routines. */\r
83         unsigned portBASE_TYPE  uxIndex;                        /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */\r
84         unsigned portSHORT              uxState;                        /*< Used internally by the co-routine implementation. */\r
85 } corCRCB; /* Co-routine control block.  Note must be identical in size down to uxPriority with tskTCB. */\r
86 \r
87 /**\r
88  * croutine. h\r
89  *<pre>\r
90  portBASE_TYPE xCoRoutineCreate(\r
91                                  crCOROUTINE_CODE pxCoRoutineCode,\r
92                                  unsigned portBASE_TYPE uxPriority,\r
93                                  unsigned portBASE_TYPE uxIndex\r
94                                );</pre>\r
95  *\r
96  * Create a new co-routine and add it to the list of co-routines that are\r
97  * ready to run.\r
98  *\r
99  * @param pxCoRoutineCode Pointer to the co-routine function.  Co-routine\r
100  * functions require special syntax - see the co-routine section of the WEB\r
101  * documentation for more information.\r
102  *\r
103  * @param uxPriority The priority with respect to other co-routines at which\r
104  *  the co-routine will run.\r
105  *\r
106  * @param uxIndex Used to distinguish between different co-routines that\r
107  * execute the same function.  See the example below and the co-routine section\r
108  * of the WEB documentation for further information.\r
109  *\r
110  * @return pdPASS if the co-routine was successfully created and added to a ready\r
111  * list, otherwise an error code defined with ProjDefs.h.\r
112  *\r
113  * Example usage:\r
114    <pre>\r
115  // Co-routine to be created.\r
116  void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
117  {\r
118  // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
119  // This may not be necessary for const variables.\r
120  static const char cLedToFlash[ 2 ] = { 5, 6 };\r
121  static const portTickType xTimeToDelay[ 2 ] = { 200, 400 };\r
122 \r
123      // Must start every co-routine with a call to crSTART();\r
124      crSTART( xHandle );\r
125 \r
126      for( ;; )\r
127      {\r
128          // This co-routine just delays for a fixed period, then toggles\r
129          // an LED.  Two co-routines are created using this function, so\r
130          // the uxIndex parameter is used to tell the co-routine which\r
131          // LED to flash and how long to delay.  This assumes xQueue has\r
132          // already been created.\r
133          vParTestToggleLED( cLedToFlash[ uxIndex ] );\r
134          crDELAY( xHandle, uxFlashRates[ uxIndex ] );\r
135      }\r
136 \r
137      // Must end every co-routine with a call to crEND();\r
138      crEND();\r
139  }\r
140 \r
141  // Function that creates two co-routines.\r
142  void vOtherFunction( void )\r
143  {\r
144  unsigned char ucParameterToPass;\r
145  xTaskHandle xHandle;\r
146                 \r
147      // Create two co-routines at priority 0.  The first is given index 0\r
148      // so (from the code above) toggles LED 5 every 200 ticks.  The second\r
149      // is given index 1 so toggles LED 6 every 400 ticks.\r
150      for( uxIndex = 0; uxIndex < 2; uxIndex++ )\r
151      {\r
152          xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );\r
153      }\r
154  }\r
155    </pre>\r
156  * \defgroup xCoRoutineCreate xCoRoutineCreate\r
157  * \ingroup Tasks\r
158  */\r
159 signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex );\r
160 \r
161 \r
162 /**\r
163  * croutine. h\r
164  *<pre>\r
165  void vCoRoutineSchedule( void );</pre>\r
166  *\r
167  * Run a co-routine.\r
168  *\r
169  * vCoRoutineSchedule() executes the highest priority co-routine that is able\r
170  * to run.  The co-routine will execute until it either blocks, yields or is\r
171  * preempted by a task.  Co-routines execute cooperatively so one\r
172  * co-routine cannot be preempted by another, but can be preempted by a task.\r
173  *\r
174  * If an application comprises of both tasks and co-routines then\r
175  * vCoRoutineSchedule should be called from the idle task (in an idle task\r
176  * hook).\r
177  *\r
178  * Example usage:\r
179    <pre>\r
180  // This idle task hook will schedule a co-routine each time it is called.\r
181  // The rest of the idle task will execute between co-routine calls.\r
182  void vApplicationIdleHook( void )\r
183  {\r
184         vCoRoutineSchedule();\r
185  }\r
186 \r
187  // Alternatively, if you do not require any other part of the idle task to\r
188  // execute, the idle task hook can call vCoRoutineScheduler() within an\r
189  // infinite loop.\r
190  void vApplicationIdleHook( void )\r
191  {\r
192     for( ;; )\r
193     {\r
194         vCoRoutineSchedule();\r
195     }\r
196  }\r
197  </pre>\r
198  * \defgroup vCoRoutineSchedule vCoRoutineSchedule\r
199  * \ingroup Tasks\r
200  */\r
201 void vCoRoutineSchedule( void );\r
202 \r
203 /**\r
204  * croutine. h\r
205  * <pre>\r
206  crSTART( xCoRoutineHandle xHandle );</pre>\r
207  *\r
208  * This macro MUST always be called at the start of a co-routine function.\r
209  *\r
210  * Example usage:\r
211    <pre>\r
212  // Co-routine to be created.\r
213  void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
214  {\r
215  // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
216  static portLONG ulAVariable;\r
217 \r
218      // Must start every co-routine with a call to crSTART();\r
219      crSTART( xHandle );\r
220 \r
221      for( ;; )\r
222      {\r
223           // Co-routine functionality goes here.\r
224      }\r
225 \r
226      // Must end every co-routine with a call to crEND();\r
227      crEND();\r
228  }</pre>\r
229  * \defgroup crSTART crSTART\r
230  * \ingroup Tasks\r
231  */\r
232 #define crSTART( pxCRCB ) switch( ( ( corCRCB * )pxCRCB )->uxState ) { case 0:\r
233 \r
234 /**\r
235  * croutine. h\r
236  * <pre>\r
237  crEND();</pre>\r
238  *\r
239  * This macro MUST always be called at the end of a co-routine function.\r
240  *\r
241  * Example usage:\r
242    <pre>\r
243  // Co-routine to be created.\r
244  void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
245  {\r
246  // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
247  static portLONG ulAVariable;\r
248 \r
249      // Must start every co-routine with a call to crSTART();\r
250      crSTART( xHandle );\r
251 \r
252      for( ;; )\r
253      {\r
254           // Co-routine functionality goes here.\r
255      }\r
256 \r
257      // Must end every co-routine with a call to crEND();\r
258      crEND();\r
259  }</pre>\r
260  * \defgroup crSTART crSTART\r
261  * \ingroup Tasks\r
262  */\r
263 #define crEND() }\r
264 \r
265 /*\r
266  * These macros are intended for internal use by the co-routine implementation\r
267  * only.  The macros should not be used directly by application writers.\r
268  */\r
269 #define crSET_STATE0( xHandle ) ( ( corCRCB * )xHandle)->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):\r
270 #define crSET_STATE1( xHandle ) ( ( corCRCB * )xHandle)->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):\r
271 \r
272 /**\r
273  * croutine. h\r
274  *<pre>\r
275  crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );</pre>\r
276  *\r
277  * Delay a co-routine for a fixed period of time.\r
278  *\r
279  * crDELAY can only be called from the co-routine function itself - not\r
280  * from within a function called by the co-routine function.  This is because\r
281  * co-routines do not maintain their own stack.\r
282  *\r
283  * @param xHandle The handle of the co-routine to delay.  This is the xHandle\r
284  * parameter of the co-routine function.\r
285  *\r
286  * @param xTickToDelay The number of ticks that the co-routine should delay\r
287  * for.  The actual amount of time this equates to is defined by\r
288  * configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant portTICK_RATE_MS\r
289  * can be used to convert ticks to milliseconds.\r
290  *\r
291  * Example usage:\r
292    <pre>\r
293  // Co-routine to be created.\r
294  void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
295  {\r
296  // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
297  // This may not be necessary for const variables.\r
298  // We are to delay for 200ms.\r
299  static const xTickType xDelayTime = 200 / portTICK_RATE_MS;\r
300 \r
301      // Must start every co-routine with a call to crSTART();\r
302      crSTART( xHandle );\r
303 \r
304      for( ;; )\r
305      {\r
306         // Delay for 200ms.\r
307         crDELAY( xHandle, xDelayTime );\r
308 \r
309         // Do something here.\r
310      }\r
311 \r
312      // Must end every co-routine with a call to crEND();\r
313      crEND();\r
314  }</pre>\r
315  * \defgroup crDELAY crDELAY\r
316  * \ingroup Tasks\r
317  */\r
318 #define crDELAY( xHandle, xTicksToDelay )                                                                                               \\r
319         if( xTicksToDelay > 0 )                                                                                                                         \\r
320         {                                                                                                                                                                       \\r
321                 vCoRoutineAddToDelayedList( xTicksToDelay, NULL );                                                              \\r
322         }                                                                                                                                                                       \\r
323         crSET_STATE0( xHandle );\r
324 \r
325 /**\r
326  * <pre>\r
327  crQUEUE_SEND(\r
328                   xCoRoutineHandle xHandle,\r
329                   xQueueHandle pxQueue,\r
330                   void *pvItemToQueue,\r
331                   portTickType xTicksToWait,\r
332                   portBASE_TYPE *pxResult\r
333              )</pre>\r
334  *\r
335  * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine\r
336  * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.\r
337  *\r
338  * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas\r
339  * xQueueSend() and xQueueReceive() can only be used from tasks.\r
340  *\r
341  * crQUEUE_SEND can only be called from the co-routine function itself - not\r
342  * from within a function called by the co-routine function.  This is because\r
343  * co-routines do not maintain their own stack.\r
344  *\r
345  * See the co-routine section of the WEB documentation for information on\r
346  * passing data between tasks and co-routines and between ISR's and\r
347  * co-routines.\r
348  *\r
349  * @param xHandle The handle of the calling co-routine.  This is the xHandle\r
350  * parameter of the co-routine function.\r
351  *\r
352  * @param pxQueue The handle of the queue on which the data will be posted.\r
353  * The handle is obtained as the return value when the queue is created using\r
354  * the xQueueCreate() API function.\r
355  *\r
356  * @param pvItemToQueue A pointer to the data being posted onto the queue.\r
357  * The number of bytes of each queued item is specified when the queue is\r
358  * created.  This number of bytes is copied from pvItemToQueue into the queue\r
359  * itself.\r
360  *\r
361  * @param xTickToDelay The number of ticks that the co-routine should block\r
362  * to wait for space to become available on the queue, should space not be\r
363  * available immediately. The actual amount of time this equates to is defined\r
364  * by configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant\r
365  * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example\r
366  * below).\r
367  *\r
368  * @param pxResult The variable pointed to by pxResult will be set to pdPASS if\r
369  * data was successfully posted onto the queue, otherwise it will be set to an\r
370  * error defined within ProjDefs.h.\r
371  *\r
372  * Example usage:\r
373    <pre>\r
374  // Co-routine function that blocks for a fixed period then posts a number onto\r
375  // a queue.\r
376  static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
377  {\r
378  // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
379  static portBASE_TYPE xNumberToPost = 0;\r
380  static portBASE_TYPE xResult;\r
381 \r
382     // Co-routines must begin with a call to crSTART().\r
383     crSTART( xHandle );\r
384 \r
385     for( ;; )\r
386     {\r
387         // This assumes the queue has already been created.\r
388         crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );\r
389 \r
390         if( xResult != pdPASS )\r
391         {\r
392             // The message was not posted!\r
393         }\r
394 \r
395         // Increment the number to be posted onto the queue.\r
396         xNumberToPost++;\r
397 \r
398         // Delay for 100 ticks.\r
399         crDELAY( xHandle, 100 );\r
400     }\r
401 \r
402     // Co-routines must end with a call to crEND().\r
403     crEND();\r
404  }</pre>\r
405  * \defgroup crQUEUE_SEND crQUEUE_SEND\r
406  * \ingroup Tasks\r
407  */\r
408 #define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult )                 \\r
409 {                                                                                                                                                                               \\r
410         *pxResult = xQueueCRSend( pxQueue, pvItemToQueue, xTicksToWait );                                       \\r
411         if( *pxResult == errQUEUE_BLOCKED )                                                                                                     \\r
412         {                                                                                                                                                                       \\r
413                 crSET_STATE0( xHandle );                                                                                                                \\r
414                 *pxResult = xQueueCRSend( pxQueue, pvItemToQueue, 0 );                                                  \\r
415         }                                                                                                                                                                       \\r
416         if( *pxResult == errQUEUE_YIELD )                                                                                                       \\r
417         {                                                                                                                                                                       \\r
418                 crSET_STATE1( xHandle );                                                                                                                \\r
419                 *pxResult = pdPASS;                                                                                                                             \\r
420         }                                                                                                                                                                       \\r
421 }\r
422 \r
423 /**\r
424  * croutine. h\r
425  * <pre>\r
426   crQUEUE_RECEIVE(\r
427                      xCoRoutineHandle xHandle,\r
428                      xQueueHandle pxQueue,\r
429                      void *pvBuffer,\r
430                      portTickType xTicksToWait,\r
431                      portBASE_TYPE *pxResult\r
432                  )</pre>\r
433  *\r
434  * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine\r
435  * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.\r
436  *\r
437  * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas\r
438  * xQueueSend() and xQueueReceive() can only be used from tasks.\r
439  *\r
440  * crQUEUE_RECEIVE can only be called from the co-routine function itself - not\r
441  * from within a function called by the co-routine function.  This is because\r
442  * co-routines do not maintain their own stack.\r
443  *\r
444  * See the co-routine section of the WEB documentation for information on\r
445  * passing data between tasks and co-routines and between ISR's and\r
446  * co-routines.\r
447  *\r
448  * @param xHandle The handle of the calling co-routine.  This is the xHandle\r
449  * parameter of the co-routine function.\r
450  *\r
451  * @param pxQueue The handle of the queue from which the data will be received.\r
452  * The handle is obtained as the return value when the queue is created using\r
453  * the xQueueCreate() API function.\r
454  *\r
455  * @param pvBuffer The buffer into which the received item is to be copied.\r
456  * The number of bytes of each queued item is specified when the queue is\r
457  * created.  This number of bytes is copied into pvBuffer.\r
458  *\r
459  * @param xTickToDelay The number of ticks that the co-routine should block\r
460  * to wait for data to become available from the queue, should data not be\r
461  * available immediately. The actual amount of time this equates to is defined\r
462  * by configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant\r
463  * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the\r
464  * crQUEUE_SEND example).\r
465  *\r
466  * @param pxResult The variable pointed to by pxResult will be set to pdPASS if\r
467  * data was successfully retrieved from the queue, otherwise it will be set to\r
468  * an error code as defined within ProjDefs.h.\r
469  *\r
470  * Example usage:\r
471  <pre>\r
472  // A co-routine receives the number of an LED to flash from a queue.  It\r
473  // blocks on the queue until the number is received.\r
474  static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
475  {\r
476  // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
477  static portBASE_TYPE xResult;\r
478  static unsigned portBASE_TYPE uxLEDToFlash;\r
479 \r
480     // All co-routines must start with a call to crSTART().\r
481     crSTART( xHandle );\r
482 \r
483     for( ;; )\r
484     {\r
485         // Wait for data to become available on the queue.\r
486         crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );\r
487 \r
488         if( xResult == pdPASS )\r
489         {\r
490             // We received the LED to flash - flash it!\r
491             vParTestToggleLED( uxLEDToFlash );\r
492         }\r
493     }\r
494 \r
495     crEND();\r
496  }</pre>\r
497  * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE\r
498  * \ingroup Tasks\r
499  */\r
500 #define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult )                   \\r
501 {                                                                                                                                                                               \\r
502         *pxResult = xQueueCRReceive( pxQueue, pvBuffer, xTicksToWait );                                         \\r
503         if( *pxResult == errQUEUE_BLOCKED )                                                                                             \\r
504         {                                                                                                                                                                       \\r
505                 crSET_STATE0( xHandle );                                                                                                                \\r
506                 *pxResult = xQueueCRReceive( pxQueue, pvBuffer, 0 );                                                    \\r
507         }                                                                                                                                                                       \\r
508         if( *pxResult == errQUEUE_YIELD )                                                                                                       \\r
509         {                                                                                                                                                                       \\r
510                 crSET_STATE1( xHandle );                                                                                                                \\r
511                 *pxResult = pdPASS;                                                                                                                             \\r
512         }                                                                                                                                                                       \\r
513 }\r
514 \r
515 /**\r
516  * croutine. h\r
517  * <pre>\r
518   crQUEUE_SEND_FROM_ISR(\r
519                             xQueueHandle pxQueue,\r
520                             void *pvItemToQueue,\r
521                             portBASE_TYPE xCoRoutinePreviouslyWoken\r
522                        )</pre>\r
523  *\r
524  * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the\r
525  * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()\r
526  * functions used by tasks.\r
527  *\r
528  * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to\r
529  * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and\r
530  * xQueueReceiveFromISR() can only be used to pass data between a task and and\r
531  * ISR.\r
532  *\r
533  * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue\r
534  * that is being used from within a co-routine.\r
535  *\r
536  * See the co-routine section of the WEB documentation for information on\r
537  * passing data between tasks and co-routines and between ISR's and\r
538  * co-routines.\r
539  *\r
540  * @param xQueue The handle to the queue on which the item is to be posted.\r
541  *\r
542  * @param pvItemToQueue A pointer to the item that is to be placed on the\r
543  * queue.  The size of the items the queue will hold was defined when the\r
544  * queue was created, so this many bytes will be copied from pvItemToQueue\r
545  * into the queue storage area.\r
546  *\r
547  * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto\r
548  * the same queue multiple times from a single interrupt.  The first call\r
549  * should always pass in pdFALSE.  Subsequent calls should pass in\r
550  * the value returned from the previous call.\r
551  *\r
552  * @return pdTRUE if a co-routine was woken by posting onto the queue.  This is\r
553  * used by the ISR to determine if a context switch may be required following\r
554  * the ISR.\r
555  *\r
556  * Example usage:\r
557  <pre>\r
558  // A co-routine that blocks on a queue waiting for characters to be received.\r
559  static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
560  {\r
561  portCHAR cRxedChar;\r
562  portBASE_TYPE xResult;\r
563 \r
564      // All co-routines must start with a call to crSTART().\r
565      crSTART( xHandle );\r
566 \r
567      for( ;; )\r
568      {\r
569          // Wait for data to become available on the queue.  This assumes the\r
570          // queue xCommsRxQueue has already been created!\r
571          crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );\r
572 \r
573          // Was a character received?\r
574          if( xResult == pdPASS )\r
575          {\r
576              // Process the character here.\r
577          }\r
578      }\r
579 \r
580      // All co-routines must end with a call to crEND().\r
581      crEND();\r
582  }\r
583 \r
584  // An ISR that uses a queue to send characters received on a serial port to\r
585  // a co-routine.\r
586  void vUART_ISR( void )\r
587  {\r
588  portCHAR cRxedChar;\r
589  portBASE_TYPE xCRWokenByPost = pdFALSE;\r
590 \r
591      // We loop around reading characters until there are none left in the UART.\r
592      while( UART_RX_REG_NOT_EMPTY() )\r
593      {\r
594          // Obtain the character from the UART.\r
595          cRxedChar = UART_RX_REG;\r
596 \r
597          // Post the character onto a queue.  xCRWokenByPost will be pdFALSE\r
598          // the first time around the loop.  If the post causes a co-routine\r
599          // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.\r
600          // In this manner we can ensure that if more than one co-routine is\r
601          // blocked on the queue only one is woken by this ISR no matter how\r
602          // many characters are posted to the queue.\r
603          xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );\r
604      }\r
605  }</pre>\r
606  * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR\r
607  * \ingroup Tasks\r
608  */\r
609 #define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken )\r
610 \r
611 \r
612 /**\r
613  * croutine. h\r
614  * <pre>\r
615   crQUEUE_SEND_FROM_ISR(\r
616                             xQueueHandle pxQueue,\r
617                             void *pvBuffer,\r
618                             portBASE_TYPE * pxCoRoutineWoken\r
619                        )</pre>\r
620  *\r
621  * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the\r
622  * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()\r
623  * functions used by tasks.\r
624  *\r
625  * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to\r
626  * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and\r
627  * xQueueReceiveFromISR() can only be used to pass data between a task and and\r
628  * ISR.\r
629  *\r
630  * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data\r
631  * from a queue that is being used from within a co-routine (a co-routine\r
632  * posted to the queue).\r
633  *\r
634  * See the co-routine section of the WEB documentation for information on\r
635  * passing data between tasks and co-routines and between ISR's and\r
636  * co-routines.\r
637  *\r
638  * @param xQueue The handle to the queue on which the item is to be posted.\r
639  *\r
640  * @param pvBuffer A pointer to a buffer into which the received item will be\r
641  * placed.  The size of the items the queue will hold was defined when the\r
642  * queue was created, so this many bytes will be copied from the queue into\r
643  * pvBuffer.\r
644  *\r
645  * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become\r
646  * available on the queue.  If crQUEUE_RECEIVE_FROM_ISR causes such a\r
647  * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise\r
648  * *pxCoRoutineWoken will remain unchanged.\r
649  *\r
650  * @return pdTRUE an item was successfully received from the queue, otherwise\r
651  * pdFALSE.\r
652  *\r
653  * Example usage:\r
654  <pre>\r
655  // A co-routine that posts a character to a queue then blocks for a fixed\r
656  // period.  The character is incremented each time.\r
657  static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
658  {\r
659  // cChar holds its value while this co-routine is blocked and must therefore\r
660  // be declared static.\r
661  static portCHAR cCharToTx = 'a';\r
662  portBASE_TYPE xResult;\r
663 \r
664      // All co-routines must start with a call to crSTART().\r
665      crSTART( xHandle );\r
666 \r
667      for( ;; )\r
668      {\r
669          // Send the next character to the queue.\r
670          crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );\r
671 \r
672          if( xResult == pdPASS )\r
673          {\r
674              // The character was successfully posted to the queue.\r
675          }\r
676                  else\r
677                  {\r
678                         // Could not post the character to the queue.\r
679                  }\r
680 \r
681          // Enable the UART Tx interrupt to cause an interrupt in this\r
682                  // hypothetical UART.  The interrupt will obtain the character\r
683                  // from the queue and send it.\r
684                  ENABLE_RX_INTERRUPT();\r
685 \r
686                  // Increment to the next character then block for a fixed period.\r
687                  // cCharToTx will maintain its value across the delay as it is\r
688                  // declared static.\r
689                  cCharToTx++;\r
690                  if( cCharToTx > 'x' )\r
691                  {\r
692                         cCharToTx = 'a';\r
693                  }\r
694                  crDELAY( 100 );\r
695      }\r
696 \r
697      // All co-routines must end with a call to crEND().\r
698      crEND();\r
699  }\r
700 \r
701  // An ISR that uses a queue to receive characters to send on a UART.\r
702  void vUART_ISR( void )\r
703  {\r
704  portCHAR cCharToTx;\r
705  portBASE_TYPE xCRWokenByPost = pdFALSE;\r
706 \r
707      while( UART_TX_REG_EMPTY() )\r
708      {\r
709          // Are there any characters in the queue waiting to be sent?\r
710                  // xCRWokenByPost will automatically be set to pdTRUE if a co-routine\r
711                  // is woken by the post - ensuring that only a single co-routine is\r
712                  // woken no matter how many times we go around this loop.\r
713          if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )\r
714                  {\r
715                          SEND_CHARACTER( cCharToTx );\r
716                  }\r
717      }\r
718  }</pre>\r
719  * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR\r
720  * \ingroup Tasks\r
721  */\r
722 #define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( pxQueue, pvBuffer, pxCoRoutineWoken )\r
723 \r
724 /*\r
725  * This function is intended for internal use by the co-routine macros only.\r
726  * The macro nature of the co-routine implementation requires that the\r
727  * prototype appears here.  The function should not be used by application\r
728  * writers.\r
729  *\r
730  * Removes the current co-routine from its ready list and places it in the\r
731  * appropriate delayed list.\r
732  */\r
733 void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList );\r
734 \r
735 /*\r
736  * This function is intended for internal use by the queue implementation only.\r
737  * The function should not be used by application writers.\r
738  *\r
739  * Removes the highest priority co-routine from the event list and places it in\r
740  * the pending ready list.\r
741  */\r
742 signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList );\r
743 \r
744 #ifdef __cplusplus\r
745 }\r
746 #endif\r
747 \r
748 #endif /* CO_ROUTINE_H */\r