event_flag.c 3.9 KB

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