Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions build/example/driver/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,24 @@
* License: MIT License, see LICENSE for a full text.
*/

#ifndef DRIVER_SMP_H_
#define DRIVER_SMP_H_
#ifndef DRIVER_CPU_H_
#define DRIVER_CPU_H_

#include <stdint.h>
#include "defs.h"

#ifdef __cplusplus

namespace bsp {

struct Cpu
{
static void Start(uint8_t cpu_id, void (*entry_func)(void));
};

#else
} // namespace bsp

void Cpu_Start(uint8_t cpu_id, void (*entry_func)(void));
#endif // __cplusplus

#endif
STK_EXTERN void Cpu_Start(uint8_t cpu_id, void (*entry_func)(void));

#endif /* DRIVER_SMP_H_ */
#endif /* DRIVER_CPU_H_ */
22 changes: 22 additions & 0 deletions build/example/driver/defs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
*
* Source: https://github.com/SuperTinyKernel-RTOS
*
* Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
* License: MIT License, see LICENSE for a full text.
*/

#ifndef DRIVER_DEFS_H_
#define DRIVER_DEFS_H_

#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
#define STK_EXTERN extern "C"
#else
#define STK_EXTERN extern
#endif

#endif /* DRIVER_DEFS_H_ */
15 changes: 6 additions & 9 deletions build/example/driver/led.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
#ifndef DRIVER_LED_H_
#define DRIVER_LED_H_

#include <stdbool.h>
#include <stdint.h>
#include "defs.h"

typedef enum LedId
{
Expand Down Expand Up @@ -53,13 +52,11 @@ struct Led

} // namespace bsp

#else // __cplusplus
#endif // __cplusplus

void Led_Init(LedId led, bool init_state);
void Led_InitAll(bool init_state);
void Led_Set(LedId led, bool state);
void Led_SwitchOnExclusive(LedId led);

#endif
STK_EXTERN void Led_Init(LedId led, bool init_state);
STK_EXTERN void Led_InitAll(bool init_state);
STK_EXTERN void Led_Set(LedId led, bool state);
STK_EXTERN void Led_SwitchOnExclusive(LedId led);

#endif /* DRIVER_LED_H_ */
2 changes: 1 addition & 1 deletion build/example/timer/example.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SuperTinyKernel™ (STK): Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
* SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
*
* Source: https://github.com/SuperTinyKernel-RTOS
*
Expand Down
8 changes: 4 additions & 4 deletions interop/c/include/stk_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,9 +586,9 @@ stk_tick_t stk_ticks_from_ms(stk_time_t msec);
Use this overload when the resolution is already cached to avoid
a repeated call to stk_tick_resolution().
*/
static inline stk_tick_t stk_ticks_from_ms_r(stk_time_t msec, int32_t resolution)
static inline stk_tick_t stk_ticks_from_ms_r(stk_time_t msec, uint32_t resolution)
{
return msec * 1000 / resolution;
return ((resolution != 0U) ? (msec * 1000LL / (stk_time_t)resolution) : 0LL);
}

/*! \brief Returns current time in milliseconds since kernel start.
Expand All @@ -602,9 +602,9 @@ stk_time_t stk_time_now_ms(void);
\return Equivalent time in milliseconds.
\note ISR-safe (arithmetic only).
*/
static inline stk_time_t stk_ms_from_ticks_r(stk_tick_t ticks, int32_t resolution)
static inline stk_time_t stk_ms_from_ticks_r(stk_tick_t ticks, uint32_t resolution)
{
return (ticks * resolution) / 1000;
return (stk_time_t)((ticks * (stk_tick_t)resolution) / 1000LL);
}

/*! \brief Convert ticks to milliseconds using the current kernel tick resolution.
Expand Down
60 changes: 43 additions & 17 deletions interop/c/src/stk_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@
#define STK_TIMER_COUNT_MAX (STK_C_TIMER_MAX)
#include "time/stk_time.h"

// Check correctness of stk_config.h
#ifndef STK_C_KERNEL_TYPE_CPU_0
#error "Missing STK_C_KERNEL_TYPE_CPU_0: Kernel type for CPU0 must be defined via stk_config.h or compiler flags."
#endif
#ifndef STK_C_CPU_COUNT
#error "Missing STK_C_CPU_COUNT: CPU count must be defined via stk_config.h or compiler flags."
#endif
#ifndef STK_C_KERNEL_MAX_TASKS
#error "Missing STK_C_KERNEL_MAX_TASKS: max task count must be defined via stk_config.h or compiler flags."
#endif

using namespace stk;

#define STK_C_TASKS_MAX (STK_C_KERNEL_MAX_TASKS)
Expand All @@ -33,35 +44,43 @@ struct stk_task_t;
class TaskWrapper final : public ITask
{
public:
explicit TaskWrapper() : m_func(nullptr), m_user_data(nullptr), m_stack(nullptr),
m_stack_size(0U), m_mode(ACCESS_USER), m_weight(DEFAULT_WEIGHT), m_tname(nullptr)
{}

/*! \brief Destructor.
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
*/
~TaskWrapper() = default;

