#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <string>
#include <sstream>
#include <iomanip>
#include "FreeRTOS.h"
#include <esp_log.h>
#include "sdkconfig.h"
static const char* LOG_TAG = "FreeRTOS";
void FreeRTOS::sleep(uint32_t ms) {
::vTaskDelay(ms/portTICK_PERIOD_MS);
}
void FreeRTOS::startTask(void task(void*), std::string taskName, void *param, int stackSize) {
::xTaskCreate(task, taskName.data(), stackSize, param, 5, NULL);
}
void FreeRTOS::deleteTask(TaskHandle_t pTask) {
::vTaskDelete(pTask);
}
uint32_t FreeRTOS::getTimeSinceStart() {
return (uint32_t)(xTaskGetTickCount()*portTICK_PERIOD_MS);
}
uint32_t FreeRTOS::Semaphore::wait(std::string owner) {
ESP_LOGV(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str());
if (m_usePthreads) {
pthread_mutex_lock(&m_pthread_mutex);
} else {
xSemaphoreTake(m_semaphore, portMAX_DELAY);
}
m_owner = owner;
if (m_usePthreads) {
pthread_mutex_unlock(&m_pthread_mutex);
} else {
xSemaphoreGive(m_semaphore);
}
ESP_LOGV(LOG_TAG, "<< wait: Semaphore released: %s", toString().c_str());
m_owner = std::string("<N/A>");
return m_value;
}
FreeRTOS::Semaphore::Semaphore(std::string name) {
m_usePthreads = false;
if (m_usePthreads) {
pthread_mutex_init(&m_pthread_mutex, nullptr);
} else {
m_semaphore = xSemaphoreCreateMutex();
}
m_name = name;
m_owner = std::string("<N/A>");
m_value = 0;
}
FreeRTOS::Semaphore::~Semaphore() {
if (m_usePthreads) {
pthread_mutex_destroy(&m_pthread_mutex);
} else {
vSemaphoreDelete(m_semaphore);
}
}
void FreeRTOS::Semaphore::give() {
ESP_LOGV(LOG_TAG, "Semaphore giving: %s", toString().c_str());
if (m_usePthreads) {
pthread_mutex_unlock(&m_pthread_mutex);
} else {
xSemaphoreGive(m_semaphore);
}
#ifdef ARDUINO_ARCH_ESP32
FreeRTOS::sleep(10);
#endif
m_owner = std::string("<N/A>");
}
void FreeRTOS::Semaphore::give(uint32_t value) {
m_value = value;
give();
}
void FreeRTOS::Semaphore::giveFromISR() {
BaseType_t higherPriorityTaskWoken;
if (m_usePthreads) {
assert(false);
} else {
xSemaphoreGiveFromISR(m_semaphore, &higherPriorityTaskWoken);
}
}
void FreeRTOS::Semaphore::take(std::string owner)
{
ESP_LOGD(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str());
if (m_usePthreads) {
pthread_mutex_lock(&m_pthread_mutex);
} else {
xSemaphoreTake(m_semaphore, portMAX_DELAY);
}
m_owner = owner;
ESP_LOGD(LOG_TAG, "Semaphore taken: %s", toString().c_str());
}
void FreeRTOS::Semaphore::take(uint32_t timeoutMs, std::string owner) {
ESP_LOGV(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str());
if (m_usePthreads) {
assert(false);
} else {
xSemaphoreTake(m_semaphore, timeoutMs/portTICK_PERIOD_MS);
}
m_owner = owner;
ESP_LOGV(LOG_TAG, "Semaphore taken: %s", toString().c_str());
}
std::string FreeRTOS::Semaphore::toString() {
std::stringstream stringStream;
stringStream << "name: "<< m_name << " (0x" << std::hex << std::setfill('0') << (uint32_t)m_semaphore << "), owner: " << m_owner;
return stringStream.str();
}
void FreeRTOS::Semaphore::setName(std::string name) {
m_name = name;
}
Ringbuffer::Ringbuffer(size_t length, ringbuf_type_t type) {
m_handle = ::xRingbufferCreate(length, type);
}
Ringbuffer::~Ringbuffer() {
::vRingbufferDelete(m_handle);
}
void* Ringbuffer::receive(size_t* size, TickType_t wait) {
return ::xRingbufferReceive(m_handle, size, wait);
}
void Ringbuffer::returnItem(void* item) {
::vRingbufferReturnItem(m_handle, item);
}
uint32_t Ringbuffer::send(void* data, size_t length, TickType_t wait) {
return ::xRingbufferSend(m_handle, data, length, wait);
}