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