root/Examples_CP-JR_ARM7_LPC2368/FreeRTOS_Book/Source-Code-For-Examples/FreeRTOS_Source/include/croutine.h

Revision 36, 27.1 kB (checked in by phil, 15 years ago)

added purchased FreeRTOS book

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