C++ refactoring (#91)
This commit is contained in:
committed by
GitHub
parent
d06137ba76
commit
ca5d4b8226
@@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.16)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
file(GLOB SOURCES "Source/*.c*")
|
||||
file(GLOB HEADERS "Source/*.h*")
|
||||
file(GLOB_RECURSE SOURCES "Source/*.c*")
|
||||
file(GLOB_RECURSE HEADERS "Source/*.h*")
|
||||
|
||||
add_library(TactilityCore OBJECT)
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "EventFlag.h"
|
||||
|
||||
typedef tt::EventFlag* ApiLock;
|
||||
|
||||
#define TT_API_LOCK_EVENT (1U << 0)
|
||||
|
||||
#define tt_api_lock_alloc_locked() tt::event_flag_alloc()
|
||||
|
||||
#define tt_api_lock_wait_unlock(_lock) \
|
||||
tt::event_flag_wait(_lock, TT_API_LOCK_EVENT, tt::TtFlagWaitAny, tt::TtWaitForever)
|
||||
|
||||
#define tt_api_lock_free(_lock) tt::event_flag_free(_lock)
|
||||
|
||||
#define tt_api_lock_unlock(_lock) tt::event_flag_set(_lock, TT_API_LOCK_EVENT)
|
||||
|
||||
#define tt_api_lock_wait_unlock_and_free(_lock) \
|
||||
tt_api_lock_wait_unlock(_lock); \
|
||||
tt_api_lock_free(_lock);
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
@@ -3,68 +3,54 @@
|
||||
#include "Check.h"
|
||||
#include "CoreDefines.h"
|
||||
|
||||
#ifdef ESP_TARGET
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "event_groups.h"
|
||||
#endif
|
||||
|
||||
#define TT_EVENT_FLAG_MAX_BITS_EVENT_GROUPS 24U
|
||||
#define TT_EVENT_FLAG_INVALID_BITS (~((1UL << TT_EVENT_FLAG_MAX_BITS_EVENT_GROUPS) - 1U))
|
||||
|
||||
namespace tt {
|
||||
|
||||
EventFlag* event_flag_alloc() {
|
||||
EventFlag::EventFlag() {
|
||||
tt_assert(!TT_IS_IRQ_MODE());
|
||||
|
||||
EventGroupHandle_t handle = xEventGroupCreate();
|
||||
handle = xEventGroupCreate();
|
||||
tt_check(handle);
|
||||
|
||||
return static_cast<EventFlag*>(handle);
|
||||
}
|
||||
|
||||
void event_flag_free(EventFlag* instance) {
|
||||
EventFlag::~EventFlag() {
|
||||
tt_assert(!TT_IS_IRQ_MODE());
|
||||
vEventGroupDelete((EventGroupHandle_t)instance);
|
||||
vEventGroupDelete(handle);
|
||||
}
|
||||
|
||||
uint32_t event_flag_set(EventFlag* instance, uint32_t flags) {
|
||||
tt_assert(instance);
|
||||
uint32_t EventFlag::set(uint32_t flags) const {
|
||||
tt_assert(handle);
|
||||
tt_assert((flags & TT_EVENT_FLAG_INVALID_BITS) == 0U);
|
||||
|
||||
auto hEventGroup = static_cast<EventGroupHandle_t>(instance);
|
||||
uint32_t rflags;
|
||||
BaseType_t yield;
|
||||
|
||||
if (TT_IS_IRQ_MODE()) {
|
||||
yield = pdFALSE;
|
||||
if (xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
|
||||
if (xEventGroupSetBitsFromISR(handle, (EventBits_t)flags, &yield) == pdFAIL) {
|
||||
rflags = (uint32_t)TtFlagErrorResource;
|
||||
} else {
|
||||
rflags = flags;
|
||||
portYIELD_FROM_ISR(yield);
|
||||
}
|
||||
} else {
|
||||
rflags = xEventGroupSetBits(hEventGroup, (EventBits_t)flags);
|
||||
rflags = xEventGroupSetBits(handle, (EventBits_t)flags);
|
||||
}
|
||||
|
||||
/* Return event flags after setting */
|
||||
return (rflags);
|
||||
return rflags;
|
||||
}
|
||||
|
||||
uint32_t event_flag_clear(EventFlag* instance, uint32_t flags) {
|
||||
tt_assert(instance);
|
||||
uint32_t EventFlag::clear(uint32_t flags) const {
|
||||
tt_assert((flags & TT_EVENT_FLAG_INVALID_BITS) == 0U);
|
||||
|
||||
auto hEventGroup = static_cast<EventGroupHandle_t>(instance);
|
||||
uint32_t rflags;
|
||||
|
||||
if (TT_IS_IRQ_MODE()) {
|
||||
rflags = xEventGroupGetBitsFromISR(hEventGroup);
|
||||
rflags = xEventGroupGetBitsFromISR(handle);
|
||||
|
||||
if (xEventGroupClearBitsFromISR(hEventGroup, (EventBits_t)flags) == pdFAIL) {
|
||||
if (xEventGroupClearBitsFromISR(handle, (EventBits_t)flags) == pdFAIL) {
|
||||
rflags = (uint32_t)TtStatusErrorResource;
|
||||
} else {
|
||||
/* xEventGroupClearBitsFromISR only registers clear operation in the timer command queue. */
|
||||
@@ -73,42 +59,36 @@ uint32_t event_flag_clear(EventFlag* instance, uint32_t flags) {
|
||||
portYIELD_FROM_ISR(pdTRUE);
|
||||
}
|
||||
} else {
|
||||
rflags = xEventGroupClearBits(hEventGroup, (EventBits_t)flags);
|
||||
rflags = xEventGroupClearBits(handle, (EventBits_t)flags);
|
||||
}
|
||||
|
||||
/* Return event flags before clearing */
|
||||
return (rflags);
|
||||
return rflags;
|
||||
}
|
||||
|
||||
uint32_t event_flag_get(EventFlag* instance) {
|
||||
tt_assert(instance);
|
||||
|
||||
auto hEventGroup = static_cast<EventGroupHandle_t>(instance);
|
||||
uint32_t EventFlag::get() const {
|
||||
uint32_t rflags;
|
||||
|
||||
if (TT_IS_IRQ_MODE()) {
|
||||
rflags = xEventGroupGetBitsFromISR(hEventGroup);
|
||||
rflags = xEventGroupGetBitsFromISR(handle);
|
||||
} else {
|
||||
rflags = xEventGroupGetBits(hEventGroup);
|
||||
rflags = xEventGroupGetBits(handle);
|
||||
}
|
||||
|
||||
/* Return current event flags */
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
uint32_t event_flag_wait(
|
||||
EventFlag* instance,
|
||||
uint32_t EventFlag::wait(
|
||||
uint32_t flags,
|
||||
uint32_t options,
|
||||
uint32_t timeout
|
||||
) {
|
||||
) const {
|
||||
tt_assert(!TT_IS_IRQ_MODE());
|
||||
tt_assert(instance);
|
||||
tt_assert((flags & TT_EVENT_FLAG_INVALID_BITS) == 0U);
|
||||
|
||||
auto hEventGroup = static_cast<EventGroupHandle_t>(instance);
|
||||
BaseType_t wait_all;
|
||||
BaseType_t exit_clr;
|
||||
BaseType_t exit_clear;
|
||||
uint32_t rflags;
|
||||
|
||||
if (options & TtFlagWaitAll) {
|
||||
@@ -118,15 +98,15 @@ uint32_t event_flag_wait(
|
||||
}
|
||||
|
||||
if (options & TtFlagNoClear) {
|
||||
exit_clr = pdFAIL;
|
||||
exit_clear = pdFAIL;
|
||||
} else {
|
||||
exit_clr = pdTRUE;
|
||||
exit_clear = pdTRUE;
|
||||
}
|
||||
|
||||
rflags = xEventGroupWaitBits(
|
||||
hEventGroup,
|
||||
handle,
|
||||
(EventBits_t)flags,
|
||||
exit_clr,
|
||||
exit_clear,
|
||||
wait_all,
|
||||
(TickType_t)timeout
|
||||
);
|
||||
@@ -149,8 +129,7 @@ uint32_t event_flag_wait(
|
||||
}
|
||||
}
|
||||
|
||||
/* Return event flags before clearing */
|
||||
return (rflags);
|
||||
return rflags;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -2,62 +2,35 @@
|
||||
|
||||
#include "CoreTypes.h"
|
||||
|
||||
#ifdef ESP_TARGET
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "event_groups.h"
|
||||
#endif
|
||||
|
||||
namespace tt {
|
||||
|
||||
typedef void EventFlag;
|
||||
#define TT_API_LOCK_EVENT (1U << 0)
|
||||
|
||||
/** Allocate EventFlag
|
||||
*
|
||||
* @return pointer to EventFlag
|
||||
/**
|
||||
* Wrapper for FreeRTOS xEventGroup.
|
||||
*/
|
||||
EventFlag* event_flag_alloc();
|
||||
|
||||
/** Deallocate EventFlag
|
||||
*
|
||||
* @param instance pointer to EventFlag
|
||||
*/
|
||||
void event_flag_free(EventFlag* instance);
|
||||
|
||||
/** Set flags
|
||||
*
|
||||
* @param instance pointer to EventFlag
|
||||
* @param[in] flags The flags
|
||||
*
|
||||
* @return Resulting flags or error (TtStatus)
|
||||
*/
|
||||
uint32_t event_flag_set(EventFlag* instance, uint32_t flags);
|
||||
|
||||
/** Clear flags
|
||||
*
|
||||
* @param instance pointer to EventFlag
|
||||
* @param[in] flags The flags
|
||||
*
|
||||
* @return Resulting flags or error (TtStatus)
|
||||
*/
|
||||
uint32_t event_flag_clear(EventFlag* instance, uint32_t flags);
|
||||
|
||||
/** Get flags
|
||||
*
|
||||
* @param instance pointer to EventFlag
|
||||
*
|
||||
* @return Resulting flags
|
||||
*/
|
||||
uint32_t event_flag_get(EventFlag* instance);
|
||||
|
||||
/** Wait flags
|
||||
*
|
||||
* @param instance pointer to EventFlag
|
||||
* @param[in] flags The flags
|
||||
* @param[in] options The option flags
|
||||
* @param[in] timeout The timeout
|
||||
*
|
||||
* @return Resulting flags or error (TtStatus)
|
||||
*/
|
||||
uint32_t event_flag_wait(
|
||||
EventFlag* instance,
|
||||
uint32_t flags,
|
||||
uint32_t options,
|
||||
uint32_t timeout
|
||||
);
|
||||
class EventFlag {
|
||||
private:
|
||||
EventGroupHandle_t handle;
|
||||
public:
|
||||
EventFlag();
|
||||
~EventFlag();
|
||||
uint32_t set(uint32_t flags) const;
|
||||
uint32_t clear(uint32_t flags) const;
|
||||
uint32_t get() const;
|
||||
uint32_t wait(
|
||||
uint32_t flags,
|
||||
uint32_t options = TtFlagWaitAny,
|
||||
uint32_t timeout = TtWaitForever
|
||||
) const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace tt {
|
||||
|
||||
static char loglevel_to_prefix(LogLevel level) {
|
||||
static char toPrefix(LogLevel level) {
|
||||
switch (level) {
|
||||
case LogLevelError:
|
||||
return 'E';
|
||||
@@ -29,7 +29,7 @@ static char loglevel_to_prefix(LogLevel level) {
|
||||
}
|
||||
}
|
||||
|
||||
static const char* loglevel_to_colour(LogLevel level) {
|
||||
static const char* toColour(LogLevel level) {
|
||||
switch (level) {
|
||||
case LogLevelError:
|
||||
return "\033[1;31m";
|
||||
@@ -46,7 +46,7 @@ static const char* loglevel_to_colour(LogLevel level) {
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t log_timestamp() {
|
||||
static uint64_t getTimestamp() {
|
||||
#ifdef ESP_PLATFORM
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
|
||||
return clock() / CLOCKS_PER_SEC * 1000;
|
||||
@@ -73,9 +73,9 @@ uint64_t log_timestamp() {
|
||||
void log(LogLevel level, const char* tag, const char* format, ...) {
|
||||
printf(
|
||||
"%s%c (%lu) %s: ",
|
||||
loglevel_to_colour(level),
|
||||
loglevel_to_prefix(level),
|
||||
log_timestamp(),
|
||||
toColour(level),
|
||||
toPrefix(level),
|
||||
getTimestamp(),
|
||||
tag
|
||||
);
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ typedef enum {
|
||||
MutexTypeRecursive,
|
||||
} MutexType;
|
||||
|
||||
/**
|
||||
* Wrapper for FreeRTOS xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex
|
||||
* Can be used in IRQ mode (within ISR context)
|
||||
*/
|
||||
class Mutex {
|
||||
private:
|
||||
SemaphoreHandle_t semaphore;
|
||||
|
||||
@@ -2,127 +2,89 @@
|
||||
#include "Check.h"
|
||||
#include "CoreDefines.h"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#endif
|
||||
|
||||
namespace tt {
|
||||
|
||||
Semaphore* tt_semaphore_alloc(uint32_t max_count, uint32_t initial_count) {
|
||||
Semaphore::Semaphore(uint32_t maxCount, uint32_t initialCount) {
|
||||
tt_assert(!TT_IS_IRQ_MODE());
|
||||
tt_assert((max_count > 0U) && (initial_count <= max_count));
|
||||
tt_assert((maxCount > 0U) && (initialCount <= maxCount));
|
||||
|
||||
SemaphoreHandle_t hSemaphore = nullptr;
|
||||
if (max_count == 1U) {
|
||||
hSemaphore = xSemaphoreCreateBinary();
|
||||
if ((hSemaphore != nullptr) && (initial_count != 0U)) {
|
||||
if (xSemaphoreGive(hSemaphore) != pdPASS) {
|
||||
vSemaphoreDelete(hSemaphore);
|
||||
hSemaphore = nullptr;
|
||||
if (maxCount == 1U) {
|
||||
handle = xSemaphoreCreateBinary();
|
||||
if ((handle != nullptr) && (initialCount != 0U)) {
|
||||
if (xSemaphoreGive(handle) != pdPASS) {
|
||||
vSemaphoreDelete(handle);
|
||||
handle = nullptr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hSemaphore = xSemaphoreCreateCounting(max_count, initial_count);
|
||||
handle = xSemaphoreCreateCounting(maxCount, initialCount);
|
||||
}
|
||||
|
||||
tt_check(hSemaphore);
|
||||
|
||||
return (Semaphore*)hSemaphore;
|
||||
tt_check(handle);
|
||||
}
|
||||
|
||||
void tt_semaphore_free(Semaphore* instance) {
|
||||
tt_assert(instance);
|
||||
Semaphore::~Semaphore() {
|
||||
tt_assert(!TT_IS_IRQ_MODE());
|
||||
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
|
||||
|
||||
vSemaphoreDelete(hSemaphore);
|
||||
vSemaphoreDelete(handle);
|
||||
}
|
||||
|
||||
TtStatus tt_semaphore_acquire(Semaphore* instance, uint32_t timeout) {
|
||||
tt_assert(instance);
|
||||
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
|
||||
TtStatus status;
|
||||
BaseType_t yield;
|
||||
|
||||
status = TtStatusOk;
|
||||
|
||||
TtStatus Semaphore::acquire(uint32_t timeout) const {
|
||||
if (TT_IS_IRQ_MODE()) {
|
||||
if (timeout != 0U) {
|
||||
status = TtStatusErrorParameter;
|
||||
return TtStatusErrorParameter;
|
||||
} else {
|
||||
yield = pdFALSE;
|
||||
BaseType_t yield = pdFALSE;
|
||||
|
||||
if (xSemaphoreTakeFromISR(hSemaphore, &yield) != pdPASS) {
|
||||
status = TtStatusErrorResource;
|
||||
if (xSemaphoreTakeFromISR(handle, &yield) != pdPASS) {
|
||||
return TtStatusErrorResource;
|
||||
} else {
|
||||
portYIELD_FROM_ISR(yield);
|
||||
return TtStatusOk;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (xSemaphoreTake(hSemaphore, (TickType_t)timeout) != pdPASS) {
|
||||
if (xSemaphoreTake(handle, (TickType_t)timeout) != pdPASS) {
|
||||
if (timeout != 0U) {
|
||||
status = TtStatusErrorTimeout;
|
||||
return TtStatusErrorTimeout;
|
||||
} else {
|
||||
status = TtStatusErrorResource;
|
||||
return TtStatusErrorResource;
|
||||
}
|
||||
} else {
|
||||
return TtStatusOk;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
TtStatus tt_semaphore_release(Semaphore* instance) {
|
||||
tt_assert(instance);
|
||||
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
|
||||
TtStatus stat;
|
||||
BaseType_t yield;
|
||||
|
||||
stat = TtStatusOk;
|
||||
|
||||
TtStatus Semaphore::release() const {
|
||||
if (TT_IS_IRQ_MODE()) {
|
||||
yield = pdFALSE;
|
||||
BaseType_t yield = pdFALSE;
|
||||
|
||||
if (xSemaphoreGiveFromISR(hSemaphore, &yield) != pdTRUE) {
|
||||
stat = TtStatusErrorResource;
|
||||
if (xSemaphoreGiveFromISR(handle, &yield) != pdTRUE) {
|
||||
return TtStatusErrorResource;
|
||||
} else {
|
||||
portYIELD_FROM_ISR(yield);
|
||||
return TtStatusOk;
|
||||
}
|
||||
} else {
|
||||
if (xSemaphoreGive(hSemaphore) != pdPASS) {
|
||||
stat = TtStatusErrorResource;
|
||||
if (xSemaphoreGive(handle) != pdPASS) {
|
||||
return TtStatusErrorResource;
|
||||
} else {
|
||||
return TtStatusOk;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return execution status */
|
||||
return (stat);
|
||||
}
|
||||
|
||||
uint32_t tt_semaphore_get_count(Semaphore* instance) {
|
||||
tt_assert(instance);
|
||||
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
|
||||
uint32_t count;
|
||||
|
||||
uint32_t Semaphore::getCount() const {
|
||||
if (TT_IS_IRQ_MODE()) {
|
||||
// TODO: uxSemaphoreGetCountFromISR is not supported on esp-idf 5.1.2 - perhaps later on?
|
||||
#ifdef uxSemaphoreGetCountFromISR
|
||||
count = (uint32_t)uxSemaphoreGetCountFromISR(hSemaphore);
|
||||
return uxSemaphoreGetCountFromISR(handle);
|
||||
#else
|
||||
count = (uint32_t)uxQueueMessagesWaitingFromISR((QueueHandle_t)hSemaphore);
|
||||
return uxQueueMessagesWaitingFromISR((QueueHandle_t)hSemaphore);
|
||||
#endif
|
||||
} else {
|
||||
count = (uint32_t)uxSemaphoreGetCount(hSemaphore);
|
||||
return uxSemaphoreGetCount(handle);
|
||||
}
|
||||
|
||||
/* Return number of tokens */
|
||||
return (count);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -3,48 +3,50 @@
|
||||
#include "CoreTypes.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#endif
|
||||
|
||||
namespace tt {
|
||||
|
||||
typedef void Semaphore;
|
||||
|
||||
/** Allocate semaphore
|
||||
*
|
||||
* @param[in] max_count The maximum count
|
||||
* @param[in] initial_count The initial count
|
||||
*
|
||||
* @return pointer to Semaphore instance
|
||||
/**
|
||||
* Wrapper for xSemaphoreCreateBinary (max count == 1) and xSemaphoreCreateCounting (max count > 1)
|
||||
* Can be used in IRQ mode (within ISR context)
|
||||
*/
|
||||
Semaphore* tt_semaphore_alloc(uint32_t max_count, uint32_t initial_count);
|
||||
class Semaphore {
|
||||
private:
|
||||
SemaphoreHandle_t handle;
|
||||
public:
|
||||
/**
|
||||
* @param[in] maxCount The maximum count
|
||||
* @param[in] initialCount The initial count
|
||||
*/
|
||||
Semaphore(uint32_t maxCount, uint32_t initialCount);
|
||||
|
||||
/** Free semaphore
|
||||
*
|
||||
* @param instance The pointer to Semaphore instance
|
||||
*/
|
||||
void tt_semaphore_free(Semaphore* instance);
|
||||
/**
|
||||
* @param instance The pointer to Semaphore instance
|
||||
*/
|
||||
~Semaphore();
|
||||
|
||||
/** Acquire semaphore
|
||||
*
|
||||
* @param instance The pointer to Semaphore instance
|
||||
* @param[in] timeout The timeout
|
||||
*
|
||||
* @return The status.
|
||||
*/
|
||||
TtStatus tt_semaphore_acquire(Semaphore* instance, uint32_t timeout);
|
||||
/** Acquire semaphore
|
||||
* @param[in] timeout The timeout
|
||||
* @return the status
|
||||
*/
|
||||
TtStatus acquire(uint32_t timeout) const;
|
||||
|
||||
/** Release semaphore
|
||||
*
|
||||
* @param instance The pointer to Semaphore instance
|
||||
*
|
||||
* @return The status.
|
||||
*/
|
||||
TtStatus tt_semaphore_release(Semaphore* instance);
|
||||
/** Release semaphore
|
||||
* @return the status
|
||||
*/
|
||||
TtStatus release() const;
|
||||
|
||||
/** Get semaphore count
|
||||
*
|
||||
* @param instance The pointer to Semaphore instance
|
||||
*
|
||||
* @return Semaphore count
|
||||
*/
|
||||
uint32_t tt_semaphore_get_count(Semaphore* instance);
|
||||
/** Get semaphore count
|
||||
* @return semaphore count
|
||||
*/
|
||||
uint32_t getCount() const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -4,91 +4,70 @@
|
||||
#include "CoreDefines.h"
|
||||
#include "CoreTypes.h"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/stream_buffer.h"
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "stream_buffer.h"
|
||||
#endif
|
||||
|
||||
namespace tt {
|
||||
|
||||
StreamBuffer* stream_buffer_alloc(size_t size, size_t trigger_level) {
|
||||
StreamBuffer::StreamBuffer(size_t size, size_t triggerLevel) {
|
||||
tt_assert(size != 0);
|
||||
|
||||
StreamBufferHandle_t handle = xStreamBufferCreate(size, trigger_level);
|
||||
handle = xStreamBufferCreate(size, triggerLevel);
|
||||
tt_check(handle);
|
||||
|
||||
return handle;
|
||||
};
|
||||
|
||||
void stream_buffer_free(StreamBuffer* stream_buffer) {
|
||||
tt_assert(stream_buffer);
|
||||
vStreamBufferDelete((StreamBufferHandle_t)stream_buffer);
|
||||
StreamBuffer::~StreamBuffer() {
|
||||
vStreamBufferDelete(handle);
|
||||
};
|
||||
|
||||
bool stream_set_trigger_level(StreamBuffer* stream_buffer, size_t trigger_level) {
|
||||
tt_assert(stream_buffer);
|
||||
return xStreamBufferSetTriggerLevel((StreamBufferHandle_t)stream_buffer, trigger_level) == pdTRUE;
|
||||
bool StreamBuffer::setTriggerLevel(size_t triggerLevel) const {
|
||||
return xStreamBufferSetTriggerLevel(handle, triggerLevel) == pdTRUE;
|
||||
};
|
||||
|
||||
size_t stream_buffer_send(
|
||||
StreamBuffer* stream_buffer,
|
||||
size_t StreamBuffer::send(
|
||||
const void* data,
|
||||
size_t length,
|
||||
uint32_t timeout
|
||||
) {
|
||||
size_t ret;
|
||||
|
||||
) const {
|
||||
if (TT_IS_IRQ_MODE()) {
|
||||
BaseType_t yield;
|
||||
ret = xStreamBufferSendFromISR((StreamBufferHandle_t)stream_buffer, data, length, &yield);
|
||||
size_t result = xStreamBufferSendFromISR(handle, data, length, &yield);
|
||||
portYIELD_FROM_ISR(yield);
|
||||
return result;
|
||||
} else {
|
||||
ret = xStreamBufferSend((StreamBufferHandle_t)stream_buffer, data, length, timeout);
|
||||
return xStreamBufferSend(handle, data, length, timeout);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
size_t stream_buffer_receive(
|
||||
StreamBuffer* stream_buffer,
|
||||
size_t StreamBuffer::receive(
|
||||
void* data,
|
||||
size_t length,
|
||||
uint32_t timeout
|
||||
) {
|
||||
size_t ret;
|
||||
|
||||
) const {
|
||||
if (TT_IS_IRQ_MODE()) {
|
||||
BaseType_t yield;
|
||||
ret = xStreamBufferReceiveFromISR((StreamBufferHandle_t)stream_buffer, data, length, &yield);
|
||||
size_t result = xStreamBufferReceiveFromISR(handle, data, length, &yield);
|
||||
portYIELD_FROM_ISR(yield);
|
||||
return result;
|
||||
} else {
|
||||
ret = xStreamBufferReceive((StreamBufferHandle_t)stream_buffer, data, length, timeout);
|
||||
return xStreamBufferReceive(handle, data, length, timeout);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t stream_buffer_bytes_available(StreamBuffer* stream_buffer) {
|
||||
return xStreamBufferBytesAvailable((StreamBufferHandle_t)stream_buffer);
|
||||
size_t StreamBuffer::getAvailableReadBytes() const {
|
||||
return xStreamBufferBytesAvailable(handle);
|
||||
};
|
||||
|
||||
size_t stream_buffer_spaces_available(StreamBuffer* stream_buffer) {
|
||||
return xStreamBufferSpacesAvailable((StreamBufferHandle_t)stream_buffer);
|
||||
size_t StreamBuffer::getAvailableWriteBytes() const {
|
||||
return xStreamBufferSpacesAvailable(handle);
|
||||
};
|
||||
|
||||
bool stream_buffer_is_full(StreamBuffer* stream_buffer) {
|
||||
return xStreamBufferIsFull((StreamBufferHandle_t)stream_buffer) == pdTRUE;
|
||||
bool StreamBuffer::isFull() const {
|
||||
return xStreamBufferIsFull(handle) == pdTRUE;
|
||||
};
|
||||
|
||||
bool stream_buffer_is_empty(StreamBuffer* stream_buffer) {
|
||||
return (xStreamBufferIsEmpty((StreamBufferHandle_t)stream_buffer) == pdTRUE);
|
||||
bool StreamBuffer::isEmpty() const {
|
||||
return xStreamBufferIsEmpty(handle) == pdTRUE;
|
||||
};
|
||||
|
||||
TtStatus stream_buffer_reset(StreamBuffer* stream_buffer) {
|
||||
if (xStreamBufferReset((StreamBufferHandle_t)stream_buffer) == pdPASS) {
|
||||
TtStatus StreamBuffer::reset() const {
|
||||
if (xStreamBufferReset(handle) == pdPASS) {
|
||||
return TtStatusOk;
|
||||
} else {
|
||||
return TtStatusError;
|
||||
|
||||
+125
-129
@@ -1,152 +1,148 @@
|
||||
/**
|
||||
* @file stream_buffer.h
|
||||
* Tactility stream buffer primitive.
|
||||
*
|
||||
* Stream buffers are used to send a continuous stream of data from one task or
|
||||
* interrupt to another. Their implementation is light weight, making them
|
||||
* particularly suited for interrupt to task and core to core communication
|
||||
* scenarios.
|
||||
*
|
||||
* ***NOTE***: Stream buffer implementation assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader).
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/stream_buffer.h"
|
||||
#else
|
||||
#include "FreeRTOS.h"
|
||||
#include "stream_buffer.h"
|
||||
#endif
|
||||
|
||||
namespace tt {
|
||||
|
||||
typedef void StreamBuffer;
|
||||
|
||||
/**
|
||||
* @brief Allocate stream buffer instance.
|
||||
* Stream buffer implementation assumes there is only one task or
|
||||
* Stream buffers are used to send a continuous stream of data from one task or
|
||||
* interrupt to another. Their implementation is light weight, making them
|
||||
* particularly suited for interrupt to task and core to core communication
|
||||
* scenarios.
|
||||
*
|
||||
* **NOTE**: Stream buffer implementation assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader).
|
||||
*
|
||||
* @param size The total number of bytes the stream buffer will be able to hold at any one time.
|
||||
* @param trigger_level The number of bytes that must be in the stream buffer
|
||||
* before a task that is blocked on the stream buffer to wait for data is moved out of the blocked state.
|
||||
* @return The stream buffer instance.
|
||||
*/
|
||||
StreamBuffer* stream_buffer_alloc(size_t size, size_t trigger_level);
|
||||
class StreamBuffer {
|
||||
private:
|
||||
StreamBufferHandle_t handle;
|
||||
|
||||
/**
|
||||
* @brief Free stream buffer instance
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance.
|
||||
*/
|
||||
void stream_buffer_free(StreamBuffer* stream_buffer);
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Set trigger level for stream buffer.
|
||||
* A stream buffer's trigger level is the number of bytes that must be in the
|
||||
* stream buffer before a task that is blocked on the stream buffer to
|
||||
* wait for data is moved out of the blocked state.
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance
|
||||
* @param trigger_level The new trigger level for the stream buffer.
|
||||
* @return true if trigger level can be be updated (new trigger level was less than or equal to the stream buffer's length).
|
||||
* @return false if trigger level can't be be updated (new trigger level was greater than the stream buffer's length).
|
||||
*/
|
||||
bool stream_set_trigger_level(StreamBuffer* stream_buffer, size_t trigger_level);
|
||||
/**
|
||||
* Stream buffer implementation assumes there is only one task or
|
||||
* interrupt that will write to the buffer (the writer), and only one task or
|
||||
* interrupt that will read from the buffer (the reader).
|
||||
*
|
||||
* @param size The total number of bytes the stream buffer will be able to hold at any one time.
|
||||
* @param triggerLevel The number of bytes that must be in the stream buffer
|
||||
* before a task that is blocked on the stream buffer to wait for data is moved out of the blocked state.
|
||||
* @return The stream buffer instance.
|
||||
*/
|
||||
StreamBuffer(size_t size, size_t triggerLevel);
|
||||
|
||||
/**
|
||||
* @brief Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
|
||||
* Wakes up task waiting for data to become available if called from ISR.
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance.
|
||||
* @param data A pointer to the data that is to be copied into the stream buffer.
|
||||
* @param length The maximum number of bytes to copy from data into the stream buffer.
|
||||
* @param timeout The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for space to become available if the stream buffer is full.
|
||||
* Will return immediately if timeout is zero.
|
||||
* Setting timeout to TtWaitForever will cause the task to wait indefinitely.
|
||||
* Ignored if called from ISR.
|
||||
* @return The number of bytes actually written to the stream buffer.
|
||||
*/
|
||||
size_t stream_buffer_send(
|
||||
StreamBuffer* stream_buffer,
|
||||
const void* data,
|
||||
size_t length,
|
||||
uint32_t timeout
|
||||
);
|
||||
~StreamBuffer();
|
||||
|
||||
/**
|
||||
* @brief Receives bytes from a stream buffer.
|
||||
* Wakes up task waiting for space to become available if called from ISR.
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance.
|
||||
* @param data A pointer to the buffer into which the received bytes will be
|
||||
* copied.
|
||||
* @param length The length of the buffer pointed to by the data parameter.
|
||||
* @param timeout The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for data to become available if the stream buffer is empty.
|
||||
* Will return immediately if timeout is zero.
|
||||
* Setting timeout to TtWaitForever will cause the task to wait indefinitely.
|
||||
* Ignored if called from ISR.
|
||||
* @return The number of bytes read from the stream buffer, if any.
|
||||
*/
|
||||
size_t stream_buffer_receive(
|
||||
StreamBuffer* stream_buffer,
|
||||
void* data,
|
||||
size_t length,
|
||||
uint32_t timeout
|
||||
);
|
||||
/**
|
||||
* @brief Set trigger level for stream buffer.
|
||||
* A stream buffer's trigger level is the number of bytes that must be in the
|
||||
* stream buffer before a task that is blocked on the stream buffer to
|
||||
* wait for data is moved out of the blocked state.
|
||||
*
|
||||
* @param triggerLevel The new trigger level for the stream buffer.
|
||||
* @return true if trigger level can be be updated (new trigger level was less than or equal to the stream buffer's length).
|
||||
* @return false if trigger level can't be be updated (new trigger level was greater than the stream buffer's length).
|
||||
*/
|
||||
[[nodiscard]] bool setTriggerLevel(size_t triggerLevel) const;
|
||||
|
||||
/**
|
||||
* @brief Queries a stream buffer to see how much data it contains, which is equal to
|
||||
* the number of bytes that can be read from the stream buffer before the stream
|
||||
* buffer would be empty.
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance.
|
||||
* @return The number of bytes that can be read from the stream buffer before
|
||||
* the stream buffer would be empty.
|
||||
*/
|
||||
size_t stream_buffer_bytes_available(StreamBuffer* stream_buffer);
|
||||
/**
|
||||
* @brief Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
|
||||
* Wakes up task waiting for data to become available if called from ISR.
|
||||
*
|
||||
* @param data A pointer to the data that is to be copied into the stream buffer.
|
||||
* @param length The maximum number of bytes to copy from data into the stream buffer.
|
||||
* @param timeout The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for space to become available if the stream buffer is full.
|
||||
* Will return immediately if timeout is zero.
|
||||
* Setting timeout to TtWaitForever will cause the task to wait indefinitely.
|
||||
* Ignored if called from ISR.
|
||||
* @return The number of bytes actually written to the stream buffer.
|
||||
*/
|
||||
[[nodiscard]] size_t send(
|
||||
const void* data,
|
||||
size_t length,
|
||||
uint32_t timeout
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Queries a stream buffer to see how much free space it contains, which is
|
||||
* equal to the amount of data that can be sent to the stream buffer before it
|
||||
* is full.
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance.
|
||||
* @return The number of bytes that can be written to the stream buffer before
|
||||
* the stream buffer would be full.
|
||||
*/
|
||||
size_t stream_buffer_spaces_available(StreamBuffer* stream_buffer);
|
||||
/**
|
||||
* @brief Receives bytes from a stream buffer.
|
||||
* Wakes up task waiting for space to become available if called from ISR.
|
||||
*
|
||||
* @param data A pointer to the buffer into which the received bytes will be
|
||||
* copied.
|
||||
* @param length The length of the buffer pointed to by the data parameter.
|
||||
* @param timeout The maximum amount of time the task should remain in the
|
||||
* Blocked state to wait for data to become available if the stream buffer is empty.
|
||||
* Will return immediately if timeout is zero.
|
||||
* Setting timeout to TtWaitForever will cause the task to wait indefinitely.
|
||||
* Ignored if called from ISR.
|
||||
* @return The number of bytes read from the stream buffer, if any.
|
||||
*/
|
||||
[[nodiscard]] size_t receive(
|
||||
void* data,
|
||||
size_t length,
|
||||
uint32_t timeout
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Queries a stream buffer to see if it is full.
|
||||
*
|
||||
* @param stream_buffer stream buffer instance.
|
||||
* @return true if the stream buffer is full.
|
||||
* @return false if the stream buffer is not full.
|
||||
*/
|
||||
bool stream_buffer_is_full(StreamBuffer* stream_buffer);
|
||||
/**
|
||||
* @brief Queries a stream buffer to see how much data it contains, which is equal to
|
||||
* the number of bytes that can be read from the stream buffer before the stream
|
||||
* buffer would be empty.
|
||||
*
|
||||
* @return The number of bytes that can be read from the stream buffer before
|
||||
* the stream buffer would be empty.
|
||||
*/
|
||||
[[nodiscard]] size_t getAvailableReadBytes() const;
|
||||
|
||||
/**
|
||||
* @brief Queries a stream buffer to see if it is empty.
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance.
|
||||
* @return true if the stream buffer is empty.
|
||||
* @return false if the stream buffer is not empty.
|
||||
*/
|
||||
bool tt_stream_buffer_is_empty(StreamBuffer* stream_buffer);
|
||||
/**
|
||||
* @brief Queries a stream buffer to see how much free space it contains, which is
|
||||
* equal to the amount of data that can be sent to the stream buffer before it
|
||||
* is full.
|
||||
*
|
||||
* @return The number of bytes that can be written to the stream buffer before
|
||||
* the stream buffer would be full.
|
||||
*/
|
||||
[[nodiscard]] size_t getAvailableWriteBytes() const;
|
||||
|
||||
/**
|
||||
* @brief Queries a stream buffer to see if it is full.
|
||||
*
|
||||
* @return true if the stream buffer is full.
|
||||
* @return false if the stream buffer is not full.
|
||||
*/
|
||||
[[nodiscard]] bool isFull() const;
|
||||
|
||||
/**
|
||||
* @brief Queries a stream buffer to see if it is empty.
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance.
|
||||
* @return true if the stream buffer is empty.
|
||||
* @return false if the stream buffer is not empty.
|
||||
*/
|
||||
[[nodiscard]] bool isEmpty() const;
|
||||
|
||||
/**
|
||||
* @brief Resets a stream buffer to its initial, empty, state. Any data that was
|
||||
* in the stream buffer is discarded. A stream buffer can only be reset if there
|
||||
* are no tasks blocked waiting to either send to or receive from the stream buffer.
|
||||
*
|
||||
* @return TtStatusOk if the stream buffer is reset.
|
||||
* @return TtStatusError if there was a task blocked waiting to send to or read
|
||||
* from the stream buffer then the stream buffer is not reset.
|
||||
*/
|
||||
[[nodiscard]] TtStatus reset() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Resets a stream buffer to its initial, empty, state. Any data that was
|
||||
* in the stream buffer is discarded. A stream buffer can only be reset if there
|
||||
* are no tasks blocked waiting to either send to or receive from the stream buffer.
|
||||
*
|
||||
* @param stream_buffer The stream buffer instance.
|
||||
* @return TtStatusOk if the stream buffer is reset.
|
||||
* @return TtStatusError if there was a task blocked waiting to send to or read
|
||||
* from the stream buffer then the stream buffer is not reset.
|
||||
*/
|
||||
TtStatus tt_stream_buffer_reset(StreamBuffer* stream_buffer);
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "CoreDefines.h"
|
||||
#include "CoreExtraDefines.h"
|
||||
#include "CoreTypes.h"
|
||||
#include "Critical.h"
|
||||
#include "critical/Critical.h"
|
||||
#include "EventFlag.h"
|
||||
#include "Kernel.h"
|
||||
#include "Log.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "Hash.h"
|
||||
|
||||
namespace tt::hash {
|
||||
namespace tt::crypt {
|
||||
|
||||
uint32_t djb2(const char* str) {
|
||||
uint32_t hash = 5381;
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace tt::hash {
|
||||
namespace tt::crypt {
|
||||
|
||||
/**
|
||||
* Implementation of DJB2 hashing algorithm.
|
||||
Reference in New Issue
Block a user