Skip to content

Commit 389ceb2

Browse files
committed
Protect C interface from missing configuring definitions.
Fix C interface compile by IAR. Modify IStackMemory::GetStack() API to return const Word pointer in order to protect memory from unintentional write ops (see example TEST(UserTask, GetStackSpace)). Minor cleanup to remove IAR compiler warnings.
1 parent 4e18244 commit 389ceb2

19 files changed

Lines changed: 1478 additions & 1421 deletions

File tree

build/example/driver/cpu.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,24 @@
77
* License: MIT License, see LICENSE for a full text.
88
*/
99

10-
#ifndef DRIVER_SMP_H_
11-
#define DRIVER_SMP_H_
10+
#ifndef DRIVER_CPU_H_
11+
#define DRIVER_CPU_H_
1212

13-
#include <stdint.h>
13+
#include "defs.h"
1414

1515
#ifdef __cplusplus
1616

17+
namespace bsp {
18+
1719
struct Cpu
1820
{
1921
static void Start(uint8_t cpu_id, void (*entry_func)(void));
2022
};
2123

22-
#else
24+
} // namespace bsp
2325

24-
void Cpu_Start(uint8_t cpu_id, void (*entry_func)(void));
26+
#endif // __cplusplus
2527

26-
#endif
28+
STK_EXTERN void Cpu_Start(uint8_t cpu_id, void (*entry_func)(void));
2729

28-
#endif /* DRIVER_SMP_H_ */
30+
#endif /* DRIVER_CPU_H_ */

build/example/driver/defs.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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 DRIVER_DEFS_H_
11+
#define DRIVER_DEFS_H_
12+
13+
#include <stdbool.h>
14+
#include <stdint.h>
15+
16+
#ifdef __cplusplus
17+
#define STK_EXTERN extern "C"
18+
#else
19+
#define STK_EXTERN extern
20+
#endif
21+
22+
#endif /* DRIVER_DEFS_H_ */

build/example/driver/led.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
#ifndef DRIVER_LED_H_
1111
#define DRIVER_LED_H_
1212

13-
#include <stdbool.h>
14-
#include <stdint.h>
13+
#include "defs.h"
1514

1615
typedef enum LedId
1716
{
@@ -53,13 +52,11 @@ struct Led
5352

5453
} // namespace bsp
5554

56-
#else // __cplusplus
55+
#endif // __cplusplus
5756

58-
void Led_Init(LedId led, bool init_state);
59-
void Led_InitAll(bool init_state);
60-
void Led_Set(LedId led, bool state);
61-
void Led_SwitchOnExclusive(LedId led);
62-
63-
#endif
57+
STK_EXTERN void Led_Init(LedId led, bool init_state);
58+
STK_EXTERN void Led_InitAll(bool init_state);
59+
STK_EXTERN void Led_Set(LedId led, bool state);
60+
STK_EXTERN void Led_SwitchOnExclusive(LedId led);
6461

6562
#endif /* DRIVER_LED_H_ */

build/example/timer/example.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SuperTinyKernel™ (STK): Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
2+
* SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
33
*
44
* Source: https://github.com/SuperTinyKernel-RTOS
55
*

interop/c/include/stk_c.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,9 +586,9 @@ stk_tick_t stk_ticks_from_ms(stk_time_t msec);
586586
Use this overload when the resolution is already cached to avoid
587587
a repeated call to stk_tick_resolution().
588588
*/
589-
static inline stk_tick_t stk_ticks_from_ms_r(stk_time_t msec, int32_t resolution)
589+
static inline stk_tick_t stk_ticks_from_ms_r(stk_time_t msec, uint32_t resolution)
590590
{
591-
return msec * 1000 / resolution;
591+
return ((resolution != 0U) ? (msec * 1000LL / (stk_time_t)resolution) : 0LL);
592592
}
593593

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

