1 /* 2 * FreeRTOS Kernel V11.1.0 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 /* Standard includes. */ 30 #include <stdlib.h> 31 32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining 33 * all the API functions to use the MPU wrappers. That should only be done when 34 * task.h is included from an application file. */ 35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE 36 37 /* FreeRTOS includes. */ 38 #include "FreeRTOS.h" 39 #include "task.h" 40 #include "timers.h" 41 #include "event_groups.h" 42 43 /* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined 44 * for the header files above, but not in this file, in order to generate the 45 * correct privileged Vs unprivileged linkage and placement. */ 46 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE 47 48 /* This entire source file will be skipped if the application is not configured 49 * to include event groups functionality. This #if is closed at the very bottom 50 * of this file. If you want to include event groups then ensure 51 * configUSE_EVENT_GROUPS is set to 1 in FreeRTOSConfig.h. */ 52 #if ( configUSE_EVENT_GROUPS == 1 ) 53 54 typedef struct EventGroupDef_t 55 { 56 EventBits_t uxEventBits; 57 List_t xTasksWaitingForBits; /**< List of tasks waiting for a bit to be set. */ 58 59 #if ( configUSE_TRACE_FACILITY == 1 ) 60 UBaseType_t uxEventGroupNumber; 61 #endif 62 63 #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) 64 uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ 65 #endif 66 } EventGroup_t; 67 68 /*-----------------------------------------------------------*/ 69 70 /* 71 * Test the bits set in uxCurrentEventBits to see if the wait condition is met. 72 * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is 73 * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor 74 * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the 75 * wait condition is met if any of the bits set in uxBitsToWait for are also set 76 * in uxCurrentEventBits. 77 */ 78 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, 79 const EventBits_t uxBitsToWaitFor, 80 const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; 81 82 /*-----------------------------------------------------------*/ 83 84 #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 85 xEventGroupCreateStatic(StaticEventGroup_t * pxEventGroupBuffer)86 EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) 87 { 88 EventGroup_t * pxEventBits; 89 90 traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer ); 91 92 /* A StaticEventGroup_t object must be provided. */ 93 configASSERT( pxEventGroupBuffer ); 94 95 #if ( configASSERT_DEFINED == 1 ) 96 { 97 /* Sanity check that the size of the structure used to declare a 98 * variable of type StaticEventGroup_t equals the size of the real 99 * event group structure. */ 100 volatile size_t xSize = sizeof( StaticEventGroup_t ); 101 configASSERT( xSize == sizeof( EventGroup_t ) ); 102 } 103 #endif /* configASSERT_DEFINED */ 104 105 /* The user has provided a statically allocated event group - use it. */ 106 /* MISRA Ref 11.3.1 [Misaligned access] */ 107 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ 108 /* coverity[misra_c_2012_rule_11_3_violation] */ 109 pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; 110 111 if( pxEventBits != NULL ) 112 { 113 pxEventBits->uxEventBits = 0; 114 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); 115 116 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) 117 { 118 /* Both static and dynamic allocation can be used, so note that 119 * this event group was created statically in case the event group 120 * is later deleted. */ 121 pxEventBits->ucStaticallyAllocated = pdTRUE; 122 } 123 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ 124 125 traceEVENT_GROUP_CREATE( pxEventBits ); 126 } 127 else 128 { 129 /* xEventGroupCreateStatic should only ever be called with 130 * pxEventGroupBuffer pointing to a pre-allocated (compile time 131 * allocated) StaticEventGroup_t variable. */ 132 traceEVENT_GROUP_CREATE_FAILED(); 133 } 134 135 traceRETURN_xEventGroupCreateStatic( pxEventBits ); 136 137 return pxEventBits; 138 } 139 140 #endif /* configSUPPORT_STATIC_ALLOCATION */ 141 /*-----------------------------------------------------------*/ 142 143 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) 144 xEventGroupCreate(void)145 EventGroupHandle_t xEventGroupCreate( void ) 146 { 147 EventGroup_t * pxEventBits; 148 149 traceENTER_xEventGroupCreate(); 150 151 /* MISRA Ref 11.5.1 [Malloc memory assignment] */ 152 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 153 /* coverity[misra_c_2012_rule_11_5_violation] */ 154 pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); 155 156 if( pxEventBits != NULL ) 157 { 158 pxEventBits->uxEventBits = 0; 159 vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); 160 161 #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 162 { 163 /* Both static and dynamic allocation can be used, so note this 164 * event group was allocated statically in case the event group is 165 * later deleted. */ 166 pxEventBits->ucStaticallyAllocated = pdFALSE; 167 } 168 #endif /* configSUPPORT_STATIC_ALLOCATION */ 169 170 traceEVENT_GROUP_CREATE( pxEventBits ); 171 } 172 else 173 { 174 traceEVENT_GROUP_CREATE_FAILED(); 175 } 176 177 traceRETURN_xEventGroupCreate( pxEventBits ); 178 179 return pxEventBits; 180 } 181 182 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ 183 /*-----------------------------------------------------------*/ 184 xEventGroupSync(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet,const EventBits_t uxBitsToWaitFor,TickType_t xTicksToWait)185 EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, 186 const EventBits_t uxBitsToSet, 187 const EventBits_t uxBitsToWaitFor, 188 TickType_t xTicksToWait ) 189 { 190 EventBits_t uxOriginalBitValue, uxReturn; 191 EventGroup_t * pxEventBits = xEventGroup; 192 BaseType_t xAlreadyYielded; 193 BaseType_t xTimeoutOccurred = pdFALSE; 194 195 traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait ); 196 197 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); 198 configASSERT( uxBitsToWaitFor != 0 ); 199 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) 200 { 201 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); 202 } 203 #endif 204 205 vTaskSuspendAll(); 206 { 207 uxOriginalBitValue = pxEventBits->uxEventBits; 208 209 ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); 210 211 if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) 212 { 213 /* All the rendezvous bits are now set - no need to block. */ 214 uxReturn = ( uxOriginalBitValue | uxBitsToSet ); 215 216 /* Rendezvous always clear the bits. They will have been cleared 217 * already unless this is the only task in the rendezvous. */ 218 pxEventBits->uxEventBits &= ~uxBitsToWaitFor; 219 220 xTicksToWait = 0; 221 } 222 else 223 { 224 if( xTicksToWait != ( TickType_t ) 0 ) 225 { 226 traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); 227 228 /* Store the bits that the calling task is waiting for in the 229 * task's event list item so the kernel knows when a match is 230 * found. Then enter the blocked state. */ 231 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); 232 233 /* This assignment is obsolete as uxReturn will get set after 234 * the task unblocks, but some compilers mistakenly generate a 235 * warning about uxReturn being returned without being set if the 236 * assignment is omitted. */ 237 uxReturn = 0; 238 } 239 else 240 { 241 /* The rendezvous bits were not set, but no block time was 242 * specified - just return the current event bit value. */ 243 uxReturn = pxEventBits->uxEventBits; 244 xTimeoutOccurred = pdTRUE; 245 } 246 } 247 } 248 xAlreadyYielded = xTaskResumeAll(); 249 250 if( xTicksToWait != ( TickType_t ) 0 ) 251 { 252 if( xAlreadyYielded == pdFALSE ) 253 { 254 taskYIELD_WITHIN_API(); 255 } 256 else 257 { 258 mtCOVERAGE_TEST_MARKER(); 259 } 260 261 /* The task blocked to wait for its required bits to be set - at this 262 * point either the required bits were set or the block time expired. If 263 * the required bits were set they will have been stored in the task's 264 * event list item, and they should now be retrieved then cleared. */ 265 uxReturn = uxTaskResetEventItemValue(); 266 267 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) 268 { 269 /* The task timed out, just return the current event bit value. */ 270 taskENTER_CRITICAL(); 271 { 272 uxReturn = pxEventBits->uxEventBits; 273 274 /* Although the task got here because it timed out before the 275 * bits it was waiting for were set, it is possible that since it 276 * unblocked another task has set the bits. If this is the case 277 * then it needs to clear the bits before exiting. */ 278 if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) 279 { 280 pxEventBits->uxEventBits &= ~uxBitsToWaitFor; 281 } 282 else 283 { 284 mtCOVERAGE_TEST_MARKER(); 285 } 286 } 287 taskEXIT_CRITICAL(); 288 289 xTimeoutOccurred = pdTRUE; 290 } 291 else 292 { 293 /* The task unblocked because the bits were set. */ 294 } 295 296 /* Control bits might be set as the task had blocked should not be 297 * returned. */ 298 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; 299 } 300 301 traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); 302 303 /* Prevent compiler warnings when trace macros are not used. */ 304 ( void ) xTimeoutOccurred; 305 306 traceRETURN_xEventGroupSync( uxReturn ); 307 308 return uxReturn; 309 } 310 /*-----------------------------------------------------------*/ 311 xEventGroupWaitBits(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToWaitFor,const BaseType_t xClearOnExit,const BaseType_t xWaitForAllBits,TickType_t xTicksToWait)312 EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, 313 const EventBits_t uxBitsToWaitFor, 314 const BaseType_t xClearOnExit, 315 const BaseType_t xWaitForAllBits, 316 TickType_t xTicksToWait ) 317 { 318 EventGroup_t * pxEventBits = xEventGroup; 319 EventBits_t uxReturn, uxControlBits = 0; 320 BaseType_t xWaitConditionMet, xAlreadyYielded; 321 BaseType_t xTimeoutOccurred = pdFALSE; 322 323 traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait ); 324 325 /* Check the user is not attempting to wait on the bits used by the kernel 326 * itself, and that at least one bit is being requested. */ 327 configASSERT( xEventGroup ); 328 configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); 329 configASSERT( uxBitsToWaitFor != 0 ); 330 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) 331 { 332 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); 333 } 334 #endif 335 336 vTaskSuspendAll(); 337 { 338 const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; 339 340 /* Check to see if the wait condition is already met or not. */ 341 xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); 342 343 if( xWaitConditionMet != pdFALSE ) 344 { 345 /* The wait condition has already been met so there is no need to 346 * block. */ 347 uxReturn = uxCurrentEventBits; 348 xTicksToWait = ( TickType_t ) 0; 349 350 /* Clear the wait bits if requested to do so. */ 351 if( xClearOnExit != pdFALSE ) 352 { 353 pxEventBits->uxEventBits &= ~uxBitsToWaitFor; 354 } 355 else 356 { 357 mtCOVERAGE_TEST_MARKER(); 358 } 359 } 360 else if( xTicksToWait == ( TickType_t ) 0 ) 361 { 362 /* The wait condition has not been met, but no block time was 363 * specified, so just return the current value. */ 364 uxReturn = uxCurrentEventBits; 365 xTimeoutOccurred = pdTRUE; 366 } 367 else 368 { 369 /* The task is going to block to wait for its required bits to be 370 * set. uxControlBits are used to remember the specified behaviour of 371 * this call to xEventGroupWaitBits() - for use when the event bits 372 * unblock the task. */ 373 if( xClearOnExit != pdFALSE ) 374 { 375 uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; 376 } 377 else 378 { 379 mtCOVERAGE_TEST_MARKER(); 380 } 381 382 if( xWaitForAllBits != pdFALSE ) 383 { 384 uxControlBits |= eventWAIT_FOR_ALL_BITS; 385 } 386 else 387 { 388 mtCOVERAGE_TEST_MARKER(); 389 } 390 391 /* Store the bits that the calling task is waiting for in the 392 * task's event list item so the kernel knows when a match is 393 * found. Then enter the blocked state. */ 394 vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); 395 396 /* This is obsolete as it will get set after the task unblocks, but 397 * some compilers mistakenly generate a warning about the variable 398 * being returned without being set if it is not done. */ 399 uxReturn = 0; 400 401 traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); 402 } 403 } 404 xAlreadyYielded = xTaskResumeAll(); 405 406 if( xTicksToWait != ( TickType_t ) 0 ) 407 { 408 if( xAlreadyYielded == pdFALSE ) 409 { 410 taskYIELD_WITHIN_API(); 411 } 412 else 413 { 414 mtCOVERAGE_TEST_MARKER(); 415 } 416 417 /* The task blocked to wait for its required bits to be set - at this 418 * point either the required bits were set or the block time expired. If 419 * the required bits were set they will have been stored in the task's 420 * event list item, and they should now be retrieved then cleared. */ 421 uxReturn = uxTaskResetEventItemValue(); 422 423 if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) 424 { 425 taskENTER_CRITICAL(); 426 { 427 /* The task timed out, just return the current event bit value. */ 428 uxReturn = pxEventBits->uxEventBits; 429 430 /* It is possible that the event bits were updated between this 431 * task leaving the Blocked state and running again. */ 432 if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) 433 { 434 if( xClearOnExit != pdFALSE ) 435 { 436 pxEventBits->uxEventBits &= ~uxBitsToWaitFor; 437 } 438 else 439 { 440 mtCOVERAGE_TEST_MARKER(); 441 } 442 } 443 else 444 { 445 mtCOVERAGE_TEST_MARKER(); 446 } 447 448 xTimeoutOccurred = pdTRUE; 449 } 450 taskEXIT_CRITICAL(); 451 } 452 else 453 { 454 /* The task unblocked because the bits were set. */ 455 } 456 457 /* The task blocked so control bits may have been set. */ 458 uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; 459 } 460 461 traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); 462 463 /* Prevent compiler warnings when trace macros are not used. */ 464 ( void ) xTimeoutOccurred; 465 466 traceRETURN_xEventGroupWaitBits( uxReturn ); 467 468 return uxReturn; 469 } 470 /*-----------------------------------------------------------*/ 471 xEventGroupClearBits(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToClear)472 EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, 473 const EventBits_t uxBitsToClear ) 474 { 475 EventGroup_t * pxEventBits = xEventGroup; 476 EventBits_t uxReturn; 477 478 traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear ); 479 480 /* Check the user is not attempting to clear the bits used by the kernel 481 * itself. */ 482 configASSERT( xEventGroup ); 483 configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); 484 485 taskENTER_CRITICAL(); 486 { 487 traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); 488 489 /* The value returned is the event group value prior to the bits being 490 * cleared. */ 491 uxReturn = pxEventBits->uxEventBits; 492 493 /* Clear the bits. */ 494 pxEventBits->uxEventBits &= ~uxBitsToClear; 495 } 496 taskEXIT_CRITICAL(); 497 498 traceRETURN_xEventGroupClearBits( uxReturn ); 499 500 return uxReturn; 501 } 502 /*-----------------------------------------------------------*/ 503 504 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) 505 xEventGroupClearBitsFromISR(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToClear)506 BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, 507 const EventBits_t uxBitsToClear ) 508 { 509 BaseType_t xReturn; 510 511 traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ); 512 513 traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); 514 xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); 515 516 traceRETURN_xEventGroupClearBitsFromISR( xReturn ); 517 518 return xReturn; 519 } 520 521 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */ 522 /*-----------------------------------------------------------*/ 523 xEventGroupGetBitsFromISR(EventGroupHandle_t xEventGroup)524 EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) 525 { 526 UBaseType_t uxSavedInterruptStatus; 527 EventGroup_t const * const pxEventBits = xEventGroup; 528 EventBits_t uxReturn; 529 530 traceENTER_xEventGroupGetBitsFromISR( xEventGroup ); 531 532 /* MISRA Ref 4.7.1 [Return value shall be checked] */ 533 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */ 534 /* coverity[misra_c_2012_directive_4_7_violation] */ 535 uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); 536 { 537 uxReturn = pxEventBits->uxEventBits; 538 } 539 taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); 540 541 traceRETURN_xEventGroupGetBitsFromISR( uxReturn ); 542 543 return uxReturn; 544 } 545 /*-----------------------------------------------------------*/ 546 xEventGroupSetBits(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet)547 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, 548 const EventBits_t uxBitsToSet ) 549 { 550 ListItem_t * pxListItem; 551 ListItem_t * pxNext; 552 ListItem_t const * pxListEnd; 553 List_t const * pxList; 554 EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; 555 EventGroup_t * pxEventBits = xEventGroup; 556 BaseType_t xMatchFound = pdFALSE; 557 558 traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet ); 559 560 /* Check the user is not attempting to set the bits used by the kernel 561 * itself. */ 562 configASSERT( xEventGroup ); 563 configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); 564 565 pxList = &( pxEventBits->xTasksWaitingForBits ); 566 pxListEnd = listGET_END_MARKER( pxList ); 567 vTaskSuspendAll(); 568 { 569 traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); 570 571 pxListItem = listGET_HEAD_ENTRY( pxList ); 572 573 /* Set the bits. */ 574 pxEventBits->uxEventBits |= uxBitsToSet; 575 576 /* See if the new bit value should unblock any tasks. */ 577 while( pxListItem != pxListEnd ) 578 { 579 pxNext = listGET_NEXT( pxListItem ); 580 uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); 581 xMatchFound = pdFALSE; 582 583 /* Split the bits waited for from the control bits. */ 584 uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; 585 uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; 586 587 if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) 588 { 589 /* Just looking for single bit being set. */ 590 if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) 591 { 592 xMatchFound = pdTRUE; 593 } 594 else 595 { 596 mtCOVERAGE_TEST_MARKER(); 597 } 598 } 599 else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) 600 { 601 /* All bits are set. */ 602 xMatchFound = pdTRUE; 603 } 604 else 605 { 606 /* Need all bits to be set, but not all the bits were set. */ 607 } 608 609 if( xMatchFound != pdFALSE ) 610 { 611 /* The bits match. Should the bits be cleared on exit? */ 612 if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) 613 { 614 uxBitsToClear |= uxBitsWaitedFor; 615 } 616 else 617 { 618 mtCOVERAGE_TEST_MARKER(); 619 } 620 621 /* Store the actual event flag value in the task's event list 622 * item before removing the task from the event list. The 623 * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows 624 * that is was unblocked due to its required bits matching, rather 625 * than because it timed out. */ 626 vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); 627 } 628 629 /* Move onto the next list item. Note pxListItem->pxNext is not 630 * used here as the list item may have been removed from the event list 631 * and inserted into the ready/pending reading list. */ 632 pxListItem = pxNext; 633 } 634 635 /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT 636 * bit was set in the control word. */ 637 pxEventBits->uxEventBits &= ~uxBitsToClear; 638 } 639 ( void ) xTaskResumeAll(); 640 641 traceRETURN_xEventGroupSetBits( pxEventBits->uxEventBits ); 642 643 return pxEventBits->uxEventBits; 644 } 645 /*-----------------------------------------------------------*/ 646 vEventGroupDelete(EventGroupHandle_t xEventGroup)647 void vEventGroupDelete( EventGroupHandle_t xEventGroup ) 648 { 649 EventGroup_t * pxEventBits = xEventGroup; 650 const List_t * pxTasksWaitingForBits; 651 652 traceENTER_vEventGroupDelete( xEventGroup ); 653 654 configASSERT( pxEventBits ); 655 656 pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); 657 658 vTaskSuspendAll(); 659 { 660 traceEVENT_GROUP_DELETE( xEventGroup ); 661 662 while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) 663 { 664 /* Unblock the task, returning 0 as the event list is being deleted 665 * and cannot therefore have any bits set. */ 666 configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); 667 vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); 668 } 669 } 670 ( void ) xTaskResumeAll(); 671 672 #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) 673 { 674 /* The event group can only have been allocated dynamically - free 675 * it again. */ 676 vPortFree( pxEventBits ); 677 } 678 #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) 679 { 680 /* The event group could have been allocated statically or 681 * dynamically, so check before attempting to free the memory. */ 682 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) 683 { 684 vPortFree( pxEventBits ); 685 } 686 else 687 { 688 mtCOVERAGE_TEST_MARKER(); 689 } 690 } 691 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ 692 693 traceRETURN_vEventGroupDelete(); 694 } 695 /*-----------------------------------------------------------*/ 696 697 #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) xEventGroupGetStaticBuffer(EventGroupHandle_t xEventGroup,StaticEventGroup_t ** ppxEventGroupBuffer)698 BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, 699 StaticEventGroup_t ** ppxEventGroupBuffer ) 700 { 701 BaseType_t xReturn; 702 EventGroup_t * pxEventBits = xEventGroup; 703 704 traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer ); 705 706 configASSERT( pxEventBits ); 707 configASSERT( ppxEventGroupBuffer ); 708 709 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) 710 { 711 /* Check if the event group was statically allocated. */ 712 if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE ) 713 { 714 /* MISRA Ref 11.3.1 [Misaligned access] */ 715 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ 716 /* coverity[misra_c_2012_rule_11_3_violation] */ 717 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; 718 xReturn = pdTRUE; 719 } 720 else 721 { 722 xReturn = pdFALSE; 723 } 724 } 725 #else /* configSUPPORT_DYNAMIC_ALLOCATION */ 726 { 727 /* Event group must have been statically allocated. */ 728 /* MISRA Ref 11.3.1 [Misaligned access] */ 729 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ 730 /* coverity[misra_c_2012_rule_11_3_violation] */ 731 *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; 732 xReturn = pdTRUE; 733 } 734 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ 735 736 traceRETURN_xEventGroupGetStaticBuffer( xReturn ); 737 738 return xReturn; 739 } 740 #endif /* configSUPPORT_STATIC_ALLOCATION */ 741 /*-----------------------------------------------------------*/ 742 743 /* For internal use only - execute a 'set bits' command that was pended from 744 * an interrupt. */ vEventGroupSetBitsCallback(void * pvEventGroup,uint32_t ulBitsToSet)745 void vEventGroupSetBitsCallback( void * pvEventGroup, 746 uint32_t ulBitsToSet ) 747 { 748 traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet ); 749 750 /* MISRA Ref 11.5.4 [Callback function parameter] */ 751 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 752 /* coverity[misra_c_2012_rule_11_5_violation] */ 753 ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); 754 755 traceRETURN_vEventGroupSetBitsCallback(); 756 } 757 /*-----------------------------------------------------------*/ 758 759 /* For internal use only - execute a 'clear bits' command that was pended from 760 * an interrupt. */ vEventGroupClearBitsCallback(void * pvEventGroup,uint32_t ulBitsToClear)761 void vEventGroupClearBitsCallback( void * pvEventGroup, 762 uint32_t ulBitsToClear ) 763 { 764 traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear ); 765 766 /* MISRA Ref 11.5.4 [Callback function parameter] */ 767 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 768 /* coverity[misra_c_2012_rule_11_5_violation] */ 769 ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); 770 771 traceRETURN_vEventGroupClearBitsCallback(); 772 } 773 /*-----------------------------------------------------------*/ 774 prvTestWaitCondition(const EventBits_t uxCurrentEventBits,const EventBits_t uxBitsToWaitFor,const BaseType_t xWaitForAllBits)775 static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, 776 const EventBits_t uxBitsToWaitFor, 777 const BaseType_t xWaitForAllBits ) 778 { 779 BaseType_t xWaitConditionMet = pdFALSE; 780 781 if( xWaitForAllBits == pdFALSE ) 782 { 783 /* Task only has to wait for one bit within uxBitsToWaitFor to be 784 * set. Is one already set? */ 785 if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) 786 { 787 xWaitConditionMet = pdTRUE; 788 } 789 else 790 { 791 mtCOVERAGE_TEST_MARKER(); 792 } 793 } 794 else 795 { 796 /* Task has to wait for all the bits in uxBitsToWaitFor to be set. 797 * Are they set already? */ 798 if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) 799 { 800 xWaitConditionMet = pdTRUE; 801 } 802 else 803 { 804 mtCOVERAGE_TEST_MARKER(); 805 } 806 } 807 808 return xWaitConditionMet; 809 } 810 /*-----------------------------------------------------------*/ 811 812 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) 813 xEventGroupSetBitsFromISR(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet,BaseType_t * pxHigherPriorityTaskWoken)814 BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, 815 const EventBits_t uxBitsToSet, 816 BaseType_t * pxHigherPriorityTaskWoken ) 817 { 818 BaseType_t xReturn; 819 820 traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ); 821 822 traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); 823 xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); 824 825 traceRETURN_xEventGroupSetBitsFromISR( xReturn ); 826 827 return xReturn; 828 } 829 830 #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */ 831 /*-----------------------------------------------------------*/ 832 833 #if ( configUSE_TRACE_FACILITY == 1 ) 834 uxEventGroupGetNumber(void * xEventGroup)835 UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) 836 { 837 UBaseType_t xReturn; 838 839 /* MISRA Ref 11.5.2 [Opaque pointer] */ 840 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 841 /* coverity[misra_c_2012_rule_11_5_violation] */ 842 EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; 843 844 traceENTER_uxEventGroupGetNumber( xEventGroup ); 845 846 if( xEventGroup == NULL ) 847 { 848 xReturn = 0; 849 } 850 else 851 { 852 xReturn = pxEventBits->uxEventGroupNumber; 853 } 854 855 traceRETURN_uxEventGroupGetNumber( xReturn ); 856 857 return xReturn; 858 } 859 860 #endif /* configUSE_TRACE_FACILITY */ 861 /*-----------------------------------------------------------*/ 862 863 #if ( configUSE_TRACE_FACILITY == 1 ) 864 vEventGroupSetNumber(void * xEventGroup,UBaseType_t uxEventGroupNumber)865 void vEventGroupSetNumber( void * xEventGroup, 866 UBaseType_t uxEventGroupNumber ) 867 { 868 traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber ); 869 870 /* MISRA Ref 11.5.2 [Opaque pointer] */ 871 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 872 /* coverity[misra_c_2012_rule_11_5_violation] */ 873 ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; 874 875 traceRETURN_vEventGroupSetNumber(); 876 } 877 878 #endif /* configUSE_TRACE_FACILITY */ 879 /*-----------------------------------------------------------*/ 880 881 /* This entire source file will be skipped if the application is not configured 882 * to include event groups functionality. If you want to include event groups 883 * then ensure configUSE_EVENT_GROUPS is set to 1 in FreeRTOSConfig.h. */ 884 #endif /* configUSE_EVENT_GROUPS == 1 */ 885