timer.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include "timer.h"
  2. #include "check.h"
  3. #include "memmgr.h"
  4. #include "kernel.h"
  5. #include <FreeRTOS.h>
  6. #include <timers.h>
  7. typedef struct {
  8. FuriTimerCallback func;
  9. void* context;
  10. } TimerCallback_t;
  11. static void TimerCallback(TimerHandle_t hTimer) {
  12. TimerCallback_t* callb;
  13. /* Retrieve pointer to callback function and context */
  14. callb = (TimerCallback_t*)pvTimerGetTimerID(hTimer);
  15. /* Remove dynamic allocation flag */
  16. callb = (TimerCallback_t*)((uint32_t)callb & ~1U);
  17. if(callb != NULL) {
  18. callb->func(callb->context);
  19. }
  20. }
  21. FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* context) {
  22. furi_assert((furi_kernel_is_irq_or_masked() == 0U) && (func != NULL));
  23. TimerHandle_t hTimer;
  24. TimerCallback_t* callb;
  25. UBaseType_t reload;
  26. hTimer = NULL;
  27. /* Dynamic memory allocation is available: if memory for callback and */
  28. /* its context is not provided, allocate it from dynamic memory pool */
  29. callb = (TimerCallback_t*)malloc(sizeof(TimerCallback_t));
  30. callb->func = func;
  31. callb->context = context;
  32. if(type == FuriTimerTypeOnce) {
  33. reload = pdFALSE;
  34. } else {
  35. reload = pdTRUE;
  36. }
  37. /* Store callback memory dynamic allocation flag */
  38. callb = (TimerCallback_t*)((uint32_t)callb | 1U);
  39. // TimerCallback function is always provided as a callback and is used to call application
  40. // specified function with its context both stored in structure callb.
  41. hTimer = xTimerCreate(NULL, 1, reload, callb, TimerCallback);
  42. furi_check(hTimer);
  43. /* Return timer ID */
  44. return ((FuriTimer*)hTimer);
  45. }
  46. void furi_timer_free(FuriTimer* instance) {
  47. furi_assert(!furi_kernel_is_irq_or_masked());
  48. furi_assert(instance);
  49. TimerHandle_t hTimer = (TimerHandle_t)instance;
  50. TimerCallback_t* callb;
  51. callb = (TimerCallback_t*)pvTimerGetTimerID(hTimer);
  52. furi_check(xTimerDelete(hTimer, portMAX_DELAY) == pdPASS);
  53. while(furi_timer_is_running(instance)) furi_delay_tick(2);
  54. if((uint32_t)callb & 1U) {
  55. /* Callback memory was allocated from dynamic pool, clear flag */
  56. callb = (TimerCallback_t*)((uint32_t)callb & ~1U);
  57. /* Return allocated memory to dynamic pool */
  58. free(callb);
  59. }
  60. }
  61. FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) {
  62. furi_assert(!furi_kernel_is_irq_or_masked());
  63. furi_assert(instance);
  64. TimerHandle_t hTimer = (TimerHandle_t)instance;
  65. FuriStatus stat;
  66. if(xTimerChangePeriod(hTimer, ticks, portMAX_DELAY) == pdPASS) {
  67. stat = FuriStatusOk;
  68. } else {
  69. stat = FuriStatusErrorResource;
  70. }
  71. /* Return execution status */
  72. return (stat);
  73. }
  74. FuriStatus furi_timer_stop(FuriTimer* instance) {
  75. furi_assert(!furi_kernel_is_irq_or_masked());
  76. furi_assert(instance);
  77. TimerHandle_t hTimer = (TimerHandle_t)instance;
  78. FuriStatus stat;
  79. if(xTimerIsTimerActive(hTimer) == pdFALSE) {
  80. stat = FuriStatusErrorResource;
  81. } else {
  82. furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS);
  83. stat = FuriStatusOk;
  84. }
  85. /* Return execution status */
  86. return (stat);
  87. }
  88. uint32_t furi_timer_is_running(FuriTimer* instance) {
  89. furi_assert(!furi_kernel_is_irq_or_masked());
  90. furi_assert(instance);
  91. TimerHandle_t hTimer = (TimerHandle_t)instance;
  92. /* Return 0: not running, 1: running */
  93. return (uint32_t)xTimerIsTimerActive(hTimer);
  94. }