610610
/*! \brief Convert ticks to milliseconds using the current kernel tick resolution.

interop/c/src/stk_c.cpp

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121
#define STK_TIMER_COUNT_MAX (STK_C_TIMER_MAX)
2222
#include "time/stk_time.h"
2323

24+
// Check correctness of stk_config.h
25+
#ifndef STK_C_KERNEL_TYPE_CPU_0
26+
#error "Missing STK_C_KERNEL_TYPE_CPU_0: Kernel type for CPU0 must be defined via stk_config.h or compiler flags."
27+
#endif
28+
#ifndef STK_C_CPU_COUNT
29+
#error "Missing STK_C_CPU_COUNT: CPU count must be defined via stk_config.h or compiler flags."
30+
#endif
31+
#ifndef STK_C_KERNEL_MAX_TASKS
32+
#error "Missing STK_C_KERNEL_MAX_TASKS: max task count must be defined via stk_config.h or compiler flags."
33+
#endif
34+
2435
using namespace stk;
2536

2637
#define STK_C_TASKS_MAX (STK_C_KERNEL_MAX_TASKS)
@@ -33,35 +44,43 @@ struct stk_task_t;
3344
class TaskWrapper final : public ITask
3445
{
3546
public:
47+
explicit TaskWrapper() : m_func(nullptr), m_user_data(nullptr), m_stack(nullptr),
48+
m_stack_size(0U), m_mode(ACCESS_USER), m_weight(DEFAULT_WEIGHT), m_tname(nullptr)
49+
{}
50+
51+
/*! \brief Destructor.
52+
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
53+
*/
54+
~TaskWrapper() = default;
55+
3656
// ITask
37-
EAccessMode GetAccessMode() const override { return m_mode; }
38-
void OnDeadlineMissed(uint32_t duration) override { (void)duration; }
39-
int32_t GetWeight() const override { return m_weight; }
40-
const char *GetTraceName() const override { return m_tname; }
57+
EAccessMode GetAccessMode() const override { return m_mode; }
58+
void OnDeadlineMissed(uint32_t duration) override { (void)duration; }
59+
int32_t GetWeight() const override { return m_weight; }
60+
const char *GetTraceName() const override { return m_tname; }
4161

4262
// IStackMemory
43-
stk_word_t *GetStack() const override { return m_stack; }
44-
size_t GetStackSize() const override { return m_stack_size; }
63+
const Word *GetStack() const override { return m_stack; }
64+
size_t GetStackSize() const override { return m_stack_size; }
4565
size_t GetStackSizeBytes() const override { return m_stack_size * sizeof(stk_word_t); }
4666

47-
void Initialize(stk_task_entry_t func,
48-
void *user_data,
49-
stk_word_t *stack,
50-
size_t stack_size,
51-
EAccessMode mode)
67+
void Initialize(stk_task_entry_t func, void *user_data, stk_word_t *stack,
68+
size_t stack_size, EAccessMode mode)
5269
{
5370
m_func = func;
5471
m_user_data = user_data;
5572
m_stack = stack;
5673
m_stack_size = stack_size;
5774
m_mode = mode;
58-
m_weight = 1;
75+
m_weight = DEFAULT_WEIGHT;
5976
}
6077

61-
void SetWeight(int32_t weight) { m_weight = weight; }
78+
void SetWeight(Weight weight) { m_weight = weight; }
6279
void SetName(const char *tname) { m_tname = tname; }
6380

6481
private:
82+
STK_NONCOPYABLE_CLASS(TaskWrapper);
83+
6584
void Run() override { m_func(m_user_data); }
6685
void OnExit() override { FreeTask(ToStkTask()); }
6786

@@ -73,7 +92,7 @@ class TaskWrapper final : public ITask
7392
stk_word_t *m_stack;
7493
size_t m_stack_size;
7594
EAccessMode m_mode;
76-
int32_t m_weight;
95+
Weight m_weight;
7796
const char *m_tname;
7897
};
7998