// ITask
EAccessMode GetAccessMode() const override { return m_mode; }
void OnDeadlineMissed(uint32_t duration) override { (void)duration; }
int32_t GetWeight() const override { return m_weight; }
const char *GetTraceName() const override { return m_tname; }
EAccessMode GetAccessMode() const override { return m_mode; }
void OnDeadlineMissed(uint32_t duration) override { (void)duration; }
int32_t GetWeight() const override { return m_weight; }
const char *GetTraceName() const override { return m_tname; }

// IStackMemory
stk_word_t *GetStack() const override { return m_stack; }
size_t GetStackSize() const override { return m_stack_size; }
const Word *GetStack() const override { return m_stack; }
size_t GetStackSize() const override { return m_stack_size; }
size_t GetStackSizeBytes() const override { return m_stack_size * sizeof(stk_word_t); }

void Initialize(stk_task_entry_t func,
void *user_data,
stk_word_t *stack,
size_t stack_size,
EAccessMode mode)
void Initialize(stk_task_entry_t func, void *user_data, stk_word_t *stack,
size_t stack_size, EAccessMode mode)
{
m_func = func;
m_user_data = user_data;
m_stack = stack;
m_stack_size = stack_size;
m_mode = mode;
m_weight = 1;
m_weight = DEFAULT_WEIGHT;
}

void SetWeight(int32_t weight) { m_weight = weight; }
void SetWeight(Weight weight) { m_weight = weight; }
void SetName(const char *tname) { m_tname = tname; }

private:
STK_NONCOPYABLE_CLASS(TaskWrapper);

void Run() override { m_func(m_user_data); }
void OnExit() override { FreeTask(ToStkTask()); }

Expand All @@ -73,7 +92,7 @@ class TaskWrapper final : public ITask
stk_word_t *m_stack;
size_t m_stack_size;
EAccessMode m_mode;
int32_t m_weight;
Weight m_weight;
const char *m_tname;
};

