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