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