BellTask.h 3.0 KB

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