Expand Down Expand Up @@ -239,12 +258,19 @@ extern "C" {
// -----------------------------------------------------------------------------
// Kernel create/destroy wrappers
// -----------------------------------------------------------------------------
#define STK_PP_CAT(A, B) A##B
#define STK_PP_CAT_EXPAND(A, B) STK_PP_CAT(A, B)
#define STK_KERNEL_TYPE(X) STK_PP_CAT(STK_C_KERNEL_TYPE_CPU_, X)
#define STK_KERNEL_MEM(X) STK_PP_CAT_EXPAND(kernel_, STK_PP_CAT_EXPAND(X, _mem))
#define STK_KERNEL_CASE(X) \
case X: \
{ \
STK_STATIC_ASSERT_N(sizeof(STK_C_KERNEL_TYPE_CPU_##X) % sizeof(Word) == 0, "Kernel memory size must be multiple of Word"); \
alignas(alignof(STK_C_KERNEL_TYPE_CPU_##X)) static Word kernel_##X##_mem[sizeof(STK_C_KERNEL_TYPE_CPU_##X) / sizeof(Word)]; \
IKernel *kernel = new (kernel_##X##_mem) STK_C_KERNEL_TYPE_CPU_##X(); \
using KernelType_ = STK_KERNEL_TYPE(X); \
STK_STATIC_ASSERT_N(((sizeof(KernelType_) % sizeof(Word)) == 0U), \
"Kernel memory size must be multiple of Word"); \
alignas(alignof(KernelType_)) \
static Word STK_KERNEL_MEM(X)[sizeof(KernelType_) / sizeof(Word)]; \
IKernel *kernel = new (STK_KERNEL_MEM(X)) KernelType_(); \
RegisterKernel(kernel, X); \
return reinterpret_cast<stk_kernel_t *>(kernel); \
}
Expand Down
2 changes: 1 addition & 1 deletion interop/c/src/stk_c_sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ stk_rwmutex_t *stk_rwmutex_create(stk_rwmutex_mem_t *memory, uint32_t memory_siz
if (memory_size < sizeof(stk_rwmutex_t))
return nullptr;

return (stk_rwmutex_t *)new (memory->data) stk_rwmutex_t{};
return (stk_rwmutex_t *)new (memory->data) stk_rwmutex_t();
}

void stk_rwmutex_destroy(stk_rwmutex_t *rw)
Expand Down
6 changes: 3 additions & 3 deletions interop/c/src/stk_c_time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ class CTimerWrapper final : public TimerHost::Timer
m_host_handle = nullptr;
}

stk_timer_callback_t GetCallback() const { return m_callback; }
void *GetUserData() const { return m_user_data; }
stk_timerhost_t *GetHostHandle() const { return m_host_handle; }
stk_timer_callback_t GetCallback() { return m_callback; }
void *GetUserData() { return m_user_data; }
stk_timerhost_t *GetHostHandle() { return m_host_handle; }

void OnExpired(TimerHost */*host*/) override
{
Expand Down
3 changes: 1 addition & 2 deletions stk/include/arch/arm/cortex-m/stk_arch_arm-cortex-m.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ class PlatformArmCortexM final : public IPlatform
/*! \brief Destructor.
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
*/
~PlatformArmCortexM()
{}
~PlatformArmCortexM() = default;

void Initialize(IEventHandler *event_handler, IKernelService *service, uint32_t resolution_us, Stack *exit_trap) override;
void Start() override;
Expand Down
11 changes: 6 additions & 5 deletions stk/include/arch/stk_arch_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ class PlatformContext
/*! \brief Destructor.
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
*/
~PlatformContext()
{}
~PlatformContext() = default;

/*! \brief Initialize context.
\param[in] handler: Event handler.
Expand All @@ -56,15 +55,17 @@ class PlatformContext
*/
static inline Word *InitStackMemory(IStackMemory *memory)
{
size_t stack_size = memory->GetStackSize();
Word *itr = memory->GetStack();
Word *stack_top = itr + stack_size;
const size_t stack_size = memory->GetStackSize();
Word *itr = const_cast<Word *>(memory->GetStack());
Word *const stack_top = itr + stack_size;

STK_ASSERT(stack_size >= STACK_SIZE_MIN);

// initialization of the stack memory satisfies stack integrity check in Kernel::StateSwitch
while (itr < stack_top)
{
*itr++ = STK_STACK_MEMORY_FILLER;
}

// expecting STK_STACK_MEMORY_ALIGN-byte aligned memory for a stack
STK_ASSERT((hw::PtrToWord(stack_top) & (STK_STACK_MEMORY_ALIGN - 1)) == 0U);
Expand Down
6 changes: 3 additions & 3 deletions stk/include/stk.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ final
\brief Bitmask of transient state flags. Set by the task or the kernel and
consumed (cleared) during UpdateTaskState() on the next tick.
*/
enum EStateFlags
enum EStateFlags : uint32_t
{
STATE_NONE = 0, //!< No pending state flags.
STATE_REMOVE_PENDING = (1 << 0), //!< Task returned from its Run function; slot will be freed on the next tick (KERNEL_DYNAMIC only).
Expand Down Expand Up @@ -528,8 +528,8 @@ final
*/
bool IsMemoryOfSP(Word SP) const
{
Word *start = m_user->GetStack();
Word *end = start + m_user->GetStackSize();
const Word *const start = m_user->GetStack();
const Word *const end = start + m_user->GetStackSize();

return (SP >= hw::PtrToWord(start)) && (SP <= hw::PtrToWord(end));
}
Expand Down
18 changes: 10 additions & 8 deletions stk/include/stk_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,10 @@ __stk_forceinline T ReadVolatile64(volatile const T *addr)
{
// 32-bit arch: split the 64-bit address into two 32-bit halves.
// Writer always updates hi before lo (see WriteVolatile64), so if hi is
// the same before and after reading lo, no write straddled the two reads.
volatile const uint32_t *plo = &((volatile const uint32_t *)addr)[STK_ENDIAN_IDX_LO];
volatile const uint32_t *phi = &((volatile const uint32_t *)addr)[STK_ENDIAN_IDX_HI];
// the same before and after reading lo, no write straddled the two reads.
volatile const uint32_t *const p_base = reinterpret_cast<volatile const uint32_t *>(addr);
volatile const uint32_t *const plo = &p_base[STK_ENDIAN_IDX_LO];
volatile const uint32_t *const phi = &p_base[STK_ENDIAN_IDX_HI];

uint32_t hi, lo;
do
Expand All @@ -392,7 +393,7 @@ __stk_forceinline T ReadVolatile64(volatile const T *addr)
}
while (hi != (*phi)); // hi changed: a write occurred during the read; retry

return ((uint64_t)hi << 32) | lo;
return (static_cast<uint64_t>(hi) << 32) | lo;
}
}

Expand Down Expand Up @@ -429,15 +430,16 @@ __stk_forceinline void WriteVolatile64(volatile T *addr, T value)
}
else
{
volatile uint32_t *plo = &((volatile uint32_t *)addr)[STK_ENDIAN_IDX_LO];
volatile uint32_t *phi = &((volatile uint32_t *)addr)[STK_ENDIAN_IDX_HI];
volatile uint32_t *const p_base = reinterpret_cast<volatile uint32_t *>(addr);
volatile uint32_t *const plo = &p_base[STK_ENDIAN_IDX_LO];
volatile uint32_t *const phi = &p_base[STK_ENDIAN_IDX_HI];

// Write hi first: ReadVolatile64 reads hi twice and retries if it changed,
// so writing hi before lo ensures readers can detect a torn write.
(*phi) = (uint32_t)(value >> 32);
(*phi) = static_cast<uint32_t>(static_cast<uint64_t>(value) >> 32);
__stk_full_memfence();

(*plo) = (uint32_t)value;
(*plo) = static_cast<uint32_t>(value);
}
}

Expand Down
Loading
Loading