Task.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #ifndef BELL_TASK_H
  2. #define BELL_TASK_H
  3. #ifdef ESP_PLATFORM
  4. #include <esp_pthread.h>
  5. #include <esp_task.h>
  6. #include <freertos/FreeRTOS.h>
  7. #include <freertos/timers.h>
  8. #include <freertos/task.h>
  9. #endif
  10. #include <pthread.h>
  11. namespace bell
  12. {
  13. class Task
  14. {
  15. public:
  16. std::string taskName;
  17. int stackSize, core;
  18. bool isRunning = false;
  19. bool runOnPSRAM;
  20. Task(std::string taskName, int stackSize, int priority, int core, bool runOnPSRAM = true)
  21. {
  22. this->taskName = taskName;
  23. this->stackSize = stackSize;
  24. this->core = core;
  25. this->runOnPSRAM = runOnPSRAM;
  26. #ifdef ESP_PLATFORM
  27. this->priority = CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + priority;
  28. if (this->priority < 0) this->priority = ESP_TASK_PRIO_MIN;
  29. #endif
  30. }
  31. virtual ~Task() {}
  32. bool startTask()
  33. {
  34. #ifdef ESP_PLATFORM
  35. if (runOnPSRAM)
  36. {
  37. xTaskBuffer = (StaticTask_t *)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  38. xStack = (StackType_t *)heap_caps_malloc(this->stackSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  39. return (xTaskCreateStaticPinnedToCore(taskEntryFuncPSRAM, this->taskName.c_str(), this->stackSize, this, this->priority, xStack, xTaskBuffer, this->core) != NULL);
  40. }
  41. else
  42. {
  43. esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
  44. cfg.stack_size = stackSize;
  45. cfg.inherit_cfg = true;
  46. cfg.thread_name = this->taskName.c_str();
  47. cfg.pin_to_core = core;
  48. cfg.prio = this->priority;
  49. esp_pthread_set_cfg(&cfg);
  50. }
  51. #endif
  52. return (pthread_create(&_thread, NULL, taskEntryFunc, this) == 0);
  53. }
  54. void waitForTaskToReturn()
  55. {
  56. #ifdef ESP_PLATFORM
  57. if (runOnPSRAM)
  58. {
  59. while (isRunning)
  60. {
  61. vTaskDelay(100 / portTICK_PERIOD_MS);
  62. }
  63. heap_caps_free(xStack);
  64. // TCB are cleanup in IDLE task, so give it some time
  65. TimerHandle_t timer = xTimerCreate( "cleanup", pdMS_TO_TICKS(5000), pdFALSE, xTaskBuffer,
  66. [](TimerHandle_t xTimer) {
  67. heap_caps_free(pvTimerGetTimerID(xTimer));
  68. xTimerDelete(xTimer, portMAX_DELAY);
  69. } );
  70. xTimerStart(timer, portMAX_DELAY);
  71. }
  72. else
  73. {
  74. (void)pthread_join(_thread, NULL);
  75. }
  76. #else
  77. (void)pthread_join(_thread, NULL);
  78. #endif
  79. }
  80. protected:
  81. virtual void runTask() = 0;
  82. private:
  83. #ifdef ESP_PLATFORM
  84. int priority;
  85. StaticTask_t *xTaskBuffer;
  86. StackType_t *xStack;
  87. #endif
  88. static void *taskEntryFunc(void *This)
  89. {
  90. ((Task *)This)->runTask();
  91. return NULL;
  92. }
  93. #ifdef ESP_PLATFORM
  94. static void taskEntryFuncPSRAM(void *This)
  95. {
  96. ((Task *)This)->isRunning = true;
  97. Task *self = (Task *)This;
  98. self->isRunning = true;
  99. self->runTask();
  100. self->isRunning = false;
  101. vTaskDelete(NULL);
  102. }
  103. #endif
  104. pthread_t _thread;
  105. };
  106. }
  107. #endif