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