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