Skip to content

Commit 045729d

Browse files
authored
Extend C API for sync::MessageQueue and memory::BlockMemoryPool
2 parents 17de50b + 6318161 commit 045729d

11 files changed

Lines changed: 934 additions & 56 deletions

File tree

Doxyfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ PROJECT_NAME = "SuperTinyKernel™ RTOS"
4848
# could be handy for archiving the generated documentation or if some version
4949
# control system is used.
5050

51-
PROJECT_NUMBER = 1.05.3
51+
PROJECT_NUMBER = 1.06.0
5252

5353
# Using the PROJECT_BRIEF tag one can provide an optional one line description
5454
# for a project that appears at the top of each page and should give viewer a
@@ -910,7 +910,6 @@ WARN_LOGFILE =
910910

911911
INPUT = stk \
912912
interop \
913-
test \
914913
README.md \
915914
@DOXYGEN_INPUT@
916915

build/example/blinky_c/example.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include <stk_config.h>
1111
#include <stk_c.h>
12+
#include <stk_c_time.h>
13+
#include <stk_c_memory.h>
1214
#include "example.h"
1315

1416
#define STACK_SIZE 256

build/example/project/eclipse/x86/blinky_c-mingw32/.project

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@
175175
<type>1</type>
176176
<locationURI>PARENT-6-PROJECT_LOC/interop/c/include/stk_c.h</locationURI>
177177
</link>
178+
<link>
179+
<name>deps/interop/c/include/stk_c_memory.h</name>
180+
<type>1</type>
181+
<locationURI>PARENT-6-PROJECT_LOC/interop/c/include/stk_c_memory.h</locationURI>
182+
</link>
178183
<link>
179184
<name>deps/interop/c/include/stk_c_time.h</name>
180185
<type>1</type>
@@ -185,6 +190,11 @@
185190
<type>1</type>
186191
<locationURI>PARENT-6-PROJECT_LOC/interop/c/src/stk_c.cpp</locationURI>
187192
</link>
193+
<link>
194+
<name>deps/interop/c/src/stk_c_memory.cpp</name>
195+
<type>1</type>
196+
<locationURI>PARENT-6-PROJECT_LOC/interop/c/src/stk_c_memory.cpp</locationURI>
197+
</link>
188198
<link>
189199
<name>deps/interop/c/src/stk_c_sync.cpp</name>
190200
<type>1</type>

interop/c/include/stk_c.h

Lines changed: 179 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
#include <stdbool.h>
1616
#include <assert.h>
1717

