furi_ac.c 4.8 KB

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