This is a FreeRTOS C++ binding. Supports some advanced C++ features.
The current supported FreeRTOS features: Task, Queue, Semaphores and Mutex.
# idf_component.yml
dependencies:
freertos-cpp:
git: https://github.com/Augtons/ESP-FreeRTOS-Cpp
Please refer to examples:
-
get-started
, Click Here -
reference_count
, Click Here
task<> your_task = task_builder<>("task name")
.stack(2048)
.priority(0)
.bind([] {
while (true) {
ESP_LOGI("TAG", "Task is running.");
vTaskDelay(pdMS_TO_TICKS(1000));
}
});
task<> your_task = task_factory<>::create("task name", 2048, 0, [] {
while (true) {
ESP_LOGI("TAG", "Task is running.");
vTaskDelay(pdMS_TO_TICKS(1000));
}
});
Also Supports function.
void task_function() {
while (true) {
ESP_LOGI("TAG", "Task is running.");
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
task<> your_task = task_factory<>::create("task name", 2048, 0, task_function);
Next, using C++ reference types as an example, please note that during the task execution, the reference must remain valid (for example, int a = 0 in the following example must not go out of scope)
int a = 123;
task<int&> your_task = task_builder<int&>("task name")
.stack(2048)
.priority(0)
.bind(a, [](int& args) { // variable `a` will be passed as a int&
while (true) {
ESP_LOGI("TAG", "Task is running, a = %d.", arg);
vTaskDelay(pdMS_TO_TICKS(1000));
}
});
You can also use lambda to capture variables in scope.
int a = 123;
task<> your_task = task_builder<>("task name")
.stack(2048)
.priority(0)
.bind([&a]() { // variable `a` captured as reference.
while (true) {
ESP_LOGI("TAG", "Task is running, a = %d.", a);
vTaskDelay(pdMS_TO_TICKS(1000));
}
});
task_factory<Type>
also ok!
int a = 123;
task<int&> your_task = task_factory<int&>::create("task name", 2048, 0, a, [](int& arg) {
while (true) {
ESP_LOGI("TAG", "Task is running, a = %d.", arg);
vTaskDelay(pdMS_TO_TICKS(1000));
}
});
It will be deleted automatically when its task function returns.
The Safe Way:
task<> your_task = task_factory<>::create("task name", 2048, 0, [] {
ESP_LOGI("TAG", "Start.");
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_LOGI("TAG", "Will be deleted.");
});
Note: Don't use
vTaskDelete(NULL)
to delete it! Memory leaks will occur.
The Safe Way:
your_task.delete_task();
Note: Don't use
vTaskDelete((TaskHandle_t)your_task)
to delete it. Memory leaks will occur.
// The first way.
auto handle = (TaskHandle_t)your_task;
// Equals to the first way.
auto handle = your_task.native_handle();
// Get native handle but `abort()` when your_task is null.
auto handle = your_task.native_handle_not_null();
Examples
// 1.
task<> t1;
auto handle = (TaskHandle_t)t1; // handle is nullptr.
auto handle = t1.native_handle(); //handle is nullptr.
// 2.
task<> t2;
task<> t3 = task_builder<>(...)...; // Create Task
auto handle = t2.native_handle_not_null(); // Error, abort().
auto handle = t3.native_handle_not_null(); // Handle of t3.
auto handle = (TaskHandle_t)t2; // nullptr
When the reference count of a task<>
object is 0, the FreeRTOS Task will be deleted.
It has some features similar to std::shared_ptr
.
task<> t1;
t1.use_count(); // use_count of null object it always 1.
task<> t2 = task_builder<>("task").stack(2048).priority(0).bind([]() {
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
});
t2.use_count(); // 1
t1 = t2;
t2.use_count(); // 2
t1.use_count(); // 2
task<> t3 = task_builder<>("task2").stack(2048).priority(0).bind([]() {
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
});
t1 = t3;
t3.use_count(); // 2
t2.use_count(); // 1
task<> t4 = task_builder<>("task2").stack(2048).priority(0).bind([]() {
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
});
t1 = std::move(t4);
t1.use_count(); // 1
Please refer to examples queue
, Click Here
Please refer to examples semaphore
, Click Here