SuperTinyKernel™ RTOS 1.05.3
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_c.cpp
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#include <cstddef> // for std::size_t
11
12#include <stk_config.h>
13#include <stk.h>
14#include <sync/stk_sync.h>
15#include "stk_c.h"
16
17#define STK_C_TASKS_MAX (STK_C_KERNEL_MAX_TASKS)
18
19inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
20inline void operator delete(void *, void *) noexcept { /* nothing for placement delete */ }
21
22using namespace stk;
23
24class TaskWrapper : public ITask
25{
26public:
27 // ITask
28 EAccessMode GetAccessMode() const { return m_mode; }
29 void OnDeadlineMissed(uint32_t duration) { (void)duration; }
30 int32_t GetWeight() const { return m_weight; }
31 stk_tid_t GetId() const { return m_tid; }
32 const char *GetTraceName() const { return m_tname; }
33
34 // IStackMemory
35 stk_word_t *GetStack() const { return m_stack; }
36 size_t GetStackSize() const { return m_stack_size; }
37 size_t GetStackSizeBytes() const { return m_stack_size * sizeof(stk_word_t); }
38
40 void *user_data,
41 stk_word_t *stack,
42 size_t stack_size,
43 EAccessMode mode)
44 {
45 m_func = func;
46 m_user_data = user_data;
47 m_stack = stack;
48 m_stack_size = stack_size;
49 m_mode = mode;
50 m_weight = 1;
51 }
52
53 void SetWeight(int32_t weight) { m_weight = weight; }
54 void SetId(stk_tid_t tid) { m_tid = tid; }
55 void SetName(const char *tname) { m_tname = tname; }
56
57private:
58 void Run() { m_func(m_user_data); }
59
65 int32_t m_weight;
67 const char *m_tname;
68};
69
74
76{
77 TaskSlot() : busy(false), task()
78 {}
79
80 bool busy;
82};
83
84// Static vars
85static volatile bool s_TaskPoolLock = false;
87
88// ---------------------------------------------------------------------------
89// Helpers
90// ---------------------------------------------------------------------------
91
93 void *arg,
94 stk_word_t *stack,
95 uint32_t stack_size,
96 EAccessMode mode)
97{
98 stk_task_t *task = nullptr;
99
101
102 for (uint32_t i = 0; i < STK_C_TASKS_MAX; ++i)
103 {
104 if (!s_Tasks[i].busy)
105 {
106 s_Tasks[i].busy = true;
107
108 task = &s_Tasks[i].task;
109 task->handle.Initialize(entry, arg, stack, stack_size, mode);
110 break;
111 }
112 }
113
114 STK_ASSERT(task != nullptr);
115 return task;
116}
117
118static void FreeTask(const stk_task_t *task)
119{
121
122 for (uint32_t i = 0; i < STK_C_TASKS_MAX; ++i)
123 {
124 if (s_Tasks[i].busy && (task == &s_Tasks[i].task))
125 {
126 s_Tasks[i].busy = false;
127 return;
128 }
129 }
130
131 STK_ASSERT(false);
132}
133
134// ---------------------------------------------------------------------------
135// C-interface
136// ---------------------------------------------------------------------------
137extern "C" {
138
139// ---------------------------------------------------------------------------
140// Kernel create/destroy wrappers
141// ---------------------------------------------------------------------------
142#define STK_KERNEL_CASE(X) \
143 case X: \
144 { \
145 static_assert(sizeof(STK_C_KERNEL_TYPE_CPU_##X) % sizeof(stk_word_t) == 0, \
146 "Kernel memory size must be multiple of stk_word_t"); \
147 alignas(alignof(STK_C_KERNEL_TYPE_CPU_##X)) /* instead of __stk_c_stack_attr */ \
148 static stk_word_t kernel_##X##_mem[sizeof(STK_C_KERNEL_TYPE_CPU_##X) / sizeof(stk_word_t)]; \
149 IKernel *kernel = new (kernel_##X##_mem) STK_C_KERNEL_TYPE_CPU_##X(); \
150 return reinterpret_cast<stk_kernel_t *>(kernel); \
151 }
152
154{
155 switch (core_nr)
156 {
157#ifdef STK_C_KERNEL_TYPE_CPU_0
159#endif
160#ifdef STK_C_KERNEL_TYPE_CPU_1
162#endif
163#ifdef STK_C_KERNEL_TYPE_CPU_2
165#endif
166#ifdef STK_C_KERNEL_TYPE_CPU_3
168#endif
169#ifdef STK_C_KERNEL_TYPE_CPU_4
171#endif
172#ifdef STK_C_KERNEL_TYPE_CPU_5
174#endif
175#ifdef STK_C_KERNEL_TYPE_CPU_6
177#endif
178#ifdef STK_C_KERNEL_TYPE_CPU_7
180#endif
181 default:
182 return nullptr;
183 }
184}
185
187{
188 STK_ASSERT(k != nullptr);
189
190 reinterpret_cast<IKernel *>(k)->~IKernel();
191}
192
193// ---------------------------------------------------------------------------
194// Kernel control wrappers
195// ---------------------------------------------------------------------------
196void stk_kernel_init(stk_kernel_t *k, uint32_t tick_period_us)
197{
198 STK_ASSERT(k != nullptr);
199
200 reinterpret_cast<stk::IKernel *>(k)->Initialize(tick_period_us);
201}
202
204{
205 STK_ASSERT(k != nullptr);
206
207 reinterpret_cast<stk::IKernel *>(k)->Start();
208}
209
211{
212 STK_ASSERT(k != nullptr);
213
214 return static_cast<EKernelState>(reinterpret_cast<const stk::IKernel *>(k)->GetState());
215}
216
218{
219 STK_ASSERT(k != nullptr);
220
222 reinterpret_cast<stk::IKernel *>(const_cast<stk_kernel_t *>(k))->GetSwitchStrategy());
223}
224
226{
227 STK_ASSERT(k != nullptr);
228 STK_ASSERT(task != nullptr);
229
230 reinterpret_cast<stk::IKernel *>(k)->AddTask(&task->handle);
231}
232
234{
235 STK_ASSERT(k != nullptr);
236 STK_ASSERT(task != nullptr);
237
238 reinterpret_cast<stk::IKernel *>(k)->RemoveTask(&task->handle);
239}
240
242 stk_task_t *task,
243 int32_t periodicity_ticks,
244 int32_t deadline_ticks,
245 int32_t start_delay_ticks)
246{
247 STK_ASSERT(k != nullptr);
248 STK_ASSERT(task != nullptr);
249
250 reinterpret_cast<stk::IKernel *>(k)->AddTask(
251 &task->handle,
252 periodicity_ticks,
253 deadline_ticks,
254 start_delay_ticks);
255}
256
257// ---------------------------------------------------------------------------
258// Task creation
259// ---------------------------------------------------------------------------
261 void *arg,
262 stk_word_t *stack,
263 uint32_t stack_size)
264{
265 STK_ASSERT(entry != nullptr);
266 STK_ASSERT(stack != nullptr);
267 STK_ASSERT(stack_size != 0);
268
269 return reinterpret_cast<stk_task_t *>(AllocateTask(entry, arg, stack, stack_size, ACCESS_PRIVILEGED));
270}
271
273 void *arg,
274 stk_word_t *stack,
275 uint32_t stack_size)
276{
277 STK_ASSERT(entry != nullptr);
278 STK_ASSERT(stack != nullptr);
279 STK_ASSERT(stack_size != 0);
280
281 return reinterpret_cast<stk_task_t *>(AllocateTask(entry, arg, stack, stack_size, ACCESS_USER));
282}
283
284void stk_task_set_weight(stk_task_t *task, uint32_t weight)
285{
286 STK_ASSERT(task != nullptr);
287 STK_ASSERT(weight != 0);
288
289 task->handle.SetWeight(weight);
290}
291
292void stk_task_set_priority(stk_task_t *task, uint8_t priority)
293{
294 STK_ASSERT(priority <= 31);
295
296 stk_task_set_weight(task, priority);
297}
298
299void stk_task_set_id(stk_task_t *task, uint32_t tid)
300{
301 STK_ASSERT(task != nullptr);
302
303 task->handle.SetId(tid);
304}
305
306void stk_task_set_name(stk_task_t *task, const char *tname)
307{
308 STK_ASSERT(task != nullptr);
309
310 task->handle.SetName(tname);
311}
312
314{
315 STK_ASSERT(task != nullptr);
316
317 FreeTask(task);
318}
319
320// ---------------------------------------------------------------------------
321// Kernel services (available inside tasks)
322// ---------------------------------------------------------------------------
323stk_tid_t stk_tid(void) { return stk::GetTid(); }
324int64_t stk_ticks(void) { return stk::GetTicks(); }
326int64_t stk_time_now_ms(void) { return stk::GetTimeNowMs(); }
327int64_t stk_ticks_from_ms(int64_t msec) { return stk_ticks_from_ms_r(msec, stk::GetTickResolution()); }
328void stk_delay(uint32_t ticks) { stk::Delay(ticks); }
329void stk_sleep(uint32_t ticks) { stk::Sleep(ticks); }
330void stk_delay_ms(uint32_t ms) { stk::DelayMs(ms); }
331void stk_sleep_ms(uint32_t ms) { stk::SleepMs(ms); }
332void stk_sleep_until(int64_t ts) { stk::SleepUntil(ts); }
333void stk_yield(void) { stk::Yield(); }
334
335// ---------------------------------------------------------------------------
336// Thread-Local Storage (TLS) API
337// ---------------------------------------------------------------------------
338void *stk_tls_get(void)
339{
340 return hw::GetTlsPtr<void *>();
341}
342
343void stk_tls_set(void *ptr)
344{
345 hw::SetTlsPtr(ptr);
346}
347
348// ---------------------------------------------------------------------------
349// Critical Section - Manual Enter/Exit
350// ---------------------------------------------------------------------------
355
360
361} // extern "C"
Top-level STK include. Provides the Kernel class template and all built-in task-switching strategies.
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:330
Collection of synchronization primitives (stk::sync namespace).
C language binding/interface for SuperTinyKernel (STK).
static volatile bool s_TaskPoolLock
Definition stk_c.cpp:85
static stk_task_t * AllocateTask(stk_task_entry_t entry, void *arg, stk_word_t *stack, uint32_t stack_size, EAccessMode mode)
Definition stk_c.cpp:92
#define STK_KERNEL_CASE(X)
Definition stk_c.cpp:142
static void FreeTask(const stk_task_t *task)
Definition stk_c.cpp:118
static TaskSlot s_Tasks[(STK_C_KERNEL_MAX_TASKS)]
Definition stk_c.cpp:86
#define STK_C_TASKS_MAX
Definition stk_c.cpp:17
stk_task_t * stk_task_create_user(stk_task_entry_t entry, void *arg, stk_word_t *stack, uint32_t stack_size)
Create user-mode task.
Definition stk_c.cpp:272
void stk_kernel_add_task(stk_kernel_t *k, stk_task_t *task)
Add task to non-HRT kernel (static or dynamic).
Definition stk_c.cpp:225
void stk_delay(uint32_t ticks)
Busy-wait delay (other tasks continue to run).
Definition stk_c.cpp:328
stk_tid_t stk_tid(void)
Returns current task/thread ID (the value set by stk_task_set_id).
Definition stk_c.cpp:323
void * stk_tls_get(void)
Get thread-local pointer (platform-specific slot).
Definition stk_c.cpp:338
void stk_kernel_remove_task(stk_kernel_t *k, stk_task_t *task)
Remove finished task from dynamic kernel.
Definition stk_c.cpp:233
void stk_kernel_destroy(stk_kernel_t *k)
Destroy dynamic kernel instance (only when not running).
Definition stk_c.cpp:186
struct stk_kernel_t stk_kernel_t
Opaque handle to a kernel instance.
Definition stk_c.h:91
int64_t stk_time_now_ms(void)
Returns current time in milliseconds since kernel start.
Definition stk_c.cpp:326
void stk_task_set_weight(stk_task_t *task, uint32_t weight)
Set task weight (used only by Smooth Weighted Round Robin).
Definition stk_c.cpp:284
void stk_yield(void)
Voluntarily give up CPU to another ready task (cooperative yield).
Definition stk_c.cpp:333
void stk_sleep(uint32_t ticks)
Put current task to sleep (non-HRT kernels only).
Definition stk_c.cpp:329
void stk_kernel_start(stk_kernel_t *k)
Start the scheduler - never returns.
Definition stk_c.cpp:203
void stk_task_set_id(stk_task_t *task, uint32_t tid)
Assign application-defined task ID (for tracing/debugging).
Definition stk_c.cpp:299
void stk_task_destroy(stk_task_t *task)
Destroy dynamically created task object.
Definition stk_c.cpp:313
int64_t stk_ticks_from_ms(int64_t msec)
Get ticks from milliseconds using current kernel tick resolution.
Definition stk_c.cpp:327
void stk_critical_section_exit(void)
Leave critical section — re-enable context switches.
Definition stk_c.cpp:356
EKernelState stk_kernel_get_state(const stk_kernel_t *k)
Get state of the scheduler.
Definition stk_c.cpp:210
int32_t stk_tick_resolution(void)
Returns how many microseconds correspond to one kernel tick.
Definition stk_c.cpp:325
void stk_kernel_init(stk_kernel_t *k, uint32_t tick_period_us)
Initialize kernel with given tick period.
Definition stk_c.cpp:196
void stk_task_set_name(stk_task_t *task, const char *tname)
Assign human-readable task name (for tracing/debugging).
Definition stk_c.cpp:306
void(* stk_task_entry_t)(void *arg)
Task entry point function type.
Definition stk_c.h:108
int64_t stk_ticks(void)
Returns number of ticks elapsed since kernel start.
Definition stk_c.cpp:324
void stk_sleep_until(int64_t ts)
Put current task to sleep (non-HRT kernels only).
Definition stk_c.cpp:332
void stk_tls_set(void *ptr)
Set thread-local pointer.
Definition stk_c.cpp:343
stk_task_t * stk_task_create_privileged(stk_task_entry_t entry, void *arg, stk_word_t *stack, uint32_t stack_size)
Create privileged-mode (kernel-mode) task.
Definition stk_c.cpp:260
stk_word_t stk_tid_t
Task id.
Definition stk_c.h:87
enum _EKernelState EKernelState
Kernel state.
stk_kernel_t * stk_kernel_create(uint8_t core_nr)
Create kernel.
Definition stk_c.cpp:153
uintptr_t stk_word_t
CPU register type.
Definition stk_c.h:83
void stk_delay_ms(uint32_t ms)
Busy-wait delay (other tasks continue to run).
Definition stk_c.cpp:330
void stk_sleep_ms(uint32_t ms)
Put current task to sleep (non-HRT kernels only).
Definition stk_c.cpp:331
void stk_critical_section_enter(void)
Enter critical section — disable context switches on current core.
Definition stk_c.cpp:351
void stk_kernel_add_task_hrt(stk_kernel_t *k, stk_task_t *task, int32_t periodicity_ticks, int32_t deadline_ticks, int32_t start_delay_ticks)
Add task with HRT timing parameters (HRT kernels only).
Definition stk_c.cpp:241
void stk_task_set_priority(stk_task_t *task, uint8_t priority)
Set task priority (used only by Fixed Priority scheduler).
Definition stk_c.cpp:292
static int64_t stk_ticks_from_ms_r(int64_t msec, int32_t resolution)
Get ticks from milliseconds using an explicit tick resolution.
Definition stk_c.h:378
bool stk_kernel_is_schedulable(const stk_kernel_t *k)
Test whether currently configured task set is schedulable.
Definition stk_c.cpp:217
Namespace of STK package.
static int64_t GetTimeNowMs()
Get current time in milliseconds since kernel start.
Definition stk_helper.h:281
void Sleep(uint32_t ticks)
Put calling process into a sleep state.
Definition stk_helper.h:298
static void DelayMs(uint32_t ms)
Delay calling process by busy-waiting until the deadline expires.
Definition stk_helper.h:353
Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:248
void Yield()
Notify scheduler to switch to the next runnable task.
Definition stk_helper.h:331
void Delay(uint32_t ticks)
Delay calling process by busy-waiting until the deadline expires.
Definition stk_helper.h:342
void SleepUntil(Ticks timestamp)
Put calling process into a sleep state until the specified timestamp.
Definition stk_helper.h:322
TId GetTid()
Get task/thread Id of the calling task.
Definition stk_helper.h:217
int32_t GetTickResolution()
Get number of microseconds in one tick.
Definition stk_helper.h:258
static void SleepMs(uint32_t ms)
Put calling process into a sleep state.
Definition stk_helper.h:311
EAccessMode
Hardware access mode by the user task.
Definition stk_common.h:31
@ ACCESS_USER
Unprivileged access mode (access to some hardware is restricted, see CPU manual for details).
Definition stk_common.h:32
@ ACCESS_PRIVILEGED
Privileged access mode (access to hardware is fully unrestricted).
Definition stk_common.h:33
__stk_forceinline void SetTlsPtr(const _TyTls *tp)
Type-safe wrapper around SetTls() that stores a typed pointer as the raw TP value.
Definition stk_arch.h:170
__stk_forceinline _TyTls * GetTlsPtr()
Type-safe wrapper around GetTls() that casts the raw TP value to a typed pointer.
Definition stk_arch.h:158
static void Exit()
Exit a critical section.
Definition stktest.cpp:78
static void Enter()
Enter a critical section.
Definition stktest.cpp:74
Interface for a user task.
Definition stk_common.h:433
Interface for the implementation of the kernel of the scheduler. It supports Soft and Hard Real-Time ...
Definition stk_common.h:854
virtual EState GetState() const =0
Get a snapshot of the kernel state.
static SchedulabilityCheckResult< _TaskCount > IsSchedulableWCRT(const ITaskSwitchStrategy *strategy)
Perform WCRT schedulability analysis on the task set registered with strategy.
RAII-style low-level synchronization primitive for atomic code execution. Used as building brick for ...
Definition stk_sync_cs.h:54
stk_word_t * m_stack
Definition stk_c.cpp:62
void SetId(stk_tid_t tid)
Definition stk_c.cpp:54
void SetName(const char *tname)
Definition stk_c.cpp:55
const char * m_tname
Definition stk_c.cpp:67
size_t GetStackSizeBytes() const
Get size of the memory in bytes.
Definition stk_c.cpp:37
EAccessMode GetAccessMode() const
Get hardware access mode of the user task.
Definition stk_c.cpp:28
void Run()
Entry point of the user task.
Definition stk_c.cpp:58
stk_task_entry_t m_func
Definition stk_c.cpp:60
EAccessMode m_mode
Definition stk_c.cpp:64
size_t m_stack_size
Definition stk_c.cpp:63
int32_t GetWeight() const
Get static base weight of the task.
Definition stk_c.cpp:30
void * m_user_data
Definition stk_c.cpp:61
int32_t m_weight
Definition stk_c.cpp:65
const char * GetTraceName() const
Get task trace name set by application.
Definition stk_c.cpp:32
stk_word_t * GetStack() const
Get pointer to the stack memory.
Definition stk_c.cpp:35
size_t GetStackSize() const
Get number of elements of the stack memory array.
Definition stk_c.cpp:36
void Initialize(stk_task_entry_t func, void *user_data, stk_word_t *stack, size_t stack_size, EAccessMode mode)
Definition stk_c.cpp:39
stk_tid_t GetId() const
Get task Id set by application.
Definition stk_c.cpp:31
void OnDeadlineMissed(uint32_t duration)
Called by the scheduler if deadline of the task is missed when Kernel is operating in Hard Real-Time ...
Definition stk_c.cpp:29
void SetWeight(int32_t weight)
Definition stk_c.cpp:53
stk_tid_t m_tid
Definition stk_c.cpp:66
TaskWrapper handle
Definition stk_c.cpp:72
stk_task_t task
Definition stk_c.cpp:81
TaskSlot()
Definition stk_c.cpp:77
bool busy
Definition stk_c.cpp:80