# FreeRTOS Binging For ESP-IDF This is a FreeRTOS C++ binding. Supports some advanced C++ features. The current supported FreeRTOS features: Task, Queue, Semaphores and Mutex. # Contents - [FreeRTOS Binging For ESP-IDF](#freertos-binging-for-esp-idf) - [Installation](#installation) - [Getting Started](#getting-started) - [1. Tasks](#1-tasks) - [(1) Creating](#1-creating) - [a) Without Arguments:](#a-without-arguments) - [b) With Arguments:](#b-with-arguments) - [(2) Deleting.](#2-deleting) - [Delete itself](#delete-itself) - [Delete by `task<...>` object](#delete-by-task-object) - [(3) Get Native Task Handle (TaskHandle_t)](#3-get-native-task-handle-taskhandle_t) - [(4) Reference count.](#4-reference-count) - [2. Queue](#2-queue) - [3. Semaphores and Mutex](#3-semaphores-and-mutex) # Installation ```yaml # idf_component.yml dependencies: freertos-cpp: git: https://github.com/Augtons/ESP-FreeRTOS-Cpp ``` # Getting Started ## 1. Tasks Please refer to examples: - `get-started`, [Click Here](examples/get-started/main/get-started.cpp) - `reference_count`, [Click Here](examples/reference_count/main/reference_count.cpp) ### (1) Creating #### a) Without Arguments: ```cpp 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)); } }); ``` ```cpp 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. ```cpp 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); ``` #### b) With Arguments: 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) ```cpp 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. ```cpp 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! ```cpp 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)); } }); ``` ### (2) Deleting. #### Delete itself It will be deleted automatically when its task function returns. The Safe Way: ```cpp 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. #### Delete by `task<...>` object The Safe Way: ```cpp your_task.delete_task(); ``` > Note: **Don't** use `vTaskDelete((TaskHandle_t)your_task)` to delete it. Memory leaks will occur. ### (3) Get Native Task Handle (TaskHandle_t) ```cpp // 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 ```cpp // 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 ``` ### (4) Reference count. 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`. ```cpp 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 ``` ## 2. Queue Please refer to examples `queue`, [Click Here](examples/queue/main/queue.cpp) ## 3. Semaphores and Mutex Please refer to examples `semaphore`, [Click Here](examples/semaphore/main/semaphore.cpp)
idf.py add-dependency "augtons/freertos-cpp^1.0.3"