kernel.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include "kernel.h"
  2. #include "base.h"
  3. #include "check.h"
  4. #include "common_defines.h"
  5. #include <furi_hal.h>
  6. #include CMSIS_device_header
  7. int32_t furi_kernel_lock() {
  8. furi_assert(!furi_is_irq_context());
  9. int32_t lock;
  10. switch(xTaskGetSchedulerState()) {
  11. case taskSCHEDULER_SUSPENDED:
  12. lock = 1;
  13. break;
  14. case taskSCHEDULER_RUNNING:
  15. vTaskSuspendAll();
  16. lock = 0;
  17. break;
  18. case taskSCHEDULER_NOT_STARTED:
  19. default:
  20. lock = (int32_t)FuriStatusError;
  21. break;
  22. }
  23. /* Return previous lock state */
  24. return (lock);
  25. }
  26. int32_t furi_kernel_unlock() {
  27. furi_assert(!furi_is_irq_context());
  28. int32_t lock;
  29. switch(xTaskGetSchedulerState()) {
  30. case taskSCHEDULER_SUSPENDED:
  31. lock = 1;
  32. if(xTaskResumeAll() != pdTRUE) {
  33. if(xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) {
  34. lock = (int32_t)FuriStatusError;
  35. }
  36. }
  37. break;
  38. case taskSCHEDULER_RUNNING:
  39. lock = 0;
  40. break;
  41. case taskSCHEDULER_NOT_STARTED:
  42. default:
  43. lock = (int32_t)FuriStatusError;
  44. break;
  45. }
  46. /* Return previous lock state */
  47. return (lock);
  48. }
  49. int32_t furi_kernel_restore_lock(int32_t lock) {
  50. furi_assert(!furi_is_irq_context());
  51. switch(xTaskGetSchedulerState()) {
  52. case taskSCHEDULER_SUSPENDED:
  53. case taskSCHEDULER_RUNNING:
  54. if(lock == 1) {
  55. vTaskSuspendAll();
  56. } else {
  57. if(lock != 0) {
  58. lock = (int32_t)FuriStatusError;
  59. } else {
  60. if(xTaskResumeAll() != pdTRUE) {
  61. if(xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
  62. lock = (int32_t)FuriStatusError;
  63. }
  64. }
  65. }
  66. }
  67. break;
  68. case taskSCHEDULER_NOT_STARTED:
  69. default:
  70. lock = (int32_t)FuriStatusError;
  71. break;
  72. }
  73. /* Return new lock state */
  74. return (lock);
  75. }
  76. uint32_t furi_kernel_get_tick_frequency() {
  77. /* Return frequency in hertz */
  78. return (configTICK_RATE_HZ_RAW);
  79. }
  80. void furi_delay_tick(uint32_t ticks) {
  81. furi_assert(!furi_is_irq_context());
  82. if(ticks == 0U) {
  83. taskYIELD();
  84. } else {
  85. vTaskDelay(ticks);
  86. }
  87. }
  88. FuriStatus furi_delay_until_tick(uint32_t tick) {
  89. furi_assert(!furi_is_irq_context());
  90. TickType_t tcnt, delay;
  91. FuriStatus stat;
  92. stat = FuriStatusOk;
  93. tcnt = xTaskGetTickCount();
  94. /* Determine remaining number of tick to delay */
  95. delay = (TickType_t)tick - tcnt;
  96. /* Check if target tick has not expired */
  97. if((delay != 0U) && (0 == (delay >> (8 * sizeof(TickType_t) - 1)))) {
  98. if(xTaskDelayUntil(&tcnt, delay) == pdFALSE) {
  99. /* Did not delay */
  100. stat = FuriStatusError;
  101. }
  102. } else {
  103. /* No delay or already expired */
  104. stat = FuriStatusErrorParameter;
  105. }
  106. /* Return execution status */
  107. return (stat);
  108. }
  109. uint32_t furi_get_tick() {
  110. TickType_t ticks;
  111. if(furi_is_irq_context() != 0U) {
  112. ticks = xTaskGetTickCountFromISR();
  113. } else {
  114. ticks = xTaskGetTickCount();
  115. }
  116. return ticks;
  117. }
  118. uint32_t furi_ms_to_ticks(uint32_t milliseconds) {
  119. #if configTICK_RATE_HZ_RAW == 1000
  120. return milliseconds;
  121. #else
  122. return (uint32_t)((float)configTICK_RATE_HZ_RAW) / 1000.0f * (float)milliseconds;
  123. #endif
  124. }
  125. void furi_delay_ms(uint32_t milliseconds) {
  126. if(!FURI_IS_ISR() && xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
  127. if(milliseconds > 0 && milliseconds < portMAX_DELAY - 1) {
  128. milliseconds += 1;
  129. }
  130. #if configTICK_RATE_HZ_RAW == 1000
  131. furi_delay_tick(milliseconds);
  132. #else
  133. furi_delay_tick(furi_ms_to_ticks(milliseconds));
  134. #endif
  135. } else if(milliseconds > 0) {
  136. furi_delay_us(milliseconds * 1000);
  137. }
  138. }
  139. void furi_delay_us(uint32_t microseconds) {
  140. furi_hal_cortex_delay_us(microseconds);
  141. }