event_flag.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "event_flag.h"
  2. #include "common_defines.h"
  3. #include "check.h"
  4. #include <event_groups.h>
  5. #define FURI_EVENT_FLAG_MAX_BITS_EVENT_GROUPS 24U
  6. #define FURI_EVENT_FLAG_INVALID_BITS (~((1UL << FURI_EVENT_FLAG_MAX_BITS_EVENT_GROUPS) - 1U))
  7. FuriEventFlag* furi_event_flag_alloc() {
  8. furi_assert(!FURI_IS_IRQ_MODE());
  9. EventGroupHandle_t handle = xEventGroupCreate();
  10. furi_check(handle);
  11. return ((FuriEventFlag*)handle);
  12. }
  13. void furi_event_flag_free(FuriEventFlag* instance) {
  14. furi_assert(!FURI_IS_IRQ_MODE());
  15. vEventGroupDelete((EventGroupHandle_t)instance);
  16. }
  17. uint32_t furi_event_flag_set(FuriEventFlag* instance, uint32_t flags) {
  18. furi_assert(instance);
  19. furi_assert((flags & FURI_EVENT_FLAG_INVALID_BITS) == 0U);
  20. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)instance;
  21. uint32_t rflags;
  22. BaseType_t yield;
  23. if(FURI_IS_IRQ_MODE()) {
  24. yield = pdFALSE;
  25. if(xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
  26. rflags = (uint32_t)FuriFlagErrorResource;
  27. } else {
  28. rflags = flags;
  29. portYIELD_FROM_ISR(yield);
  30. }
  31. } else {
  32. rflags = xEventGroupSetBits(hEventGroup, (EventBits_t)flags);
  33. }
  34. /* Return event flags after setting */
  35. return (rflags);
  36. }
  37. uint32_t furi_event_flag_clear(FuriEventFlag* instance, uint32_t flags) {
  38. furi_assert(instance);
  39. furi_assert((flags & FURI_EVENT_FLAG_INVALID_BITS) == 0U);
  40. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)instance;
  41. uint32_t rflags;
  42. if(FURI_IS_IRQ_MODE()) {
  43. rflags = xEventGroupGetBitsFromISR(hEventGroup);
  44. if(xEventGroupClearBitsFromISR(hEventGroup, (EventBits_t)flags) == pdFAIL) {
  45. rflags = (uint32_t)FuriStatusErrorResource;
  46. } else {
  47. /* xEventGroupClearBitsFromISR only registers clear operation in the timer command queue. */
  48. /* Yield is required here otherwise clear operation might not execute in the right order. */
  49. /* See https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/93 for more info. */
  50. portYIELD_FROM_ISR(pdTRUE);
  51. }
  52. } else {
  53. rflags = xEventGroupClearBits(hEventGroup, (EventBits_t)flags);
  54. }
  55. /* Return event flags before clearing */
  56. return (rflags);
  57. }
  58. uint32_t furi_event_flag_get(FuriEventFlag* instance) {
  59. furi_assert(instance);
  60. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)instance;
  61. uint32_t rflags;
  62. if(FURI_IS_IRQ_MODE()) {
  63. rflags = xEventGroupGetBitsFromISR(hEventGroup);
  64. } else {
  65. rflags = xEventGroupGetBits(hEventGroup);
  66. }
  67. /* Return current event flags */
  68. return (rflags);
  69. }
  70. uint32_t furi_event_flag_wait(
  71. FuriEventFlag* instance,
  72. uint32_t flags,
  73. uint32_t options,
  74. uint32_t timeout) {
  75. furi_assert(!FURI_IS_IRQ_MODE());
  76. furi_assert(instance);
  77. furi_assert((flags & FURI_EVENT_FLAG_INVALID_BITS) == 0U);
  78. EventGroupHandle_t hEventGroup = (EventGroupHandle_t)instance;
  79. BaseType_t wait_all;
  80. BaseType_t exit_clr;
  81. uint32_t rflags;
  82. if(options & FuriFlagWaitAll) {
  83. wait_all = pdTRUE;
  84. } else {
  85. wait_all = pdFAIL;
  86. }
  87. if(options & FuriFlagNoClear) {
  88. exit_clr = pdFAIL;
  89. } else {
  90. exit_clr = pdTRUE;
  91. }
  92. rflags = xEventGroupWaitBits(
  93. hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout);
  94. if(options & FuriFlagWaitAll) {
  95. if((flags & rflags) != flags) {
  96. if(timeout > 0U) {
  97. rflags = (uint32_t)FuriStatusErrorTimeout;
  98. } else {
  99. rflags = (uint32_t)FuriStatusErrorResource;
  100. }
  101. }
  102. } else {
  103. if((flags & rflags) == 0U) {
  104. if(timeout > 0U) {
  105. rflags = (uint32_t)FuriStatusErrorTimeout;
  106. } else {
  107. rflags = (uint32_t)FuriStatusErrorResource;
  108. }
  109. }
  110. }
  111. /* Return event flags before clearing */
  112. return (rflags);
  113. }