18-
/*! \file stk_c.h
19-
\brief C language binding/interface for SuperTinyKernel (STK).
18+
/*! \file stk_c.h
19+
\brief C language binding/interface for SuperTinyKernel (STK).
2020
2121
This header provides a pure C API to create, configure and run STK kernel
2222
from C code.
@@ -122,11 +122,11 @@ typedef void (*stk_task_entry_t)(void *arg);
122122
/* Available kernel type definitions:
123123
124124
Kernel mode flags (may be OR-combined, subject to the constraints listed below):
125-
KERNEL_STATIC fixed task list; tasks must never return from their entry function.
126-
KERNEL_DYNAMIC tasks may be added/removed at runtime and may return when done.
127-
KERNEL_HRT Hard Real-Time mode; must be combined with KERNEL_STATIC or KERNEL_DYNAMIC.
128-
KERNEL_SYNC enables synchronization primitives (Mutex, Event, Semaphore, etc.).
129-
KERNEL_TICKLESS tickless low-power idle; suppresses the SysTick when all tasks sleep.
125+
KERNEL_STATIC - fixed task list; tasks must never return from their entry function.
126+
KERNEL_DYNAMIC - tasks may be added/removed at runtime and may return when done.
127+
KERNEL_HRT - Hard Real-Time mode; must be combined with KERNEL_STATIC or KERNEL_DYNAMIC.
128+
KERNEL_SYNC - enables synchronization primitives (Mutex, Event, Semaphore, etc.).
129+
KERNEL_TICKLESS - tickless low-power idle; suppresses the SysTick when all tasks sleep.
130130
Requires STK_TICKLESS_IDLE=1 in stk_config.h.
131131
INCOMPATIBLE with KERNEL_HRT (HRT requires a continuous tick).
132132
@@ -202,7 +202,7 @@ Kernel<KERNEL_DYNAMIC | KERNEL_TICKLESS | KERNEL_SYNC, STK_C_KERNEL_MAX_TASKS, S
202202
#define STK_C_KERNEL_TYPE_CPU_6 Kernel<KERNEL_STATIC, STK_C_KERNEL_MAX_TASKS, SwitchStrategyRR, PlatformDefault>
203203
#define STK_C_KERNEL_TYPE_CPU_7 Kernel<KERNEL_STATIC, STK_C_KERNEL_MAX_TASKS, SwitchStrategyRR, PlatformDefault>
204204
205-
// Tickless example CPU enters low-power state when all tasks are sleeping:
205+
// Tickless example - CPU enters low-power state when all tasks are sleeping:
206206
#define STK_C_KERNEL_TYPE_CPU_0 Kernel<KERNEL_STATIC | KERNEL_TICKLESS, STK_C_KERNEL_MAX_TASKS, SwitchStrategyRR, PlatformDefault>
207207
\endcode
208208
*/
@@ -307,7 +307,7 @@ void stk_kernel_schedule_task_removal(stk_kernel_t *k, stk_task_t *task);
307307
\param[in] task: Task to suspend.
308308
\param[out] suspended: Set to true if the task was successfully suspended (was awake),
309309
false if the task was already sleeping (e.g. blocked on a mutex or timed Sleep).
310-
\note Do not hold a critical section when suspending the calling task this will deadlock.
310+
\note Do not hold a critical section when suspending the calling task - this will deadlock.
311311
\note If the task suspends itself, the call blocks until the kernel switches it out.
312312
*/
313313
void stk_kernel_suspend_task(stk_kernel_t *k, stk_task_t *task, bool *suspended);
@@ -600,12 +600,12 @@ void stk_tls_set(void *ptr);
600600

601601
// ───── Critical Section ──────────────────────────────────────────────────────
602602

603-
/*! \brief Enter critical section disable context switches on current core.
603+
/*! \brief Enter critical section - disable context switches on current core.
604604
\note Supports nesting (number of enter calls must match number of exit calls).
605605
*/
606606
void stk_critical_section_enter(void);
607607

