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