@@ -239,12 +258,19 @@ extern "C" {
239258
// -----------------------------------------------------------------------------
240259
// Kernel create/destroy wrappers
241260
// -----------------------------------------------------------------------------
261+
#define STK_PP_CAT(A, B) A##B
262+
#define STK_PP_CAT_EXPAND(A, B) STK_PP_CAT(A, B)
263+
#define STK_KERNEL_TYPE(X) STK_PP_CAT(STK_C_KERNEL_TYPE_CPU_, X)
264+
#define STK_KERNEL_MEM(X) STK_PP_CAT_EXPAND(kernel_, STK_PP_CAT_EXPAND(X, _mem))
242265
#define STK_KERNEL_CASE(X) \
243266
case X: \
244267
{ \
245-
STK_STATIC_ASSERT_N(sizeof(STK_C_KERNEL_TYPE_CPU_##X) % sizeof(Word) == 0, "Kernel memory size must be multiple of Word"); \
246-
alignas(alignof(STK_C_KERNEL_TYPE_CPU_##X)) static Word kernel_##X##_mem[sizeof(STK_C_KERNEL_TYPE_CPU_##X) / sizeof(Word)]; \
247-
IKernel *kernel = new (kernel_##X##_mem) STK_C_KERNEL_TYPE_CPU_##X(); \
268+
using KernelType_ = STK_KERNEL_TYPE(X); \
269+
STK_STATIC_ASSERT_N(((sizeof(KernelType_) % sizeof(Word)) == 0U), \
270+
"Kernel memory size must be multiple of Word"); \
271+
alignas(alignof(KernelType_)) \
272+
static Word STK_KERNEL_MEM(X)[sizeof(KernelType_) / sizeof(Word)]; \
273+
IKernel *kernel = new (STK_KERNEL_MEM(X)) KernelType_(); \
248274
RegisterKernel(kernel, X); \
249275
return reinterpret_cast<stk_kernel_t *>(kernel); \
250276
}

interop/c/src/stk_c_sync.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ stk_rwmutex_t *stk_rwmutex_create(stk_rwmutex_mem_t *memory, uint32_t memory_siz
715715
if (memory_size < sizeof(stk_rwmutex_t))
716716
return nullptr;
717717

718-
return (stk_rwmutex_t *)new (memory->data) stk_rwmutex_t{};
718+
return (stk_rwmutex_t *)new (memory->data) stk_rwmutex_t();
719719
}
720720

721721
void stk_rwmutex_destroy(stk_rwmutex_t *rw)

interop/c/src/stk_c_time.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ class CTimerWrapper final : public TimerHost::Timer
5959
m_host_handle = nullptr;
6060
}
6161

62-
stk_timer_callback_t GetCallback() const { return m_callback; }
63-
void *GetUserData() const { return m_user_data; }
64-
stk_timerhost_t *GetHostHandle() const { return m_host_handle; }
62+
stk_timer_callback_t GetCallback() { return m_callback; }
63+
void *GetUserData() { return m_user_data; }
64+
stk_timerhost_t *GetHostHandle() { return m_host_handle; }
6565

6666
void OnExpired(TimerHost */*host*/) override
6767
{

stk/include/arch/arm/cortex-m/stk_arch_arm-cortex-m.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ class PlatformArmCortexM final : public IPlatform
2727
/*! \brief Destructor.
2828
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
2929
*/
30-
~PlatformArmCortexM()
31-
{}
30+
~PlatformArmCortexM() = default;
3231

3332
void Initialize(IEventHandler *event_handler, IKernelService *service, uint32_t resolution_us, Stack *exit_trap) override;
3433
void Start() override;

stk/include/arch/stk_arch_common.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ class PlatformContext
3131
/*! \brief Destructor.
3232
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
3333
*/
34-
~PlatformContext()
35-
{}
34+
~PlatformContext() = default;
3635

3736
/*! \brief Initialize context.
3837
\param[in] handler: Event handler.
@@ -56,15 +55,17 @@ class PlatformContext
5655
*/
5756
static inline Word *InitStackMemory(IStackMemory *memory)
5857
{
59-
size_t stack_size = memory->GetStackSize();
60-
Word *itr = memory->GetStack();
61-
Word *stack_top = itr + stack_size;
58+
const size_t stack_size = memory->GetStackSize();
59+
Word *itr = const_cast<Word *>(memory->GetStack());
60+
Word *const stack_top = itr + stack_size;
6261

6362
STK_ASSERT(stack_size >= STACK_SIZE_MIN);
6463

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

6970
// expecting STK_STACK_MEMORY_ALIGN-byte aligned memory for a stack
7071
STK_ASSERT((hw::PtrToWord(stack_top) & (STK_STACK_MEMORY_ALIGN - 1)) == 0U);

0 commit comments

Comments
 (0)