C++ refactoring (#91)

This commit is contained in:
Ken Van Hoeylandt
2024-11-26 17:51:05 +01:00
committed by GitHub
parent d06137ba76
commit ca5d4b8226
159 changed files with 904 additions and 1086 deletions
+2 -2
View File
@@ -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)
-20
View File
@@ -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);
-1
View File
@@ -5,7 +5,6 @@
#pragma once
#include <cstdint>
#include <cstdio>
#include <string>
#include <unordered_map>
+25 -46
View File
@@ -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
+26 -53
View File
@@ -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
+6 -6
View File
@@ -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
);
+4
View File
@@ -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;
+36 -74
View File
@@ -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
+38 -36
View File
@@ -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
+26 -47
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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.