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