608-
/*! \brief Leave critical section re-enable context switches.
608+
/*! \brief Leave critical section - re-enable context switches.
609609
\note Must be called once for each previous stk_critical_section_enter().
610610
*/
611611
void stk_critical_section_exit(void);
@@ -1030,6 +1030,174 @@ size_t stk_pipe_read_bulk(stk_pipe_t *pipe, stk_word_t *dst, size_t count, int32
10301030
*/
10311031
size_t stk_pipe_get_size(stk_pipe_t *pipe);
10321032

1033+
// ───── MessageQueue ──────────────────────────────────────────────────────────
1034+
1035+
/*! \brief A memory size (multiples of stk_word_t) required for a MessageQueue instance.
1036+
\details Covers the fixed-overhead fields of stk::sync::MessageQueue:
1037+
six size_t members (buffer ptr, capacity, msg_size, count, head, tail)
1038+
plus two ConditionVariable objects (cv_not_empty, cv_not_full) and
1039+
optional debug-name word.
1040+
\note The backing data buffer is allocated separately by the caller and
1041+
passed to stk_msgq_create() via the \a buf / \a buf_size parameters.
1042+
*/
1043+
#define STK_MSGQ_IMPL_SIZE (6 + (2 * STK_CV_IMPL_SIZE) + (STK_SYNC_DEBUG_NAMES ? 1 : 0))
1044+
1045+
/*! \brief Opaque memory container for a MessageQueue instance.
1046+
*/
1047+
typedef struct stk_msgq_mem_t {
1048+
stk_word_t data[STK_MSGQ_IMPL_SIZE] __stk_c_stack_attr;
1049+
} stk_msgq_mem_t;
1050+
1051+
/*! \brief Opaque handle to a MessageQueue instance.
1052+
*/
1053+
typedef struct stk_msgq_t stk_msgq_t;
1054+
1055+
/*! \def STK_MSGQ_BUF_SIZE(capacity, msg_size)
1056+
\brief Compute the required data-buffer size (in bytes) for a MessageQueue.
1057+
\param[in] capacity: Maximum number of messages.
1058+
\param[in] msg_size: Size of each message in bytes.
1059+
\note Use this macro when declaring the \c uint8_t buffer passed to
1060+
stk_msgq_create():
1061+
\code
1062+
#define MY_QUEUE_CAP 8
1063+
#define MY_MSG_SIZE sizeof(MyMsg_t)
1064+
1065+
static uint8_t s_msgq_buf[STK_MSGQ_BUF_SIZE(MY_QUEUE_CAP, MY_MSG_SIZE)];
1066+
static stk_msgq_mem_t s_msgq_mem;
1067+
stk_msgq_t *g_queue = stk_msgq_create(&s_msgq_mem, sizeof(s_msgq_mem),
1068+
s_msgq_buf, sizeof(s_msgq_buf),
1069+
MY_QUEUE_CAP, MY_MSG_SIZE);
1070+
\endcode
1071+
*/
1072+
#define STK_MSGQ_BUF_SIZE(capacity, msg_size) ((capacity) * (msg_size))
1073+
1074+
/*! \brief Create a MessageQueue (using provided memory).
1075+
\details Constructs a stk::sync::MessageQueue in-place inside \a memory.
1076+
The queue will hold up to \a capacity messages, each \a msg_size bytes
1077+
wide. The backing storage for messages must be supplied by the caller
1078+
via \a buf / \a buf_size.
1079+
1080+
\param[in] memory: Pointer to static memory container for the queue object.
1081+
Must be at least sizeof(stk_msgq_mem_t) bytes.
1082+
\param[in] memory_size: Size of \a memory in bytes (must be >= sizeof(stk_msgq_mem_t)).
1083+
\param[in] buf: Pointer to the message data buffer.
1084+
Must be at least \a capacity * \a msg_size bytes.
1085+
\param[in] buf_size: Size of \a buf in bytes (used only for the safety assertion; must equal
1086+
\a capacity * \a msg_size).
1087+
\param[in] capacity: Maximum number of messages [1, 65534].
1088+
\param[in] msg_size: Size of each individual message in bytes (>= 1).
1089+
\return MessageQueue handle, or NULL if any size assertion fails.
1090+
1091+
\note Convenience macro STK_MSGQ_BUF_SIZE(capacity, msg_size) computes
1092+
the required \a buf_size.
1093+
\note Only available when kernel is compiled with \a KERNEL_SYNC mode enabled.
1094+
*/
1095+
stk_msgq_t *stk_msgq_create(stk_msgq_mem_t *memory,
1096+
uint32_t memory_size,
1097+
uint8_t *buf,
1098+
uint32_t buf_size,
1099+
size_t capacity,
1100+
size_t msg_size);
1101+
1102+
/*! \brief Destroy a MessageQueue.
1103+
\param[in] mq: MessageQueue handle.
1104+
\note Any tasks still blocked on Put/Get at destruction time are considered
1105+
a logic error; an assertion is triggered in debug builds.
1106+
*/
1107+
void stk_msgq_destroy(stk_msgq_t *mq);
1108+
1109+
/*! \brief Put a message into the queue.
1110+
\details Copies \a msg_size bytes from \a msg into the next available slot.
1111+
Blocks if the queue is full until space becomes available or the
1112+
timeout expires.
1113+
\param[in] mq: MessageQueue handle.
1114+
\param[in] msg: Pointer to the message payload (must be >= msg_size bytes).
1115+
\param[in] timeout: Max time to wait (ticks). Use \c STK_WAIT_INFINITE to block
1116+
indefinitely, \c STK_NO_WAIT for a non-blocking attempt.
1117+
\return True if the message was enqueued, False on timeout.
1118+
\warning ISR-safe only with \a timeout = \c STK_NO_WAIT.
1119+
*/
1120+
bool stk_msgq_put(stk_msgq_t *mq, const void *msg, int32_t timeout);
1121+
1122+
/*! \brief Attempt to put a message into the queue without blocking.
1123+
\param[in] mq: MessageQueue handle.
1124+
\param[in] msg: Pointer to the message payload.
1125+
\return True if enqueued, False if the queue was full.
1126+
\warning ISR-safe.
1127+
*/
1128+
bool stk_msgq_tryput(stk_msgq_t *mq, const void *msg);
1129+
1130+
/*! \brief Get a message from the queue.
1131+
\details Copies the oldest message into \a msg. Blocks if the queue is
1132+
empty until a message arrives or the timeout expires.
1133+
\param[in] mq: MessageQueue handle.
1134+
\param[out] msg: Destination buffer (must be >= msg_size bytes).
1135+
\param[in] timeout: Max time to wait (ticks). Use \c STK_WAIT_INFINITE to block
1136+
indefinitely, \c STK_NO_WAIT for a non-blocking attempt.
1137+
\return True if a message was retrieved, False on timeout.
1138+
\warning ISR-safe only with \a timeout = \c STK_NO_WAIT.
1139+
*/
1140+
bool stk_msgq_get(stk_msgq_t *mq, void *msg, int32_t timeout);
1141+
1142+
/*! \brief Attempt to get a message from the queue without blocking.
1143+
\param[in] mq: MessageQueue handle.
1144+
\param[out] msg: Destination buffer.
1145+
\return True if a message was retrieved, False if the queue was empty.
1146+
\warning ISR-safe.
1147+
*/
1148+
bool stk_msgq_tryget(stk_msgq_t *mq, void *msg);
1149+
1150+
/*! \brief Discard all messages and reset the queue to the empty state.
1151+
\details Tasks blocked in Put() are woken so they can re-enqueue into the
1152+
now-empty queue.
1153+
\param[in] mq: MessageQueue handle.
1154+
\warning Messages that were in the queue are silently discarded.
1155+
\warning ISR-safe.
1156+
*/
1157+
void stk_msgq_reset(stk_msgq_t *mq);
1158+
1159+
/*! \brief Get the maximum number of messages the queue can hold.
1160+
\param[in] mq: MessageQueue handle.
1161+
\return Construction-time capacity.
1162+
\note ISR-safe.
1163+
*/
1164+
size_t stk_msgq_get_capacity(const stk_msgq_t *mq);
1165+
1166+
/*! \brief Get the size of each message in bytes.
1167+
\param[in] mq: MessageQueue handle.
1168+
\return Construction-time message size.
1169+
\note ISR-safe.
1170+
*/
1171+
size_t stk_msgq_get_msg_size(const stk_msgq_t *mq);
1172+
1173+
/*! \brief Get the current number of messages waiting in the queue.
1174+
\param[in] mq: MessageQueue handle.
1175+
\return Point-in-time snapshot of the message count.
1176+
\note ISR-safe on targets where a size_t-aligned read is atomic.
1177+
*/
1178+
size_t stk_msgq_get_count(const stk_msgq_t *mq);
1179+
1180+
/*! \brief Get the number of free slots currently available.
1181+
\param[in] mq: MessageQueue handle.
1182+
\return Point-in-time snapshot of the free-slot count.
1183+
\note ISR-safe.
1184+
*/
1185+
size_t stk_msgq_get_space(const stk_msgq_t *mq);
1186+
1187+
/*! \brief Check whether the queue is currently empty.
1188+
\param[in] mq: MessageQueue handle.
1189+
\return True if the queue contains no messages.
1190+
\note ISR-safe.
1191+
*/
1192+
bool stk_msgq_is_empty(const stk_msgq_t *mq);
1193+
1194+
/*! \brief Check whether the queue is currently full.
1195+
\param[in] mq: MessageQueue handle.
1196+
\return True if the queue contains \a capacity messages.
1197+
\note ISR-safe.
1198+
*/
1199+
bool stk_msgq_is_full(const stk_msgq_t *mq);
1200+
10331201
// ───── RWMutex (Reader-Writer Lock) ──────────────────────────────────────────
10341202

10351203
/*! \brief A memory size (multiples of stk_word_t) required for RWMutex instance.

0 commit comments

Comments
 (0)