Skip to content

Commit 47e419c

Browse files
add freertos timers api as fake timers (not using mock. Allows for move time forward behavior)
1 parent 852f739 commit 47e419c

File tree

5 files changed

+489
-1
lines changed

5 files changed

+489
-1
lines changed

cpputest-for-freertos-lib/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,11 @@ add_library(cpputest-for-freertos-lib
3939
src/cpputest_freertos_task.cpp
4040
src/cpputest_freertos_queue.cpp
4141
src/cpputest_freertos_assert.cpp
42+
src/cpputest_freertos_timers.cpp
4243
src/cpputest_main.cpp
4344
)
4445

4546
add_subdirectory(tests)
4647

4748
target_include_directories(cpputest-for-freertos-lib PUBLIC include port/include externals/FreeRTOS-Kernel/include)
48-
49+
target_link_libraries(cpputest-for-freertos-lib fake-timers-lib)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
#ifndef CPPUTEST_FOR_FREERTOS_LIB_CPPUTEST_FREERTOS_TIMERS_HPP
3+
#define CPPUTEST_FOR_FREERTOS_LIB_CPPUTEST_FREERTOS_TIMERS_HPP
4+
5+
#include <chrono>
6+
7+
namespace cms {
8+
namespace test {
9+
10+
void InitFakeTimers();
11+
void DestroyFakeTimers();
12+
void MoveTimeForward(std::chrono::nanoseconds duration);
13+
14+
} //namespace
15+
}//namespace
16+
17+
#endif //CPPUTEST_FOR_FREERTOS_LIB_CPPUTEST_FREERTOS_TIMERS_HPP
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
#include "FreeRTOS.h"
2+
#include "timers.h"
3+
#include "FakeTimers.hpp"
4+
5+
namespace cms {
6+
namespace test {
7+
8+
static FakeTimers* s_fakeTimers = nullptr;
9+
10+
void InitFakeTimers()
11+
{
12+
configASSERT(s_fakeTimers == nullptr);
13+
14+
std::chrono::milliseconds sysTick { configTICK_RATE_HZ * 1/1000 };
15+
s_fakeTimers = new FakeTimers(sysTick);
16+
}
17+
18+
void DestroyFakeTimers()
19+
{
20+
configASSERT(s_fakeTimers != nullptr);
21+
delete s_fakeTimers;
22+
s_fakeTimers = nullptr;
23+
}
24+
25+
void MoveTimeForward(std::chrono::nanoseconds duration)
26+
{
27+
configASSERT(s_fakeTimers != nullptr);
28+
s_fakeTimers->MoveTimeForward(duration);
29+
}
30+
31+
std::chrono::nanoseconds TicksToChrono(TickType_t ticks)
32+
{
33+
std::chrono::milliseconds rtn(pdTICKS_TO_MS(ticks));
34+
return rtn;
35+
}
36+
37+
static const uint8_t s_an_object = 1;
38+
39+
void* HandleToPointer(FakeTimers::Handle handle)
40+
{
41+
return (void*)((&s_an_object) + handle);
42+
}
43+
44+
FakeTimers::Handle PointerToHandle(void* ptr)
45+
{
46+
return ((uint8_t*)ptr - &s_an_object);
47+
}
48+
49+
} //namespace test
50+
} //namespace cms
51+
52+
using namespace cms::test;
53+
54+
extern "C" TimerHandle_t xTimerCreate( const char * const pcTimerName,
55+
const TickType_t xTimerPeriodInTicks,
56+
const BaseType_t xAutoReload,
57+
void * const pvTimerID,
58+
TimerCallbackFunction_t pxCallbackFunction )
59+
{
60+
configASSERT(s_fakeTimers != nullptr);
61+
auto behavior = FakeTimers::Behavior::SingleShot;
62+
if (xAutoReload == pdTRUE)
63+
{
64+
behavior = FakeTimers::Behavior::AutoReload;
65+
}
66+
auto handle = s_fakeTimers->TimerCreate(pcTimerName,
67+
TicksToChrono(xTimerPeriodInTicks),
68+
behavior, pvTimerID,
69+
[=](FakeTimers::Handle handle, FakeTimers::Context){
70+
pxCallbackFunction(
71+
(TimerHandle_t)cms::test::HandleToPointer(handle));
72+
});
73+
74+
return (TimerHandle_t)HandleToPointer(handle);
75+
}
76+
77+
extern "C" BaseType_t xTimerGenericCommandFromTask( TimerHandle_t xTimer,
78+
const BaseType_t xCommandID,
79+
const TickType_t xOptionalValue,
80+
BaseType_t * const pxHigherPriorityTaskWoken,
81+
const TickType_t xTicksToWait )
82+
{
83+
configASSERT(s_fakeTimers != nullptr);
84+
configASSERT(xTimer != nullptr);
85+
86+
(void)pxHigherPriorityTaskWoken;
87+
(void)xTicksToWait;
88+
89+
switch (xCommandID) {
90+
case tmrCOMMAND_START: {
91+
bool ok = s_fakeTimers->TimerStart(PointerToHandle(xTimer));
92+
configASSERT(ok);
93+
break;
94+
}
95+
case tmrCOMMAND_DELETE: {
96+
bool ok = s_fakeTimers->TimerDelete(PointerToHandle(xTimer));
97+
configASSERT(ok);
98+
break;
99+
}
100+
case tmrCOMMAND_STOP: {
101+
bool ok = s_fakeTimers->TimerStop(PointerToHandle(xTimer));
102+
configASSERT(ok);
103+
break;
104+
}
105+
case tmrCOMMAND_CHANGE_PERIOD: {
106+
bool ok = s_fakeTimers->TimerChangePeriod(
107+
PointerToHandle(xTimer),
108+
std::chrono::milliseconds (pdTICKS_TO_MS(xOptionalValue)));
109+
configASSERT(ok);
110+
break;
111+
}
112+
case tmrCOMMAND_RESET: {
113+
bool ok = s_fakeTimers->TimerReset(PointerToHandle(xTimer));
114+
configASSERT(ok);
115+
break;
116+
}
117+
default:
118+
configASSERT(true == false);
119+
break;
120+
}
121+
122+
return pdPASS;
123+
}
124+
125+
extern "C" TickType_t xTaskGetTickCount(void)
126+
{
127+
configASSERT(s_fakeTimers != nullptr);
128+
auto current = s_fakeTimers->GetCurrentInternalTime();
129+
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(current);
130+
131+
return pdMS_TO_TICKS(milliseconds.count());
132+
}
133+
134+
extern "C" BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
135+
{
136+
configASSERT(s_fakeTimers != nullptr);
137+
bool active = s_fakeTimers->TimerIsActive(PointerToHandle(xTimer));
138+
if (active)
139+
{
140+
return pdTRUE;
141+
}
142+
else
143+
{
144+
return pdFALSE;
145+
}
146+
}
147+
148+
extern "C" void * pvTimerGetTimerID( const TimerHandle_t xTimer )
149+
{
150+
configASSERT(s_fakeTimers != nullptr);
151+
auto context = s_fakeTimers->TimerGetContext(PointerToHandle(xTimer));
152+
return context;
153+
}
154+
155+
extern "C" void vTimerSetTimerID( TimerHandle_t xTimer, void * pvNewID )
156+
{
157+
configASSERT(s_fakeTimers != nullptr);
158+
s_fakeTimers->TimerSetContext(PointerToHandle(xTimer), pvNewID);
159+
}
160+
161+
extern "C" const char * pcTimerGetName( TimerHandle_t xTimer )
162+
{
163+
configASSERT(s_fakeTimers != nullptr);
164+
return s_fakeTimers->TimerGetName(PointerToHandle(xTimer));
165+
}
166+
167+
extern "C" BaseType_t xTimerGetReloadMode(TimerHandle_t xTimer)
168+
{
169+
configASSERT(s_fakeTimers != nullptr);
170+
auto behavior = s_fakeTimers->TimerGetBehavior(PointerToHandle(xTimer));
171+
if (behavior == cms::test::FakeTimers::Behavior::AutoReload)
172+
{
173+
return pdTRUE;
174+
}
175+
else
176+
{
177+
return pdFALSE;
178+
}
179+
}
180+
181+
extern "C" void vTimerSetReloadMode(TimerHandle_t xTimer, const BaseType_t xAutoReload)
182+
{
183+
configASSERT(s_fakeTimers != nullptr);
184+
185+
if (xAutoReload == pdTRUE)
186+
{
187+
s_fakeTimers->TimerSetBehavior(PointerToHandle(xTimer), FakeTimers::Behavior::AutoReload);
188+
}
189+
else
190+
{
191+
s_fakeTimers->TimerSetBehavior(PointerToHandle(xTimer), FakeTimers::Behavior::SingleShot);
192+
}
193+
}
194+
195+
extern "C" TickType_t xTimerGetPeriod( TimerHandle_t xTimer )
196+
{
197+
configASSERT(s_fakeTimers != nullptr);
198+
auto period = s_fakeTimers->TimerGetPeriod(PointerToHandle(xTimer));
199+
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(period);
200+
return pdMS_TO_TICKS(milliseconds.count());
201+
}
202+
203+
extern "C" TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )
204+
{
205+
configASSERT(s_fakeTimers != nullptr);
206+
auto period = s_fakeTimers->TimerGetExpiryTime(PointerToHandle(xTimer));
207+
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(period);
208+
return pdMS_TO_TICKS(milliseconds.count());
209+
}

cpputest-for-freertos-lib/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
set(TEST_APP_NAME cpputest-for-freertos-lib-tests)
33
set(TEST_SOURCES
44
cpputest_freertos_assert_tests.cpp
5+
cpputest_freertos_timers_tests.cpp
56
)
67

78
# this include expects TEST_SOURCES and TEST_APP_NAME to be

0 commit comments

Comments
 (0)