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