]> begriffs open source - freertos/blob - include/croutine.h
[AUTO][RELEASE]: Bump file header version to "10.4.4"
[freertos] / include / croutine.h
1 /*\r
2  * FreeRTOS Kernel V10.4.4\r
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
8  * this software and associated documentation files (the "Software"), to deal in\r
9  * the Software without restriction, including without limitation the rights to\r
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
11  * the Software, and to permit persons to whom the Software is furnished to do so,\r
12  * subject to the following conditions:\r
13  *\r
14  * The above copyright notice and this permission notice shall be included in all\r
15  * copies or substantial portions of the Software.\r
16  *\r
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
23  *\r
24  * https://www.FreeRTOS.org\r
25  * https://github.com/FreeRTOS\r
26  *\r
27  */\r
28 \r
29 #ifndef CO_ROUTINE_H\r
30 #define CO_ROUTINE_H\r
31 \r
32 #ifndef INC_FREERTOS_H\r
33     #error "include FreeRTOS.h must appear in source files before include croutine.h"\r
34 #endif\r
35 \r
36 #include "list.h"\r
37 \r
38 /* *INDENT-OFF* */\r
39 #ifdef __cplusplus\r
40     extern "C" {\r
41 #endif\r
42 /* *INDENT-ON* */\r
43 \r
44 /* Used to hide the implementation of the co-routine control block.  The\r
45  * control block structure however has to be included in the header due to\r
46  * the macro implementation of the co-routine functionality. */\r
47 typedef void * CoRoutineHandle_t;\r
48 \r
49 /* Defines the prototype to which co-routine functions must conform. */\r
50 typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t,\r
51                                    UBaseType_t );\r
52 \r
53 typedef struct corCoRoutineControlBlock\r
54 {\r
55     crCOROUTINE_CODE pxCoRoutineFunction;\r
56     ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */\r
57     ListItem_t xEventListItem;   /*< List item used to place the CRCB in event lists. */\r
58     UBaseType_t uxPriority;      /*< The priority of the co-routine in relation to other co-routines. */\r
59     UBaseType_t uxIndex;         /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */\r
60     uint16_t uxState;            /*< Used internally by the co-routine implementation. */\r
61 } CRCB_t;                        /* Co-routine control block.  Note must be identical in size down to uxPriority with TCB_t. */\r
62 \r
63 /**\r
64  * croutine. h\r
65  * <pre>\r
66  * BaseType_t xCoRoutineCreate(\r
67  *                               crCOROUTINE_CODE pxCoRoutineCode,\r
68  *                               UBaseType_t uxPriority,\r
69  *                               UBaseType_t uxIndex\r
70  *                             );\r
71  * </pre>\r
72  *\r
73  * Create a new co-routine and add it to the list of co-routines that are\r
74  * ready to run.\r
75  *\r
76  * @param pxCoRoutineCode Pointer to the co-routine function.  Co-routine\r
77  * functions require special syntax - see the co-routine section of the WEB\r
78  * documentation for more information.\r
79  *\r
80  * @param uxPriority The priority with respect to other co-routines at which\r
81  *  the co-routine will run.\r
82  *\r
83  * @param uxIndex Used to distinguish between different co-routines that\r
84  * execute the same function.  See the example below and the co-routine section\r
85  * of the WEB documentation for further information.\r
86  *\r
87  * @return pdPASS if the co-routine was successfully created and added to a ready\r
88  * list, otherwise an error code defined with ProjDefs.h.\r
89  *\r
90  * Example usage:\r
91  * <pre>\r
92  * // Co-routine to be created.\r
93  * void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
94  * {\r
95  * // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
96  * // This may not be necessary for const variables.\r
97  * static const char cLedToFlash[ 2 ] = { 5, 6 };\r
98  * static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };\r
99  *\r
100  *   // Must start every co-routine with a call to crSTART();\r
101  *   crSTART( xHandle );\r
102  *\r
103  *   for( ;; )\r
104  *   {\r
105  *       // This co-routine just delays for a fixed period, then toggles\r
106  *       // an LED.  Two co-routines are created using this function, so\r
107  *       // the uxIndex parameter is used to tell the co-routine which\r
108  *       // LED to flash and how int32_t to delay.  This assumes xQueue has\r
109  *       // already been created.\r
110  *       vParTestToggleLED( cLedToFlash[ uxIndex ] );\r
111  *       crDELAY( xHandle, uxFlashRates[ uxIndex ] );\r
112  *   }\r
113  *\r
114  *   // Must end every co-routine with a call to crEND();\r
115  *   crEND();\r
116  * }\r
117  *\r
118  * // Function that creates two co-routines.\r
119  * void vOtherFunction( void )\r
120  * {\r
121  * uint8_t ucParameterToPass;\r
122  * TaskHandle_t xHandle;\r
123  *\r
124  *   // Create two co-routines at priority 0.  The first is given index 0\r
125  *   // so (from the code above) toggles LED 5 every 200 ticks.  The second\r
126  *   // is given index 1 so toggles LED 6 every 400 ticks.\r
127  *   for( uxIndex = 0; uxIndex < 2; uxIndex++ )\r
128  *   {\r
129  *       xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );\r
130  *   }\r
131  * }\r
132  * </pre>\r
133  * \defgroup xCoRoutineCreate xCoRoutineCreate\r
134  * \ingroup Tasks\r
135  */\r
136 BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,\r
137                              UBaseType_t uxPriority,\r
138                              UBaseType_t uxIndex );\r
139 \r
140 \r
141 /**\r
142  * croutine. h\r
143  * <pre>\r
144  * void vCoRoutineSchedule( void );\r
145  * </pre>\r
146  *\r
147  * Run a co-routine.\r
148  *\r
149  * vCoRoutineSchedule() executes the highest priority co-routine that is able\r
150  * to run.  The co-routine will execute until it either blocks, yields or is\r
151  * preempted by a task.  Co-routines execute cooperatively so one\r
152  * co-routine cannot be preempted by another, but can be preempted by a task.\r
153  *\r
154  * If an application comprises of both tasks and co-routines then\r
155  * vCoRoutineSchedule should be called from the idle task (in an idle task\r
156  * hook).\r
157  *\r
158  * Example usage:\r
159  * <pre>\r
160  * // This idle task hook will schedule a co-routine each time it is called.\r
161  * // The rest of the idle task will execute between co-routine calls.\r
162  * void vApplicationIdleHook( void )\r
163  * {\r
164  *  vCoRoutineSchedule();\r
165  * }\r
166  *\r
167  * // Alternatively, if you do not require any other part of the idle task to\r
168  * // execute, the idle task hook can call vCoRoutineSchedule() within an\r
169  * // infinite loop.\r
170  * void vApplicationIdleHook( void )\r
171  * {\r
172  *  for( ;; )\r
173  *  {\r
174  *      vCoRoutineSchedule();\r
175  *  }\r
176  * }\r
177  * </pre>\r
178  * \defgroup vCoRoutineSchedule vCoRoutineSchedule\r
179  * \ingroup Tasks\r
180  */\r
181 void vCoRoutineSchedule( void );\r
182 \r
183 /**\r
184  * croutine. h\r
185  * <pre>\r
186  * crSTART( CoRoutineHandle_t xHandle );\r
187  * </pre>\r
188  *\r
189  * This macro MUST always be called at the start of a co-routine function.\r
190  *\r
191  * Example usage:\r
192  * <pre>\r
193  * // Co-routine to be created.\r
194  * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
195  * {\r
196  * // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
197  * static int32_t ulAVariable;\r
198  *\r
199  *   // Must start every co-routine with a call to crSTART();\r
200  *   crSTART( xHandle );\r
201  *\r
202  *   for( ;; )\r
203  *   {\r
204  *        // Co-routine functionality goes here.\r
205  *   }\r
206  *\r
207  *   // Must end every co-routine with a call to crEND();\r
208  *   crEND();\r
209  * }\r
210  * </pre>\r
211  * \defgroup crSTART crSTART\r
212  * \ingroup Tasks\r
213  */\r
214 #define crSTART( pxCRCB )                            \\r
215     switch( ( ( CRCB_t * ) ( pxCRCB ) )->uxState ) { \\r
216         case 0:\r
217 \r
218 /**\r
219  * croutine. h\r
220  * <pre>\r
221  * crEND();\r
222  * </pre>\r
223  *\r
224  * This macro MUST always be called at the end of a co-routine function.\r
225  *\r
226  * Example usage:\r
227  * <pre>\r
228  * // Co-routine to be created.\r
229  * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
230  * {\r
231  * // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
232  * static int32_t ulAVariable;\r
233  *\r
234  *   // Must start every co-routine with a call to crSTART();\r
235  *   crSTART( xHandle );\r
236  *\r
237  *   for( ;; )\r
238  *   {\r
239  *        // Co-routine functionality goes here.\r
240  *   }\r
241  *\r
242  *   // Must end every co-routine with a call to crEND();\r
243  *   crEND();\r
244  * }\r
245  * </pre>\r
246  * \defgroup crSTART crSTART\r
247  * \ingroup Tasks\r
248  */\r
249 #define crEND()    }\r
250 \r
251 /*\r
252  * These macros are intended for internal use by the co-routine implementation\r
253  * only.  The macros should not be used directly by application writers.\r
254  */\r
255 #define crSET_STATE0( xHandle )                                       \\r
256     ( ( CRCB_t * ) ( xHandle ) )->uxState = ( __LINE__ * 2 ); return; \\r
257     case ( __LINE__ * 2 ):\r
258 #define crSET_STATE1( xHandle )                                               \\r
259     ( ( CRCB_t * ) ( xHandle ) )->uxState = ( ( __LINE__ * 2 ) + 1 ); return; \\r
260     case ( ( __LINE__ * 2 ) + 1 ):\r
261 \r
262 /**\r
263  * croutine. h\r
264  * <pre>\r
265  * crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );\r
266  * </pre>\r
267  *\r
268  * Delay a co-routine for a fixed period of time.\r
269  *\r
270  * crDELAY can only be called from the co-routine function itself - not\r
271  * from within a function called by the co-routine function.  This is because\r
272  * co-routines do not maintain their own stack.\r
273  *\r
274  * @param xHandle The handle of the co-routine to delay.  This is the xHandle\r
275  * parameter of the co-routine function.\r
276  *\r
277  * @param xTickToDelay The number of ticks that the co-routine should delay\r
278  * for.  The actual amount of time this equates to is defined by\r
279  * configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant portTICK_PERIOD_MS\r
280  * can be used to convert ticks to milliseconds.\r
281  *\r
282  * Example usage:\r
283  * <pre>\r
284  * // Co-routine to be created.\r
285  * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
286  * {\r
287  * // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
288  * // This may not be necessary for const variables.\r
289  * // We are to delay for 200ms.\r
290  * static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;\r
291  *\r
292  *   // Must start every co-routine with a call to crSTART();\r
293  *   crSTART( xHandle );\r
294  *\r
295  *   for( ;; )\r
296  *   {\r
297  *      // Delay for 200ms.\r
298  *      crDELAY( xHandle, xDelayTime );\r
299  *\r
300  *      // Do something here.\r
301  *   }\r
302  *\r
303  *   // Must end every co-routine with a call to crEND();\r
304  *   crEND();\r
305  * }\r
306  * </pre>\r
307  * \defgroup crDELAY crDELAY\r
308  * \ingroup Tasks\r
309  */\r
310 #define crDELAY( xHandle, xTicksToDelay )                      \\r
311     if( ( xTicksToDelay ) > 0 )                                \\r
312     {                                                          \\r
313         vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \\r
314     }                                                          \\r
315     crSET_STATE0( ( xHandle ) );\r
316 \r
317 /**\r
318  * <pre>\r
319  * crQUEUE_SEND(\r
320  *                CoRoutineHandle_t xHandle,\r
321  *                QueueHandle_t pxQueue,\r
322  *                void *pvItemToQueue,\r
323  *                TickType_t xTicksToWait,\r
324  *                BaseType_t *pxResult\r
325  *           )\r
326  * </pre>\r
327  *\r
328  * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine\r
329  * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.\r
330  *\r
331  * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas\r
332  * xQueueSend() and xQueueReceive() can only be used from tasks.\r
333  *\r
334  * crQUEUE_SEND can only be called from the co-routine function itself - not\r
335  * from within a function called by the co-routine function.  This is because\r
336  * co-routines do not maintain their own stack.\r
337  *\r
338  * See the co-routine section of the WEB documentation for information on\r
339  * passing data between tasks and co-routines and between ISR's and\r
340  * co-routines.\r
341  *\r
342  * @param xHandle The handle of the calling co-routine.  This is the xHandle\r
343  * parameter of the co-routine function.\r
344  *\r
345  * @param pxQueue The handle of the queue on which the data will be posted.\r
346  * The handle is obtained as the return value when the queue is created using\r
347  * the xQueueCreate() API function.\r
348  *\r
349  * @param pvItemToQueue A pointer to the data being posted onto the queue.\r
350  * The number of bytes of each queued item is specified when the queue is\r
351  * created.  This number of bytes is copied from pvItemToQueue into the queue\r
352  * itself.\r
353  *\r
354  * @param xTickToDelay The number of ticks that the co-routine should block\r
355  * to wait for space to become available on the queue, should space not be\r
356  * available immediately. The actual amount of time this equates to is defined\r
357  * by configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant\r
358  * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example\r
359  * below).\r
360  *\r
361  * @param pxResult The variable pointed to by pxResult will be set to pdPASS if\r
362  * data was successfully posted onto the queue, otherwise it will be set to an\r
363  * error defined within ProjDefs.h.\r
364  *\r
365  * Example usage:\r
366  * <pre>\r
367  * // Co-routine function that blocks for a fixed period then posts a number onto\r
368  * // a queue.\r
369  * static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
370  * {\r
371  * // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
372  * static BaseType_t xNumberToPost = 0;\r
373  * static BaseType_t xResult;\r
374  *\r
375  *  // Co-routines must begin with a call to crSTART().\r
376  *  crSTART( xHandle );\r
377  *\r
378  *  for( ;; )\r
379  *  {\r
380  *      // This assumes the queue has already been created.\r
381  *      crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );\r
382  *\r
383  *      if( xResult != pdPASS )\r
384  *      {\r
385  *          // The message was not posted!\r
386  *      }\r
387  *\r
388  *      // Increment the number to be posted onto the queue.\r
389  *      xNumberToPost++;\r
390  *\r
391  *      // Delay for 100 ticks.\r
392  *      crDELAY( xHandle, 100 );\r
393  *  }\r
394  *\r
395  *  // Co-routines must end with a call to crEND().\r
396  *  crEND();\r
397  * }\r
398  * </pre>\r
399  * \defgroup crQUEUE_SEND crQUEUE_SEND\r
400  * \ingroup Tasks\r
401  */\r
402 #define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult )           \\r
403     {                                                                                     \\r
404         *( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \\r
405         if( *( pxResult ) == errQUEUE_BLOCKED )                                           \\r
406         {                                                                                 \\r
407             crSET_STATE0( ( xHandle ) );                                                  \\r
408             *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 );                \\r
409         }                                                                                 \\r
410         if( *pxResult == errQUEUE_YIELD )                                                 \\r
411         {                                                                                 \\r
412             crSET_STATE1( ( xHandle ) );                                                  \\r
413             *pxResult = pdPASS;                                                           \\r
414         }                                                                                 \\r
415     }\r
416 \r
417 /**\r
418  * croutine. h\r
419  * <pre>\r
420  * crQUEUE_RECEIVE(\r
421  *                   CoRoutineHandle_t xHandle,\r
422  *                   QueueHandle_t pxQueue,\r
423  *                   void *pvBuffer,\r
424  *                   TickType_t xTicksToWait,\r
425  *                   BaseType_t *pxResult\r
426  *               )\r
427  * </pre>\r
428  *\r
429  * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine\r
430  * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.\r
431  *\r
432  * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas\r
433  * xQueueSend() and xQueueReceive() can only be used from tasks.\r
434  *\r
435  * crQUEUE_RECEIVE can only be called from the co-routine function itself - not\r
436  * from within a function called by the co-routine function.  This is because\r
437  * co-routines do not maintain their own stack.\r
438  *\r
439  * See the co-routine section of the WEB documentation for information on\r
440  * passing data between tasks and co-routines and between ISR's and\r
441  * co-routines.\r
442  *\r
443  * @param xHandle The handle of the calling co-routine.  This is the xHandle\r
444  * parameter of the co-routine function.\r
445  *\r
446  * @param pxQueue The handle of the queue from which the data will be received.\r
447  * The handle is obtained as the return value when the queue is created using\r
448  * the xQueueCreate() API function.\r
449  *\r
450  * @param pvBuffer The buffer into which the received item is to be copied.\r
451  * The number of bytes of each queued item is specified when the queue is\r
452  * created.  This number of bytes is copied into pvBuffer.\r
453  *\r
454  * @param xTickToDelay The number of ticks that the co-routine should block\r
455  * to wait for data to become available from the queue, should data not be\r
456  * available immediately. The actual amount of time this equates to is defined\r
457  * by configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant\r
458  * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the\r
459  * crQUEUE_SEND example).\r
460  *\r
461  * @param pxResult The variable pointed to by pxResult will be set to pdPASS if\r
462  * data was successfully retrieved from the queue, otherwise it will be set to\r
463  * an error code as defined within ProjDefs.h.\r
464  *\r
465  * Example usage:\r
466  * <pre>\r
467  * // A co-routine receives the number of an LED to flash from a queue.  It\r
468  * // blocks on the queue until the number is received.\r
469  * static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
470  * {\r
471  * // Variables in co-routines must be declared static if they must maintain value across a blocking call.\r
472  * static BaseType_t xResult;\r
473  * static UBaseType_t uxLEDToFlash;\r
474  *\r
475  *  // All co-routines must start with a call to crSTART().\r
476  *  crSTART( xHandle );\r
477  *\r
478  *  for( ;; )\r
479  *  {\r
480  *      // Wait for data to become available on the queue.\r
481  *      crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );\r
482  *\r
483  *      if( xResult == pdPASS )\r
484  *      {\r
485  *          // We received the LED to flash - flash it!\r
486  *          vParTestToggleLED( uxLEDToFlash );\r
487  *      }\r
488  *  }\r
489  *\r
490  *  crEND();\r
491  * }\r
492  * </pre>\r
493  * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE\r
494  * \ingroup Tasks\r
495  */\r
496 #define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult )           \\r
497     {                                                                                   \\r
498         *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \\r
499         if( *( pxResult ) == errQUEUE_BLOCKED )                                         \\r
500         {                                                                               \\r
501             crSET_STATE0( ( xHandle ) );                                                \\r
502             *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), 0 );            \\r
503         }                                                                               \\r
504         if( *( pxResult ) == errQUEUE_YIELD )                                           \\r
505         {                                                                               \\r
506             crSET_STATE1( ( xHandle ) );                                                \\r
507             *( pxResult ) = pdPASS;                                                     \\r
508         }                                                                               \\r
509     }\r
510 \r
511 /**\r
512  * croutine. h\r
513  * <pre>\r
514  * crQUEUE_SEND_FROM_ISR(\r
515  *                          QueueHandle_t pxQueue,\r
516  *                          void *pvItemToQueue,\r
517  *                          BaseType_t xCoRoutinePreviouslyWoken\r
518  *                     )\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( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
557  * {\r
558  * char cRxedChar;\r
559  * BaseType_t 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  * char cRxedChar;\r
586  * BaseType_t 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  * }\r
603  * </pre>\r
604  * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR\r
605  * \ingroup Tasks\r
606  */\r
607 #define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) \\r
608     xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )\r
609 \r
610 \r
611 /**\r
612  * croutine. h\r
613  * <pre>\r
614  * crQUEUE_SEND_FROM_ISR(\r
615  *                          QueueHandle_t pxQueue,\r
616  *                          void *pvBuffer,\r
617  *                          BaseType_t * pxCoRoutineWoken\r
618  *                     )\r
619  * </pre>\r
620  *\r
621  * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the\r
622  * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()\r
623  * functions used by tasks.\r
624  *\r
625  * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to\r
626  * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and\r
627  * xQueueReceiveFromISR() can only be used to pass data between a task and and\r
628  * ISR.\r
629  *\r
630  * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data\r
631  * from a queue that is being used from within a co-routine (a co-routine\r
632  * posted to the queue).\r
633  *\r
634  * See the co-routine section of the WEB documentation for information on\r
635  * passing data between tasks and co-routines and between ISR's and\r
636  * co-routines.\r
637  *\r
638  * @param xQueue The handle to the queue on which the item is to be posted.\r
639  *\r
640  * @param pvBuffer A pointer to a buffer into which the received item will be\r
641  * placed.  The size of the items the queue will hold was defined when the\r
642  * queue was created, so this many bytes will be copied from the queue into\r
643  * pvBuffer.\r
644  *\r
645  * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become\r
646  * available on the queue.  If crQUEUE_RECEIVE_FROM_ISR causes such a\r
647  * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise\r
648  * *pxCoRoutineWoken will remain unchanged.\r
649  *\r
650  * @return pdTRUE an item was successfully received from the queue, otherwise\r
651  * pdFALSE.\r
652  *\r
653  * Example usage:\r
654  * <pre>\r
655  * // A co-routine that posts a character to a queue then blocks for a fixed\r
656  * // period.  The character is incremented each time.\r
657  * static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
658  * {\r
659  * // cChar holds its value while this co-routine is blocked and must therefore\r
660  * // be declared static.\r
661  * static char cCharToTx = 'a';\r
662  * BaseType_t xResult;\r
663  *\r
664  *   // All co-routines must start with a call to crSTART().\r
665  *   crSTART( xHandle );\r
666  *\r
667  *   for( ;; )\r
668  *   {\r
669  *       // Send the next character to the queue.\r
670  *       crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );\r
671  *\r
672  *       if( xResult == pdPASS )\r
673  *       {\r
674  *           // The character was successfully posted to the queue.\r
675  *       }\r
676  *       else\r
677  *       {\r
678  *          // Could not post the character to the queue.\r
679  *       }\r
680  *\r
681  *       // Enable the UART Tx interrupt to cause an interrupt in this\r
682  *       // hypothetical UART.  The interrupt will obtain the character\r
683  *       // from the queue and send it.\r
684  *       ENABLE_RX_INTERRUPT();\r
685  *\r
686  *       // Increment to the next character then block for a fixed period.\r
687  *       // cCharToTx will maintain its value across the delay as it is\r
688  *       // declared static.\r
689  *       cCharToTx++;\r
690  *       if( cCharToTx > 'x' )\r
691  *       {\r
692  *          cCharToTx = 'a';\r
693  *       }\r
694  *       crDELAY( 100 );\r
695  *   }\r
696  *\r
697  *   // All co-routines must end with a call to crEND().\r
698  *   crEND();\r
699  * }\r
700  *\r
701  * // An ISR that uses a queue to receive characters to send on a UART.\r
702  * void vUART_ISR( void )\r
703  * {\r
704  * char cCharToTx;\r
705  * BaseType_t xCRWokenByPost = pdFALSE;\r
706  *\r
707  *   while( UART_TX_REG_EMPTY() )\r
708  *   {\r
709  *       // Are there any characters in the queue waiting to be sent?\r
710  *       // xCRWokenByPost will automatically be set to pdTRUE if a co-routine\r
711  *       // is woken by the post - ensuring that only a single co-routine is\r
712  *       // woken no matter how many times we go around this loop.\r
713  *       if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )\r
714  *       {\r
715  *           SEND_CHARACTER( cCharToTx );\r
716  *       }\r
717  *   }\r
718  * }\r
719  * </pre>\r
720  * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR\r
721  * \ingroup Tasks\r
722  */\r
723 #define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) \\r
724     xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )\r
725 \r
726 /*\r
727  * This function is intended for internal use by the co-routine macros only.\r
728  * The macro nature of the co-routine implementation requires that the\r
729  * prototype appears here.  The function should not be used by application\r
730  * writers.\r
731  *\r
732  * Removes the current co-routine from its ready list and places it in the\r
733  * appropriate delayed list.\r
734  */\r
735 void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,\r
736                                  List_t * pxEventList );\r
737 \r
738 /*\r
739  * This function is intended for internal use by the queue implementation only.\r
740  * The function should not be used by application writers.\r
741  *\r
742  * Removes the highest priority co-routine from the event list and places it in\r
743  * the pending ready list.\r
744  */\r
745 BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList );\r
746 \r
747 /* *INDENT-OFF* */\r
748 #ifdef __cplusplus\r
749     }\r
750 #endif\r
751 /* *INDENT-ON* */\r
752 \r
753 #endif /* CO_ROUTINE_H */\r