BellTask.h 3.2 KB

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