SuperTinyKernel™ RTOS 1.08.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_defs.h
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#ifndef STK_DEFS_H_
11#define STK_DEFS_H_
12
13#include <cstddef>
14#include <cstdint>
15#include <algorithm>
16#ifdef __ICCARM__
17 #include <intrinsics.h>
18 #if (__IAR_SYSTEMS_ICC__ < 8)
19 #error "Only IAR EWARM 8.0 and higher is supported by STK."
20 #endif
21#endif
22
29#include "stk_config.h"
30
42#ifndef STK_TICKLESS_IDLE
43 #define STK_TICKLESS_IDLE (0)
44#endif
45
50#ifndef STK_STRICT_COMPLIANCY
51 #define STK_STRICT_COMPLIANCY (0)
52#endif
53
62#ifndef STK_TICKLESS_USE_ARM_DWT
63 #define STK_TICKLESS_USE_ARM_DWT (1)
64#endif
65
76#ifndef STK_TICKLESS_TICKS_MAX
77 #define STK_TICKLESS_TICKS_MAX (1000)
78#endif
79#if STK_TICKLESS_TICKS_MAX > 100000
80 #error "STK_TICKLESS_TICKS_MAX is too large: cpu_ticks_requested may overflow uint32_t."
81#endif
82
98#ifndef STK_TLS
99 #define STK_TLS (0)
100#endif
101
128#ifndef STK_TLS_PREFER_REGISTER
129 #ifdef _STK_ARCH_RISC_V
130 #define STK_TLS_PREFER_REGISTER (1)
131 #else
132 #define STK_TLS_PREFER_REGISTER (0)
133 #endif
134#endif
135
139#ifndef STK_MPU
140 #define STK_MPU (0)
141#endif
142
146#ifndef STK_MPU_STACK_GUARD
147 #define STK_MPU_STACK_GUARD (0)
148#endif
149
162#ifndef STK_MPU_TASK_REGIONS
163 #define STK_MPU_TASK_REGIONS (2)
164#endif
165
166#if STK_MPU_STACK_GUARD && (STK_MPU_TASK_REGIONS != 2) && (STK_MPU_TASK_REGIONS != 4)
167 #error "STK_MPU_TASK_REGIONS must be defined as 2 or 4"
168#endif
169
179#if STK_SEGGER_SYSVIEW || STK_MPU_STACK_GUARD
180 #ifndef STK_STACK_NEEDS_TASK_ID
181 #define STK_STACK_NEEDS_TASK_ID (1)
182 #endif
183#endif
184
192#if !defined(STK_SYNC_DEBUG_NAMES) && STK_SEGGER_SYSVIEW
193 #define STK_SYNC_DEBUG_NAMES (1)
194#elif !defined(STK_SYNC_DEBUG_NAMES)
195 #define STK_SYNC_DEBUG_NAMES (0)
196#endif
197
201#if !STK_STRICT_COMPLIANCY
202 #define STK_VIRT_DTOR
203#else
204 #define STK_VIRT_DTOR virtual
205#endif
206
213#if defined(__GNUC__) || defined(__ICCARM__)
214 #define __stk_forceinline __attribute__((always_inline)) inline
215#elif defined(_MSC_VER)
216 #define __stk_forceinline __forceinline
217#else
218 #define __stk_forceinline inline
219#endif
220
227#if defined(__GNUC__) || defined(__ICCARM__)
228 #define __stk_aligned(x) __attribute__((aligned(x)))
229#else
230 #define __stk_aligned(x)
231#endif
232
238#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) || defined(__CC_ARM) || defined(__ARMCC_VERSION)
239 #define __stk_weak __attribute__((weak))
240#else
241 #define __stk_weak
242#endif
243
251#if defined(__GNUC__) || defined(__ICCARM__)
252 #define __stk_attr_naked __attribute__((naked))
253#else
254 #define __stk_attr_naked
255#endif
256
262#if defined(__GNUC__) || defined(__ICCARM__)
263 #define __stk_attr_noreturn __attribute__((__noreturn__))
264#else
265 #define __stk_attr_noreturn
266#endif
267
273#if defined(__GNUC__) || defined(__ICCARM__)
274 #define __stk_attr_unused __attribute__((unused))
275#else
276 #define __stk_attr_unused
277#endif
278
284#if defined(__GNUC__) || defined(__ICCARM__)
285 #define __stk_attr_used __attribute__((used))
286#else
287 #define __stk_attr_used
288#endif
289
295#if defined(__GNUC__) || defined(__ICCARM__)
296 #define __stk_attr_noinline __attribute__((noinline))
297#else
298 #define __stk_attr_noinline
299#endif
300
306#if defined(__GNUC__) || defined(__ICCARM__)
307 #define __stk_attr_deprecated __attribute__((deprecated))
308#elif defined(_MSC_VER)
309 #define __stk_attr_deprecated __declspec(deprecated)
310#else
311 #define __stk_attr_deprecated
312#endif
313
319#if defined(__GNUC__) || defined(__clang__)
320 static __stk_forceinline void __stk_full_memfence() { __sync_synchronize(); }
321#elif defined(__ICCARM__)
322 static __stk_forceinline void __stk_full_memfence() { __DMB(); }
323#elif defined(_MSC_VER)
324 static __stk_forceinline void __stk_full_memfence() { __stk_dmb(); }
325#else
326 #error "__stk_full_memfence() is not implemented for this compiler. Add a definition to stk_defs.h."
327#endif
328
337#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
338 static __stk_forceinline void __stk_compiler_barrier() { __asm volatile("" ::: "memory"); }
339#elif defined(_MSC_VER)
340 static __stk_forceinline void __stk_compiler_barrier() { _ReadWriteBarrier(); }
341#else
342 #error "__stk_compiler_barrier() is not implemented for this compiler. Add a definition to stk_defs.h."
343#endif
344
360#ifndef __stk_relax_cpu
361#if defined(__GNUC__) || defined(__clang__)
362 #if defined(__i386__) || defined(__x86_64__)
363 static __stk_forceinline void __stk_relax_cpu() { __builtin_ia32_pause(); }
364 #elif defined(__riscv)
365 #ifdef __riscv_zihintpause
366 static __stk_forceinline void __stk_relax_cpu() { __builtin_riscv_pause(); }
367 #else
368 static __stk_forceinline void __stk_relax_cpu() { __asm volatile("nop" ::: "memory"); }
369 #endif
370 #elif defined(__ARM_ARCH) || defined(_STK_ARCH_ARM_CORTEX_M)
371 static __stk_forceinline void __stk_relax_cpu() { __asm volatile("yield" ::: "memory"); }
372 #else
373 static __stk_forceinline void __stk_relax_cpu() { __asm volatile("" ::: "memory"); }
374 #endif
375#elif defined(__ICCARM__)
376 static __stk_forceinline void __stk_relax_cpu() { __asm volatile("YIELD"); }
377#elif defined(_MSC_VER)
378 #include <intrin.h>
379 #if defined(_M_IX86) || defined(_M_X64)
380 static __stk_forceinline void __stk_relax_cpu() { _mm_pause(); }
381 #elif defined(_M_ARM) || defined(_M_ARM64)
382 static __stk_forceinline void __stk_relax_cpu() { __yield(); }
383 #else
384 static __stk_forceinline void __stk_relax_cpu() { __stk_full_memfence(); }
385 #endif
386#else
387 #error "__stk_relax_cpu() is not implemented for this compiler. Add a definition to stk_defs.h."
388#endif
389#endif
390
405#if defined(DEBUG) || defined(_DEBUG)
406 #if defined(_STK_ARCH_ARM_CORTEX_M)
407 static __stk_forceinline void __stk_debug_break() { __asm volatile("bkpt 0"); }
408 #elif defined(_STK_ARCH_RISC_V)
409 static __stk_forceinline void __stk_debug_break() { __asm volatile("ebreak"); }
410 #elif defined(_STK_ARCH_X86_WIN32)
411 #ifdef _MSC_VER
412 static __stk_forceinline void __stk_debug_break() { __debugbreak(); }
413 #else
414 static __stk_forceinline void __stk_debug_break() { __asm volatile("int $3"); }
415 #endif
416 #endif
417#else
419#endif
420
425#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))
426 #define __stk_constexpr_cpp17 constexpr
427#else
428 #define __stk_constexpr_cpp17
429#endif
430
447#ifdef _STK_ASSERT_REDIRECT
448 extern void STK_ASSERT_HANDLER(const char *, const char *, int32_t);
449 #define STK_ASSERT(e) ((e) ? (void)0 : STK_ASSERT_HANDLER(#e, __FILE__, __LINE__))
450#else
451 #if defined(DEBUG) || defined(_DEBUG)
452 #include <cassert>
453 #define STK_ASSERT(e) assert(e)
454 #else
455 #define STK_ASSERT(e)
456 #endif
457#endif
458
467#define STK_STATIC_ASSERT_DESC_N(NAME, X, DESC) static_assert((X), DESC)
468
475#define STK_STATIC_ASSERT_DESC(X, DESC) STK_STATIC_ASSERT_DESC_N(_, X, DESC)
476
484#define STK_STATIC_ASSERT_N(NAME, X) STK_STATIC_ASSERT_DESC_N(N, (X), #X)
485
492#define STK_STATIC_ASSERT(X) STK_STATIC_ASSERT_DESC_N(_, (X), #X)
493
501#ifndef STK_STACK_MEMORY_FILLER
502 #define STK_STACK_MEMORY_FILLER (static_cast<stk::Word>((sizeof(stk::Word) <= 4U) ? 0xDEADBEEFU : 0xDEADBEEFDEADBEEFULL))
503#endif
504
508#ifndef STK_STACK_MEMORY_ALIGN
509 #if defined(__riscv)
510 #define STK_STACK_MEMORY_ALIGN (16U)
511 #elif defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
512 #define STK_STACK_MEMORY_ALIGN (8U)
513 #else // ARM, others
514 #define STK_STACK_MEMORY_ALIGN (4U)
515 #endif
516#endif
517
528#ifndef STK_CS_NESTINGS_MAX
529 #define STK_CS_NESTINGS_MAX (16U)
530#endif
531
538#ifndef STK_ARCH_CPU_COUNT
539 #define STK_ARCH_CPU_COUNT (1U)
540#endif
541
557#ifndef STK_STACK_SIZE_MIN
558 #ifdef __riscv
559 #if defined(__riscv_32e) && (__riscv_32e == 1)
560 // RISC-V RV32E (Embedded): Small 16-register file.
561 #if !defined(__riscv_flen) || (__riscv_flen == 0)
562 #define STK_STACK_SIZE_MIN (32U)
563 #else
564 // FPU present: Requires additional space for 32 FP registers.
565 #define STK_STACK_SIZE_MIN (32U + (__riscv_flen * 2))
566 #endif
567 #else
568 // Standard RISC-V (RV32I/RV64I): Large 32-register file.
569 // Higher minimum to prevent memory corruption on platforms like RP2350.
570 #if !defined(__riscv_flen) || (__riscv_flen == 0)
571 #define STK_STACK_SIZE_MIN (256U)
572 #else
573 // Standard RISC-V with FPU: Maximum frame allocation.
574 #define STK_STACK_SIZE_MIN (512U + (__riscv_flen * 2))
575 #endif
576 #endif
577 #else
578 // ARM Cortex-M and other architectures
579 #define STK_STACK_SIZE_MIN (32U)
580 #endif
581#endif
582
591#ifndef STK_SLEEP_TRAP_STACK_SIZE
592 #define STK_SLEEP_TRAP_STACK_SIZE (STK_STACK_SIZE_MIN)
593#endif
594
606template <size_t MODE, size_t FLAG, size_t ONTRUE, size_t ONFALSE>
608{
609#if defined(_MSC_VER) || defined(__ICCARM__)
610 // MSVC and IAR builds may over-allocate when the flag is not set to avoid compile errors.
611 static constexpr size_t Value = ((ONTRUE > ONFALSE) ? ONTRUE : ONFALSE);
612#else
613 // GCC and Clang support zero-sized array extensions natively.
614 static constexpr size_t Value = (((MODE & FLAG) != 0U) ? ONTRUE : ONFALSE);
615#endif
616};
617
628#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
629 #define STK_ENDIAN_IDX_HI (0U) // big-endian: high word at index 0
630 #define STK_ENDIAN_IDX_LO (1U) // big-endian: low word at index 1
631#else
632 #define STK_ENDIAN_IDX_HI (1U) // little-endian (default): high word at index 1
633 #define STK_ENDIAN_IDX_LO (0U) // little-endian (default): low word at index 0
634#endif
635
647#define STK_NONCOPYABLE_CLASS(TYPE)\
648 TYPE(const TYPE &) = delete;\
649 TYPE &operator=(const TYPE &) = delete;
650
654#define STK_UNUSED(X) static_cast<void>((X))
655
665#if __cplusplus >= 202002L
666 #define STK_LIKELY(x) ([&]() { if (!!(x)) [[likely]] { return true; } else { return false; } }())
667 #define STK_UNLIKELY(x) ([&]() { if (!!(x)) { return true; } else [[unlikely]] { return false; } }())
668#elif defined(__GNUC__) || defined(__clang__)
669 #define STK_LIKELY(x) __builtin_expect(!!(x), 1)
670 #define STK_UNLIKELY(x) __builtin_expect(!!(x), 0)
671#else
672 #define STK_LIKELY(x) (x)
673 #define STK_UNLIKELY(x) (x)
674#endif
675
681#define STK_STATIC_ARRAY_SIZE(ARRAY) static_cast<size_t>(sizeof(ARRAY) / sizeof(ARRAY[0]))
682
686namespace stk {
687
691template <typename T>
692static constexpr T Min(T a, T b) noexcept { return ((a < b) ? a : b); }
693
697template <typename T>
698static constexpr T Max(T a, T b) noexcept { return ((a > b) ? a : b); }
699
703template <typename T>
704static constexpr T Align(T v, T align) noexcept
705{
706 return ((v + align - static_cast<T>(1U)) / align) * align;
707}
708
712template <typename T>
713static constexpr T AlignPow2(T v, T align) noexcept
714{
715 return (v + align - static_cast<T>(1U)) & ~(align - static_cast<T>(1U));
716}
717
722static __stk_forceinline uint32_t CountLeadingZeros(const uint32_t value) noexcept
723{
724 uint32_t ret_val;
725 uint32_t temp_val = value;
726
727#if defined(__GNUC__) || defined(__clang__)
728 ret_val = static_cast<uint32_t>(__builtin_clz(temp_val));
729#elif defined(__ICCARM__)
730 ret_val = static_cast<uint32_t>(__CLZ(temp_val));
731#else
732 uint32_t count = 0U;
733
734 // note: binary search requires temp_val > 0 to resolve to a max of 31 leading zeros safely
735 if (temp_val <= 0x0000FFFFU) { count += 16U; temp_val = temp_val << 16U; } else { }
736 if (temp_val <= 0x00FFFFFFU) { count += 8U; temp_val = temp_val << 8U; } else { }
737 if (temp_val <= 0x0FFFFFFFU) { count += 4U; temp_val = temp_val << 4U; } else { }
738 if (temp_val <= 0x3FFFFFFFU) { count += 2U; temp_val = temp_val << 2U; } else { }
739 if (temp_val <= 0x7FFFFFFFU) { count += 1U; } else { }
740
741 ret_val = count;
742#endif
743
744 return ret_val;
745}
746
751namespace util {}
752
753} // namespace stk
754
758#ifndef _STK_CUSTOM_MEMCPY
759static void STK_MEMCPY(void *const dest, const void *const src, const size_t size);
760#endif
761
765#ifndef _STK_CUSTOM_MEMSET
766static void STK_MEMSET(void *const dest, const uint8_t value, const size_t size);
767#endif
768
769#endif /* STK_DEFS_H_ */
static void __stk_dmb()
Hardware memory barrier: ensures visibility across cores and bus masters.
#define __stk_forceinline
Forces compiler to always inline the decorated function, regardless of optimisation level.
Definition stk_defs.h:218
static void STK_MEMCPY(void *const dest, const void *const src, const size_t size)
A wrapper for a built-in memcpy, redefine to your own if required.
static void STK_MEMSET(void *const dest, const uint8_t value, const size_t size)
A wrapper for a built-in memset, redefine to your own if required.
static void __stk_debug_break()
Definition stk_defs.h:418
Namespace of STK package.
static uint32_t CountLeadingZeros(const uint32_t value) noexcept
Count leading zeros.
Definition stk_defs.h:722
static constexpr T AlignPow2(T v, T align) noexcept
Fast compile-time alignment for power-of-two boundaries.
Definition stk_defs.h:713
static constexpr T Align(T v, T align) noexcept
Aligns a value towards the next larger size multiple.
Definition stk_defs.h:704
static constexpr T Max(T a, T b) noexcept
Compile-time maximum of two values.
Definition stk_defs.h:698
static constexpr T Min(T a, T b) noexcept
Compile-time minimum of two values.
Definition stk_defs.h:692
Internal utility namespace containing data structure helpers (linked lists, etc.) used by the kernel ...
Selects a static array element count at compile time based on a mode flag.
Definition stk_defs.h:608
static constexpr size_t Value
Definition stk_defs.h:614