Skip to content

Commit 3d37d81

Browse files
authored
Merge pull request #5046 from fkjagodzinski/timerevent_tests
TimerEvent tests
2 parents 80263ea + cd539e3 commit 3d37d81

File tree

13 files changed

+291
-18
lines changed

13 files changed

+291
-18
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "mbed.h"
17+
#include "greentea-client/test_env.h"
18+
#include "unity.h"
19+
#include "utest.h"
20+
#include "drivers/TimerEvent.h"
21+
#include "hal/ticker_api.h"
22+
#include "rtos.h"
23+
24+
using namespace utest::v1;
25+
26+
#define TEST_DELAY_US 50000ULL
27+
28+
class TestTimerEvent: public TimerEvent {
29+
private:
30+
Semaphore sem;
31+
virtual void handler() {
32+
sem.release();
33+
}
34+
35+
public:
36+
TestTimerEvent() :
37+
TimerEvent(), sem(0, 1) {
38+
}
39+
40+
TestTimerEvent(const ticker_data_t *data) :
41+
TimerEvent(data), sem(0, 1) {
42+
}
43+
44+
virtual ~TestTimerEvent() {
45+
}
46+
47+
// Make these methods publicly accessible
48+
using TimerEvent::insert;
49+
using TimerEvent::insert_absolute;
50+
using TimerEvent::remove;
51+
52+
int32_t sem_wait(uint32_t millisec) {
53+
return sem.wait(millisec);
54+
}
55+
};
56+
57+
class TestTimerEventRelative: public TestTimerEvent {
58+
public:
59+
static const int32_t SEM_SLOTS_AFTER_PAST_TS_INSERTED = 0;
60+
TestTimerEventRelative() :
61+
TestTimerEvent() {
62+
}
63+
64+
TestTimerEventRelative(const ticker_data_t *data) :
65+
TestTimerEvent(data) {
66+
}
67+
68+
// Set relative timestamp of internal event to present_time + ts
69+
void set_future_timestamp(timestamp_t ts) {
70+
insert(::ticker_read(_ticker_data) + ts);
71+
}
72+
73+
void set_past_timestamp(void) {
74+
insert(::ticker_read(_ticker_data) - 1UL);
75+
}
76+
};
77+
78+
class TestTimerEventAbsolute: public TestTimerEvent {
79+
public:
80+
static const int32_t SEM_SLOTS_AFTER_PAST_TS_INSERTED = 1;
81+
TestTimerEventAbsolute() :
82+
TestTimerEvent() {
83+
}
84+
85+
TestTimerEventAbsolute(const ticker_data_t *data) :
86+
TestTimerEvent(data) {
87+
}
88+
89+
// Set absolute timestamp of internal event to present_time + ts
90+
void set_future_timestamp(us_timestamp_t ts) {
91+
insert_absolute(::ticker_read_us(_ticker_data) + ts);
92+
}
93+
94+
void set_past_timestamp(void) {
95+
insert_absolute(::ticker_read_us(_ticker_data) - 1ULL);
96+
}
97+
};
98+
99+
/** Template for tests: insert, insert_absolute
100+
*
101+
* Test insert
102+
* Given an instance of @a TimerEvent subclass
103+
* When a tiestamp is set with @a insert()
104+
* and given time elapses
105+
* Then an event handler is called
106+
*
107+
* Test insert_absolute
108+
* Given an instance of @a TimerEvent subclass
109+
* When a tiestamp is set with @a insert_absolute()
110+
* and given time elapses
111+
* Then an event handler is called
112+
*/
113+
template<typename T>
114+
void test_insert(void) {
115+
T tte;
116+
117+
tte.set_future_timestamp(TEST_DELAY_US);
118+
int32_t sem_slots = tte.sem_wait(0);
119+
TEST_ASSERT_EQUAL(0, sem_slots);
120+
121+
sem_slots = tte.sem_wait(TEST_DELAY_US / 1000 + 1);
122+
TEST_ASSERT_EQUAL(1, sem_slots);
123+
124+
tte.remove();
125+
}
126+
127+
/** Template for tests: remove
128+
*
129+
* Test remove after insert
130+
* Given an instance of @a TimerEvent subclass
131+
* When a tiestamp is set with @a insert()
132+
* and timestamp is removed before being reached
133+
* Then the event handler is never called
134+
*
135+
* Test remove after insert_absolute
136+
* Given an instance of @a TimerEvent subclass
137+
* When a tiestamp is set with @a insert_absolute()
138+
* and timestamp is removed before being reached
139+
* Then the event handler is never called
140+
*/
141+
template<typename T>
142+
void test_remove(void) {
143+
T tte;
144+
145+
tte.set_future_timestamp(TEST_DELAY_US * 2);
146+
int32_t sem_slots = tte.sem_wait(TEST_DELAY_US / 1000);
147+
TEST_ASSERT_EQUAL(0, sem_slots);
148+
tte.remove();
149+
150+
sem_slots = tte.sem_wait(TEST_DELAY_US * 2 / 1000 + 1);
151+
TEST_ASSERT_EQUAL(0, sem_slots);
152+
}
153+
154+
/** Test insert_absolute zero
155+
* Given an instance of @a TimerEvent subclass
156+
* When a timestamp of 0 us is set with @a insert_absolute()
157+
* Then an event handler is called instantly
158+
*/
159+
void test_insert_zero(void) {
160+
TestTimerEvent tte;
161+
162+
tte.insert_absolute(0ULL);
163+
int32_t sem_slots = tte.sem_wait(0);
164+
TEST_ASSERT_EQUAL(1, sem_slots);
165+
166+
tte.remove();
167+
}
168+
169+
/** Template for tests: insert, insert_absolute past timestamp
170+
*
171+
* Test insert timestamp from the past
172+
* Given an instance of @a TimerEvent subclass
173+
* When a timestamp of X us is set with @a insert()
174+
* and X is less than present_time
175+
* Then an event handler is **not** called instantly
176+
* (the event is scheduled after the ticker's overflow)
177+
*
178+
* Test insert_absolute timestamp from the past
179+
* Given an instance of @a TimerEvent subclass
180+
* When a timestamp of X us is set with @a insert_absolute()
181+
* and X is less than present_time
182+
* Then an event handler is called instantly
183+
*/
184+
template<typename T>
185+
void test_insert_past(void) {
186+
T tte;
187+
188+
tte.set_past_timestamp();
189+
int32_t sem_slots = tte.sem_wait(0);
190+
TEST_ASSERT_EQUAL(tte.SEM_SLOTS_AFTER_PAST_TS_INSERTED, sem_slots);
191+
192+
tte.remove();
193+
}
194+
195+
utest::v1::status_t test_setup(const size_t number_of_cases)
196+
{
197+
GREENTEA_SETUP(5, "default_auto");
198+
return verbose_test_setup_handler(number_of_cases);
199+
}
200+
201+
Case cases[] = {
202+
Case("Test insert", test_insert<TestTimerEventRelative>),
203+
Case("Test insert_absolute", test_insert<TestTimerEventAbsolute>),
204+
205+
Case("Test remove after insert", test_remove<TestTimerEventRelative>),
206+
Case("Test remove after insert_absolute", test_remove<TestTimerEventAbsolute>),
207+
208+
Case("Test insert_absolute zero", test_insert_zero),
209+
210+
Case("Test insert timestamp from the past", test_insert_past<TestTimerEventRelative>),
211+
Case("Test insert_absolute timestamp from the past", test_insert_past<TestTimerEventAbsolute>),
212+
};
213+
214+
Specification specification(test_setup, cases);
215+
216+
int main()
217+
{
218+
return !Harness::run(specification);
219+
}

