furi_ac.c 4.8 KB

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