Skip to content

Commit 5198ad3

Browse files
committed
Add tests for full coverage.
1 parent 72844a5 commit 5198ad3

11 files changed

Lines changed: 187 additions & 38 deletions

File tree

build/example/project/eclipse/stm/blinky-cmsis-rtos2-prio-stm32f407g-disc1/src/main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@
4848
#include "RTE_Components.h" // CMSIS_device_header definition, Example driver include
4949
#include CMSIS_device_header // STK config
5050

51-
#define FIX_PRIORITY_INHERITANCE_DEADLOCK 0
51+
// when 1 the RED led will be periodically blinking because MidPrioThread will cooperate
52+
// and periodically release time to LowPrioThread when MidPrioThread is sleeping
53+
#define FIX_COOPERATIVE_BEHAVIOR 0
5254

5355
/* --------------------------------------------------------------------------
5456
* Mutex
@@ -143,7 +145,7 @@ void MidPrioThread (void *argument) {
143145
* but this is NOT a blocking wait on a mutex/semaphore/flag – MidPrio
144146
* will always re-schedule before LowPrio (absent priority inheritance).
145147
*/
146-
#if FIX_PRIORITY_INHERITANCE_DEADLOCK
148+
#if FIX_COOPERATIVE_BEHAVIOR
147149
osThreadYield();
148150
#endif
149151
}

