furi_ac.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "flipper.h"
  2. #include "api-hal-task.h"
  3. // TODO: this file contains printf, that not implemented on uC target
  4. #ifdef FURI_DEBUG
  5. #include <stdio.h>
  6. #endif
  7. #include <string.h>
  8. #define INVALID_TASK_ID UINT16_MAX
  9. static StaticTask_t task_info_buffer[MAX_TASK_COUNT];
  10. static StackType_t stack_buffer[MAX_TASK_COUNT][DEFAULT_STACK_SIZE / 4];
  11. static FuriApp task_buffer[MAX_TASK_COUNT];
  12. static size_t current_buffer_idx = 0;
  13. uint16_t furiac_get_task_id_by_name(const char* app_name) {
  14. for(size_t i = 0; i < MAX_TASK_RECORDS; i++) {
  15. if(strcmp(task_buffer[i].name, app_name) == 0) return i;
  16. }
  17. return INVALID_TASK_ID;
  18. }
  19. void furiac_wait_libs(const FlipperAppLibrary* libs) {
  20. for(uint8_t i = 0; i < libs->count; i++) {
  21. uint16_t app_id = furiac_get_task_id_by_name(libs->name[i]);
  22. if(app_id == INVALID_TASK_ID) {
  23. #ifdef FURI_DEBUG
  24. printf("[FURIAC] Invalid library name %s\n", libs->name[i]);
  25. #endif
  26. } else {
  27. while(!task_buffer[app_id].ready) {
  28. #ifdef FURI_DEBUG
  29. printf("[FURIAC] waiting for library \"%s\"\n", libs->name[i]);
  30. #endif
  31. osDelay(50);
  32. }
  33. }
  34. }
  35. }
  36. // find task pointer by handle
  37. FuriApp* find_task(TaskHandle_t handler) {
  38. FuriApp* res = NULL;
  39. for(size_t i = 0; i < MAX_TASK_COUNT; i++) {
  40. if(task_equal(task_buffer[i].handler, handler)) {
  41. res = &task_buffer[i];
  42. }
  43. }
  44. return res;
  45. }
  46. FuriApp* furiac_start(FlipperApplication app, const char* name, void* param) {
  47. #ifdef FURI_DEBUG
  48. printf("[FURIAC] start %s\n", name);
  49. #endif
  50. // TODO check first free item (.handler == NULL) and use it
  51. if(current_buffer_idx >= MAX_TASK_COUNT) {
  52. // max task count exceed
  53. #ifdef FURI_DEBUG
  54. printf("[FURIAC] max task count exceed\n");
  55. #endif
  56. return NULL;
  57. }
  58. // application ready
  59. task_buffer[current_buffer_idx].ready = false;
  60. // create task on static stack memory
  61. task_buffer[current_buffer_idx].handler = xTaskCreateStatic(
  62. (TaskFunction_t)app,
  63. (const char* const)name,
  64. DEFAULT_STACK_SIZE / 4, // freertos specify stack size in words
  65. (void* const)param,
  66. tskIDLE_PRIORITY + 3, // normal priority
  67. stack_buffer[current_buffer_idx],
  68. &task_info_buffer[current_buffer_idx]);
  69. // save task
  70. task_buffer[current_buffer_idx].application = app;
  71. task_buffer[current_buffer_idx].prev_name = NULL;
  72. task_buffer[current_buffer_idx].prev = NULL;
  73. task_buffer[current_buffer_idx].records_count = 0;
  74. task_buffer[current_buffer_idx].name = name;
  75. current_buffer_idx++;
  76. return &task_buffer[current_buffer_idx - 1];
  77. }
  78. bool furiac_kill(FuriApp* app) {
  79. #ifdef FURI_DEBUG
  80. printf("[FURIAC] kill %s\n", app->name);
  81. #endif
  82. // check handler
  83. if(app == NULL || app->handler == NULL) return false;
  84. // kill task
  85. vTaskDelete(app->handler);
  86. // cleanup its registry
  87. // TODO realy free memory
  88. app->handler = NULL;
  89. return true;
  90. }
  91. void furiac_exit(void* param) {
  92. // get current task handler
  93. FuriApp* current_task = find_task(xTaskGetCurrentTaskHandle());
  94. // run prev
  95. if(current_task != NULL) {
  96. #ifdef FURI_DEBUG
  97. printf("[FURIAC] exit %s\n", current_task->name);
  98. #endif
  99. if(current_task->prev != NULL) {
  100. furiac_start(current_task->prev, current_task->prev_name, param);
  101. } else {
  102. #ifdef FURI_DEBUG
  103. printf("[FURIAC] no prev\n");
  104. #endif
  105. }
  106. // cleanup registry
  107. // TODO realy free memory
  108. current_task->handler = NULL;
  109. }
  110. // kill itself
  111. vTaskDelete(NULL);
  112. }
  113. void furiac_switch(FlipperApplication app, char* name, void* param) {
  114. // get current task handler
  115. FuriApp* current_task = find_task(xTaskGetCurrentTaskHandle());
  116. if(current_task == NULL) {
  117. #ifdef FURI_DEBUG
  118. printf("[FURIAC] no current task found\n");
  119. #endif
  120. }
  121. #ifdef FURI_DEBUG
  122. printf("[FURIAC] switch %s to %s\n", current_task->name, name);
  123. #endif
  124. // run next
  125. FuriApp* next = furiac_start(app, name, param);
  126. if(next != NULL) {
  127. // save current application pointer as prev
  128. next->prev = current_task->application;
  129. next->prev_name = current_task->name;
  130. // kill itself
  131. vTaskDelete(NULL);
  132. }
  133. }
  134. // set task to ready state
  135. void furiac_ready() {
  136. /*
  137. TODO:
  138. Currently i think that better way is to use application name
  139. and restrict applications to "one task per application"
  140. */
  141. FuriApp* app = find_task(xTaskGetCurrentTaskHandle());
  142. if(app == NULL) {
  143. #ifdef FURI_DEBUG
  144. printf("[FURIAC] cannot find task to set ready state\n");
  145. #endif
  146. } else {
  147. #ifdef FURI_DEBUG
  148. printf("[FURIAC] task is ready\n");
  149. #endif
  150. app->ready = true;
  151. }
  152. }