event_groups.c 35 KB

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