drivers/TimerEvent.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,31 @@ class TimerEvent : private NonCopyable<TimerEvent> {
4747
// The handler called to service the timer event of the derived class
4848
virtual void handler() = 0;
4949

50-
// insert relative timestamp in to linked list
50+
/** Set relative timestamp of the internal event.
51+
* @param timestamp event's us timestamp
52+
*
53+
* @warning
54+
* Do not insert more than one timestamp.
55+
* The same @a event object is used for every @a insert/insert_absolute call.
56+
*
57+
* @warning
58+
* Ticker's present timestamp is used for reference. For timestamps
59+
* from the past the event is scheduled after ticker's overflow.
60+
* For reference @see convert_timestamp
61+
*/
5162
void insert(timestamp_t timestamp);
5263

53-
// insert absolute timestamp into linked list
64+
/** Set absolute timestamp of the internal event.
65+
* @param timestamp event's us timestamp
66+
*
67+
* @warning
68+
* Do not insert more than one timestamp.
69+
* The same @a event object is used for every @a insert/insert_absolute call.
70+
*/
5471
void insert_absolute(us_timestamp_t timestamp);
5572

56-
// remove from linked list, if in it
73+
/** Remove timestamp.
74+
*/
5775
void remove();
5876

5977
ticker_event_t event;

targets/TARGET_ARM_SSG/TARGET_BEETLE/us_ticker.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp) {
100100

101101
void us_ticker_fire_interrupt(void)
102102
{
103-
uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
103+
uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER0);
104104
NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1);
105105
}
106106

targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp) {
199199

200200
void us_ticker_fire_interrupt(void)
201201
{
202+
us_ticker_int_counter = 0;
203+
us_ticker_int_remainder = 0;
204+
202205
#if defined(TARGET_KL43Z)
203206
NVIC_SetPendingIRQ(LPTMR0_IRQn);
204207
#else

targets/TARGET_Maxim/TARGET_MAX32600/us_ticker.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
236236

237237
void us_ticker_fire_interrupt(void)
238238
{
239-
NVIC_SetPendingIRQ(US_TIMER_IRQn);
239+
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
240+
US_TIMER->term_cnt32 = 1;
241+
US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
240242
}
241243

242244
//******************************************************************************

targets/TARGET_Maxim/TARGET_MAX32610/us_ticker.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
236236

237237
void us_ticker_fire_interrupt(void)
238238
{
239-
NVIC_SetPendingIRQ(US_TIMER_IRQn);
239+
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
240+
US_TIMER->term_cnt32 = 1;
241+
US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
240242
}
241243

242244
//******************************************************************************

targets/TARGET_Maxim/TARGET_MAX32620/us_ticker.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
267267

268268
void us_ticker_fire_interrupt(void)
269269
{
270-
NVIC_SetPendingIRQ(US_TIMER_IRQn);
270+
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
271+
US_TIMER->term_cnt32 = 1;
272+
US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
271273
}
272274

273275
//******************************************************************************

targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
230230

231231
void us_ticker_fire_interrupt(void)
232232
{
233-
NVIC_SetPendingIRQ(US_TIMER_IRQn);
233+
TMR32_SetCompare(US_TIMER, 1);
234234
}
235235

236236
//******************************************************************************

targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
230230

231231
void us_ticker_fire_interrupt(void)
232232
{
233-
NVIC_SetPendingIRQ(US_TIMER_IRQn);
233+
TMR32_SetCompare(US_TIMER, 1);
234234
}
235235

236236
//******************************************************************************

targets/TARGET_NORDIC/TARGET_MCU_NRF51822/us_ticker.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "PeripheralNames.h"
2121
#include "nrf_delay.h"
2222
#include "mbed_toolchain.h"
23+
#include "mbed_critical.h"
2324

2425
/*
2526
* Note: The micro-second timer API on the nRF51 platform is implemented using
@@ -52,6 +53,8 @@
5253
#define RTC_UNITS_TO_MICROSECONDS(RTC_UNITS) (((RTC_UNITS) * (uint64_t)1000000) / RTC_CLOCK_FREQ)
5354
#define MICROSECONDS_TO_RTC_UNITS(MICROS) ((((uint64_t)(MICROS) * RTC_CLOCK_FREQ) + 999999) / 1000000)
5455

56+
#define US_TICKER_SW_IRQ_MASK 0x1
57+
5558
static bool us_ticker_inited = false;
5659
static volatile uint32_t overflowCount; /**< The number of times the 24-bit RTC counter has overflowed. */
5760
static volatile bool us_ticker_callbackPending = false;
@@ -62,6 +65,9 @@ static bool os_tick_started = false; /**< flag indicating i
6265
*/
6366
static uint32_t previous_tick_cc_value = 0;
6467

68+
// us ticker fire interrupt flag for IRQ handler
69+
volatile uint8_t m_common_sw_irq_flag = 0;
70+
6571
/*
6672
RTX provide the following definitions which are used by the tick code:
6773
* os_trv: The number (minus 1) of clock cycle between two tick.
@@ -181,6 +187,11 @@ static inline uint32_t rtc1_getCounter(void)
181187
*/
182188
void us_ticker_handler(void)
183189
{
190+
if (m_common_sw_irq_flag & US_TICKER_SW_IRQ_MASK) {
191+
m_common_sw_irq_flag &= ~US_TICKER_SW_IRQ_MASK;
192+
us_ticker_irq_handler();
193+
}
194+
184195
if (NRF_RTC1->EVENTS_OVRFLW) {
185196
overflowCount++;
186197
NRF_RTC1->EVENTS_OVRFLW = 0;
@@ -287,7 +298,10 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
287298

288299
void us_ticker_fire_interrupt(void)
289300
{
301+
core_util_critical_section_enter();
302+
m_common_sw_irq_flag |= US_TICKER_SW_IRQ_MASK;
290303
NVIC_SetPendingIRQ(RTC1_IRQn);
304+
core_util_critical_section_exit();
291305
}
292306

293307
void us_ticker_disable_interrupt(void)

targets/TARGET_NORDIC/TARGET_NRF5/common_rtc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#define OS_TICK_CC_CHANNEL 1
3434
#define LP_TICKER_CC_CHANNEL 2
3535

36+
#define US_TICKER_SW_IRQ_MASK 0x1
37+
#define LP_TICKER_SW_IRQ_MASK 0x2
38+
3639
#define COMMON_RTC_EVENT_COMPARE(channel) \
3740
CONCAT_2(NRF_RTC_EVENT_COMPARE_, channel)
3841
#define COMMON_RTC_INT_COMPARE_MASK(channel) \
@@ -47,6 +50,7 @@
4750

4851
extern bool m_common_rtc_enabled;
4952
extern uint32_t volatile m_common_rtc_overflows;
53+
extern uint8_t volatile m_common_sw_irq_flag;
5054

5155
void common_rtc_init(void);
5256
uint32_t common_rtc_32bit_ticks_get(void);

0 commit comments

Comments
 (0)