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