2018-11-28 14:40:32 -05:00
|
|
|
/* pthread/std::thread example
|
|
|
|
|
|
|
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, this
|
|
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <thread>
|
|
|
|
#include <chrono>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
#include <sstream>
|
|
|
|
#include <esp_pthread.h>
|
|
|
|
#include <freertos/FreeRTOS.h>
|
|
|
|
#include <freertos/task.h>
|
|
|
|
#include <esp_log.h>
|
|
|
|
|
|
|
|
using namespace std::chrono;
|
|
|
|
|
2024-03-05 01:07:05 -05:00
|
|
|
const auto sleep_time = seconds {
|
2018-11-28 14:40:32 -05:00
|
|
|
5
|
|
|
|
};
|
|
|
|
|
|
|
|
void print_thread_info(const char *extra = nullptr)
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
if (extra) {
|
|
|
|
ss << extra;
|
|
|
|
}
|
|
|
|
ss << "Core id: " << xPortGetCoreID()
|
|
|
|
<< ", prio: " << uxTaskPriorityGet(nullptr)
|
|
|
|
<< ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
|
2022-02-08 04:39:38 -05:00
|
|
|
ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str());
|
2018-11-28 14:40:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void thread_func_inherited()
|
|
|
|
{
|
|
|
|
while (true) {
|
|
|
|
print_thread_info("This is the INHERITING thread with the same parameters as our parent, including name. ");
|
|
|
|
std::this_thread::sleep_for(sleep_time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void spawn_another_thread()
|
|
|
|
{
|
|
|
|
// Create a new thread, it will inherit our configuration
|
|
|
|
std::thread inherits(thread_func_inherited);
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
print_thread_info();
|
|
|
|
std::this_thread::sleep_for(sleep_time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void thread_func_any_core()
|
|
|
|
{
|
|
|
|
while (true) {
|
|
|
|
print_thread_info("This thread (with the default name) may run on any core.");
|
|
|
|
std::this_thread::sleep_for(sleep_time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void thread_func()
|
|
|
|
{
|
|
|
|
while (true) {
|
|
|
|
print_thread_info();
|
|
|
|
std::this_thread::sleep_for(sleep_time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
esp_pthread_cfg_t create_config(const char *name, int core_id, int stack, int prio)
|
|
|
|
{
|
|
|
|
auto cfg = esp_pthread_get_default_config();
|
|
|
|
cfg.thread_name = name;
|
|
|
|
cfg.pin_to_core = core_id;
|
|
|
|
cfg.stack_size = stack;
|
|
|
|
cfg.prio = prio;
|
|
|
|
return cfg;
|
|
|
|
}
|
|
|
|
|
2019-07-16 05:33:30 -04:00
|
|
|
extern "C" void app_main(void)
|
2018-11-28 14:40:32 -05:00
|
|
|
{
|
2023-02-08 14:44:54 -05:00
|
|
|
// Create a thread using default values that can run on any core
|
2018-11-28 14:40:32 -05:00
|
|
|
auto cfg = esp_pthread_get_default_config();
|
|
|
|
esp_pthread_set_cfg(&cfg);
|
|
|
|
std::thread any_core(thread_func_any_core);
|
|
|
|
|
|
|
|
// Create a thread on core 0 that spawns another thread, they will both have the same name etc.
|
|
|
|
cfg = create_config("Thread 1", 0, 3 * 1024, 5);
|
|
|
|
cfg.inherit_cfg = true;
|
|
|
|
esp_pthread_set_cfg(&cfg);
|
|
|
|
std::thread thread_1(spawn_another_thread);
|
|
|
|
|
|
|
|
// Create a thread on core 1.
|
|
|
|
cfg = create_config("Thread 2", 1, 3 * 1024, 5);
|
|
|
|
esp_pthread_set_cfg(&cfg);
|
|
|
|
std::thread thread_2(thread_func);
|
|
|
|
|
|
|
|
// Let the main task do something too
|
|
|
|
while (true) {
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "core id: " << xPortGetCoreID()
|
|
|
|
<< ", prio: " << uxTaskPriorityGet(nullptr)
|
|
|
|
<< ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
|
2022-02-08 04:39:38 -05:00
|
|
|
ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str());
|
2018-11-28 14:40:32 -05:00
|
|
|
std::this_thread::sleep_for(sleep_time);
|
|
|
|
}
|
2020-11-10 02:40:01 -05:00
|
|
|
}
|