build/example/project/eclipse/stm/blinky-cmsis-rtos2-stm32f407g-disc1/.cproject

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@
283283
<listOptionValue builtIn="false" value="STM32F407xx"/>
284284
<listOptionValue builtIn="false" value="USE_HAL_DRIVER"/>
285285
<listOptionValue builtIn="false" value="HSE_VALUE=8000000"/>
286+
<listOptionValue builtIn="false" value="OS_USE_TRACE_SEMIHOSTING_DEBUG"/>
287+
<listOptionValue builtIn="false" value="TRACE"/>
286288
</option>
287289
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.1578028994" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/>
288290
</tool>
@@ -339,6 +341,7 @@
339341
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.nostart.105469396" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>
340342
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnano.278762053" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnano" useByScannerDiscovery="false" value="true" valueType="boolean"/>
341343
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.other.1003289561" name="Other linker flags" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.other" useByScannerDiscovery="false" value="-Wl,--print-memory-usage" valueType="string"/>
344+
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnosys.648951868" name="Do not use syscalls (--specs=nosys.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnosys" value="false" valueType="boolean"/>
342345
<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.input.1091267123" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.input">
343346
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
344347
<additionalInput kind="additionalinput" paths="$(LIBS)"/>

build/example/project/eclipse/stm/blinky-cmsis-rtos2-stm32f407g-disc1/src/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ struct phases_t {
4545
* Switch LED on
4646
*---------------------------------------------------------------------------*/
4747
void Switch_On (unsigned char led) {
48-
printf("LED On: #%d\n", led);
48+
//printf("LED On: #%d\n", led);
4949
Led_Set(led, true);
5050
}
5151

5252
/*----------------------------------------------------------------------------
5353
* Switch LED off
5454
*---------------------------------------------------------------------------*/
5555
void Switch_Off (unsigned char led) {
56-
printf("LED Off: #%d\n", led);
56+
//printf("LED Off: #%d\n", led);
5757
Led_Set(led, false);
5858
}
5959

@@ -152,7 +152,7 @@ void app_main (void */*argument*/) {
152152
osDelay(osWaitForever);
153153
}
154154

155-
int main (void) {
155+
int main (int, char*[]) {
156156

157157
// System Initialization
158158
SystemCoreClockUpdate();

interop/c/src/stk_c_memory.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
*/
99

1010
#include <cstddef> // for std::size_t
11-
#include <cstdlib> // for malloc, free
1211

1312
#include <stk_config.h>
1413
#include <stk.h>
@@ -26,15 +25,12 @@ template <typename T> static constexpr size_t StkGetWordCountForType()
2625
return ((sizeof(T) + sizeof(stk::Word) - 1) / sizeof(stk::Word));
2726
}
2827

29-
// Private memory allocators.
30-
void *stk::memory::MemoryAllocator::Allocate(size_t size)
31-
{
32-
return malloc(size);
33-
}
34-
void stk::memory::MemoryAllocator::Free(void *ptr)
35-
{
36-
free(ptr);
37-
}
28+
// Private memory allocators (we define malloc, free here to overcome absence of declaration in
29+
// case of -ffreestanding compiler flag).
30+
extern "C" void *malloc(size_t size);
31+
extern "C" void free(void *ptr);
32+
void *stk::memory::MemoryAllocator::Allocate(size_t size) { return malloc(size); }
33+
void stk::memory::MemoryAllocator::Free(void *ptr) { free(ptr); }
3834

3935
// ---------------------------------------------------------------------------
4036
// stk_blockpool_t — wraps a BlockMemoryPool instance

interop/cmsis/rtos2/src/cmsis_os2_stk.cpp

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,13 @@
4646
* recursive (osMutexRecursive is therefore always effective).
4747
*/
4848

49-
#include "cmsis_os2.h"
50-
51-
#include <cstring>
52-
#include <cstdlib>
53-
#include <new>
54-
#include <stdint.h>
55-
5649
#include "stk.h"
5750
#include "sync/stk_sync.h"
5851
#include "time/stk_time.h"
5952
#include "memory/stk_memory.h"
6053

54+
#include "cmsis_os2.h"
55+
6156
// ---------------------------------------------------------------------------
6257
// Kernel version / identification
6358
// ---------------------------------------------------------------------------
@@ -90,15 +85,12 @@ template <typename T> static constexpr size_t StkGetWordCountForType()
9085
return ((sizeof(T) + sizeof(stk::Word) - 1) / sizeof(stk::Word));
9186
}
9287

93-
// Private memory allocators.
94-
void *stk::memory::MemoryAllocator::Allocate(size_t size)
95-
{
96-
return malloc(size);
97-
}
98-
void stk::memory::MemoryAllocator::Free(void *ptr)
99-
{
100-
free(ptr);
101-
}
88+
// Private memory allocators (we define malloc, free here to overcome absence of declaration in
89+
// case of -ffreestanding compiler flag).
90+
extern "C" void *malloc(size_t size);
91+
extern "C" void free(void *ptr);
92+
void *stk::memory::MemoryAllocator::Allocate(size_t size) { return malloc(size); }
93+
void stk::memory::MemoryAllocator::Free(void *ptr) { free(ptr); }
10294

10395
// ---------------------------------------------------------------------------
10496
// Priority mapping:

stk/include/stk.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,29 @@ final
10541054
task->Wake();
10551055
}
10561056

1057-
/*! \brief Enumerate tasks.
1057+
/*! \brief Enumerate kernel tasks.
1058+
\param[in,out] user_tasks: Pointer to the array for IKernelTask pointers.
1059+
\param[in] max_size: Max size of the provided array.
1060+
\return Number of tasks in the array.
1061+
*/
1062+
size_t EnumerateKernelTasks(IKernelTask **tasks, const size_t max_size) override
1063+
{
1064+
size_t count = 0U;
1065+
1066+
// avoid race with OnTick
1067+
hw::CriticalSection::ScopedLock cs_;
1068+
1069+
for (uint32_t i = 0U; i < Min(max_size, static_cast<size_t>(TASKS_MAX)); ++i)
1070+
{
1071+
KernelTask *task = &m_task_storage[i];
1072+
if (task->IsBusy())
1073+
tasks[count++] = task;
1074+
}
1075+
1076+
return count;
1077+
}
1078+
1079+
/*! \brief Enumerate tasks.
10581080
\param[in,out] user_tasks: Pointer to the array for ITask pointers.
10591081
\param[in] max_size: Max size of the provided array.
10601082
\return Number of tasks in the array.

stk/include/stk_common.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,15 @@ class IKernel
10841084
*/
10851085
virtual void ResumeTask(ITask *user_task) = 0;
10861086

1087-
/*! \brief Enumerate tasks.
1087+
/*! \brief Enumerate kernel tasks.
1088+
\param[in,out] user_tasks: Pointer to the array for IKernelTask pointers.
1089+
\param[in] max_size: Max size of the provided array.
1090+
\return Number of tasks in the array.
1091+
\warning ISR-safe.
1092+
*/
1093+
virtual size_t EnumerateKernelTasks(IKernelTask **tasks, size_t max_size) = 0;
1094+
1095+
/*! \brief Enumerate user tasks.
10881096
\param[in,out] user_tasks: Pointer to the array for ITask pointers.
10891097
\param[in] max_size: Max size of the provided array.
10901098
\return Number of tasks in the array.

test/blockpool/test_blockpool.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ STK_TEST_DECL_ASSERT;
3737

3838
// Private memory allocators (we define malloc, free here to overcome absence of declaration in
3939
// case of -ffreestanding compiler flag).
40-
extern "C" void* malloc(size_t size);
41-
extern "C" void free(void* ptr);
40+
extern "C" void *malloc(size_t size);
41+
extern "C" void free(void *ptr);
4242
void *stk::memory::MemoryAllocator::Allocate(size_t size) { return malloc(size); }
4343
void stk::memory::MemoryAllocator::Free(void *ptr) { free(ptr); }
4444

test/generic/stktest_kernel.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,116 @@ TEST(Kernel, SyncWaitTicklessDuration)
15451545
CHECK_EQUAL(true, mutex.m_locked);
15461546
}
15471547

1548+
static struct SyncFindWeightHigherThanContext
1549+
{
1550+
SyncFindWeightHigherThanContext()
1551+
{
1552+
Reset();
1553+
}
1554+
1555+
void Reset()
1556+
{
1557+
counter = 0;
1558+
platform = NULL;
1559+
sobj = NULL;
1560+
}
1561+
1562+
uint32_t counter;
1563+
PlatformTestMock *platform;
1564+
SyncObjectMock *sobj;
1565+
1566+
void Process()
1567+
{
1568+
platform->ProcessTick();
1569+
++counter;
1570+
1571+
if (counter == 1)
1572+
{
1573+
CHECK_EQUAL(2, sobj->FindWeightHigherThan(0));
1574+
}
1575+
}
1576+
}
1577+
g_SyncFindWeightHigherThan;
1578+
1579+
static void SyncFindWeightHigherThanRelaxCpu()
1580+
{
1581+
g_SyncFindWeightHigherThan.Process();
1582+
}
1583+
1584+
TEST(Kernel, SyncFindWeightHigherThan)
1585+
{
1586+
Kernel<KERNEL_STATIC | KERNEL_SYNC, 2, SwitchStrategyFP32, PlatformTestMock> kernel;
1587+
PlatformTestMock *platform = static_cast<PlatformTestMock *>(kernel.GetPlatform());
1588+
TaskMockW<1, ACCESS_USER> task1;
1589+
TaskMockW<2, ACCESS_USER> task2;
1590+
1591+
MutexMock mutex;
1592+
SyncObjectMock sobj;
1593+
1594+
g_SyncFindWeightHigherThan.Reset();
1595+
g_SyncFindWeightHigherThan.platform = platform;
1596+
g_SyncFindWeightHigherThan.sobj = &sobj;
1597+
g_RelaxCpuHandler = SyncFindWeightHigherThanRelaxCpu;
1598+
1599+
kernel.Initialize();
1600+
kernel.AddTask(&task1);
1601+
kernel.AddTask(&task2);
1602+
kernel.Start();
1603+
1604+
// no task is waiting
1605+
CHECK_EQUAL(NO_WEIGHT, sobj.FindWeightHigherThan(0));
1606+
1607+
MutexMock::ScopedLock guard(mutex);
1608+
1609+
// sleep_ticks should be equal to 2 on first OnTick call
1610+
IWaitObject *wo = IKernelService::GetInstance()->Wait(&sobj, &mutex, 5);
1611+
1612+
CHECK_TRUE(wo != nullptr);
1613+
CHECK_EQUAL(true, mutex.m_locked);
1614+
1615+
// no task is waiting here
1616+
CHECK_EQUAL(NO_WEIGHT, sobj.FindWeightHigherThan(0));
1617+
}
1618+
1619+
TEST(Kernel, SyncInheritWeight)
1620+
{
1621+
Kernel<KERNEL_STATIC | KERNEL_SYNC, 2, SwitchStrategyFP32, PlatformTestMock> kernel;
1622+
TaskMockW<1, ACCESS_USER> task1;
1623+
TaskMockW<2, ACCESS_USER> task2;
1624+
1625+
MutexMock mutex;
1626+
SyncObjectMock sobj;
1627+
1628+
kernel.Initialize();
1629+
kernel.AddTask(&task1);
1630+
kernel.AddTask(&task2);
1631+
kernel.Start();
1632+
1633+
IKernelTask *ktasks[2];
1634+
kernel.EnumerateKernelTasks(ktasks, 2);
1635+
1636+
// current weight is dynamic value used by strategy with PRIORITY_INHERITANCE_API, if not overridden
1637+
// by InheritWeight should be NO_WEIGHT
1638+
CHECK_EQUAL(NO_WEIGHT, ktasks[0]->GetCurrentWeight());
1639+
1640+
// original weight
1641+
CHECK_EQUAL(1, ktasks[0]->GetWeight());
1642+
1643+
IKernelService::GetInstance()->InheritWeight(task1.GetId(), 2);
1644+
1645+
// boosted weight
1646+
CHECK_EQUAL(2, ktasks[0]->GetCurrentWeight());
1647+
CHECK_EQUAL(2, ktasks[0]->GetWeight()); // using GetCurrentWeight
1648+
1649+
IKernelService::GetInstance()->RestoreWeight(task1.GetId());
1650+
1651+
// dynamic is back to NO_WEIGHT
1652+
CHECK_EQUAL(NO_WEIGHT, ktasks[0]->GetCurrentWeight());
1653+
1654+
// back to own weight
1655+
CHECK_EQUAL(1, ktasks[0]->GetWeight());
1656+
}
1657+
15481658
TEST(Kernel, EnumTasks)
15491659
{
15501660
Kernel<KERNEL_STATIC, 2, SwitchStrategyRR, PlatformTestMock> kernel;

test/generic/stktest_misc.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ TEST(Basic, MinMax)
6262
}
6363
}
6464

65+
TEST(Basic, ISwitchStrategyStub)
66+
{
67+
SwitchStrategyRR ss;
68+
69+
// these are just stubs for interface noop functions to achieve 100% coverage, providing nullptr
70+
// for ITasks should be noop too
71+
ss.OnTaskDeadlineMissed(nullptr);
72+
ss.OnTaskWeightChange(nullptr, NO_WEIGHT);
73+
}
74+
6575
// ============================================================================ //
6676
// ============================= UserTask ===================================== //
6777
// ============================================================================ //
@@ -134,8 +144,14 @@ TEST(UserTask, GetIdAndName)
134144
TaskMock<ACCESS_USER> task;
135145
TaskMockW<1, ACCESS_USER> taskw;
136146

137-
CHECK_EQUAL((Word)&task, task.GetId());
138-
CHECK_EQUAL((Word)&taskw, taskw.GetId());
147+
CHECK_EQUAL((TId)&task, task.GetId());
148+
CHECK_EQUAL((TId)&taskw, taskw.GetId());
149+
150+
CHECK_EQUAL((TId)&task, stk::GetTidFromUserTask(&task));
151+
CHECK_EQUAL((TId)&taskw, stk::GetTidFromUserTask(&taskw));
152+
153+
CHECK_EQUAL(&task, stk::GetUserTaskFromTid(stk::GetTidFromUserTask(&task)));
154+
CHECK_EQUAL(&taskw, stk::GetUserTaskFromTid(stk::GetTidFromUserTask(&taskw)));
139155

140156
// expect NULL name by default
141157
CHECK_EQUAL((const char *)NULL, task.GetTraceName());

0 commit comments

Comments
 (0)