Skip to content

Commit e81d4f1

Browse files
authored
Merge pull request #5509 from mprse/feature-hal-spec-sleep_tests
Add tests for Sleep HAL API
2 parents 4c98293 + 7ee9b0e commit e81d4f1

File tree

6 files changed

+430
-111
lines changed

6 files changed

+430
-111
lines changed

TESTS/mbed_drivers/ticker/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include "utest/utest.h"
1919
#include "unity/unity.h"
2020

21+
#if !DEVICE_USTICKER
22+
#error [NOT_SUPPORTED] test not supported
23+
#endif
2124

2225
using utest::v1::Case;
2326

TESTS/mbed_drivers/timer/main.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
#include "rtos.h"
2323
#include "hal/us_ticker_api.h"
2424

25+
#if !DEVICE_USTICKER
26+
#error [NOT_SUPPORTED] test not supported
27+
#endif
28+
2529
using namespace utest::v1;
2630

2731
extern uint32_t SystemCoreClock;

TESTS/mbed_hal/sleep/main.cpp

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
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+
17+
#if !DEVICE_SLEEP
18+
#error [NOT_SUPPORTED] sleep not supported for this target
19+
#endif
20+
21+
#include "mbed.h"
22+
23+
#include "utest/utest.h"
24+
#include "unity/unity.h"
25+
#include "greentea-client/test_env.h"
26+
27+
#include "sleep_api_tests.h"
28+
29+
#define US_PER_S 1000000
30+
31+
unsigned int ticks_to_us(unsigned int ticks, unsigned int freq)
32+
{
33+
return (unsigned int)((unsigned long long)ticks * US_PER_S / freq);
34+
}
35+
36+
unsigned int us_to_ticks(unsigned int us, unsigned int freq)
37+
{
38+
return (unsigned int)((unsigned long long)us * freq / US_PER_S);
39+
}
40+
41+
using namespace utest::v1;
42+
43+
/* The following ticker frequencies are possible:
44+
* high frequency ticker: 250 KHz (1 tick per 4 us) - 8 Mhz (1 tick per 1/8 us)
45+
* low power ticker: 8 KHz (1 tick per 125 us) - 64 KHz (1 tick per ~15.6 us)
46+
*/
47+
48+
/* Used for regular sleep mode, a target should be awake within 10 us. Define us delta value as follows:
49+
* delta = default 10 us + worst ticker resolution + extra time for code execution */
50+
static const uint32_t sleep_mode_delta_us = (10 + 4 + 5);
51+
52+
/* Used for deep-sleep mode, a target should be awake within 10 ms. Define us delta value as follows:
53+
* delta = default 10 ms + worst ticker resolution + extra time for code execution */
54+
static const uint32_t deepsleep_mode_delta_us = (10000 + 125 + 5);
55+
56+
57+
void us_ticker_isr(const ticker_data_t *const ticker_data)
58+
{
59+
us_ticker_clear_interrupt();
60+
}
61+
62+
#ifdef DEVICE_LOWPOWERTIMER
63+
void lp_ticker_isr(const ticker_data_t *const ticker_data)
64+
{
65+
lp_ticker_clear_interrupt();
66+
}
67+
#endif
68+
69+
/* Test that wake-up time from sleep should be less than 10 us and
70+
* high frequency ticker interrupt can wake-up target from sleep. */
71+
void sleep_usticker_test()
72+
{
73+
Timeout timeout;
74+
const ticker_data_t * ticker = get_us_ticker_data();
75+
const unsigned int ticker_freq = ticker->interface->get_info()->frequency;
76+
77+
const ticker_irq_handler_type us_ticker_irq_handler_org = set_us_ticker_irq_handler(us_ticker_isr);
78+
79+
/* Test only sleep functionality. */
80+
sleep_manager_lock_deep_sleep();
81+
TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should be locked");
82+
83+
/* Testing wake-up time 10 us. */
84+
for (timestamp_t i = 100; i < 1000; i += 100) {
85+
/* note: us_ticker_read() operates on ticks. */
86+
87+
const timestamp_t next_match_timestamp = us_ticker_read() + us_to_ticks(i, ticker_freq);
88+
us_ticker_set_interrupt(next_match_timestamp);
89+
90+
sleep();
91+
92+
TEST_ASSERT_UINT32_WITHIN(us_to_ticks(sleep_mode_delta_us, ticker_freq), next_match_timestamp,
93+
us_ticker_read());
94+
}
95+
96+
set_us_ticker_irq_handler(us_ticker_irq_handler_org);
97+
98+
sleep_manager_unlock_deep_sleep();
99+
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
100+
}
101+
102+
#ifdef DEVICE_LOWPOWERTIMER
103+
104+
/* Test that wake-up time from sleep should be less than 10 ms and
105+
* low power ticker interrupt can wake-up target from sleep. */
106+
void deepsleep_lpticker_test()
107+
{
108+
const ticker_data_t * ticker = get_us_ticker_data();
109+
const unsigned int ticker_freq = ticker->interface->get_info()->frequency;
110+
111+
const ticker_irq_handler_type lp_ticker_irq_handler_org = set_lp_ticker_irq_handler(lp_ticker_isr);
112+
113+
/* Give some time Green Tea to finish UART transmission before entering
114+
* deep-sleep mode.
115+
*/
116+
wait_ms(10);
117+
118+
TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should not be locked");
119+
120+
/* Testing wake-up time 10 ms. */
121+
for (timestamp_t i = 20000; i < 200000; i += 20000) {
122+
/* note: lp_ticker_read() operates on ticks. */
123+
const timestamp_t next_match_timestamp = lp_ticker_read() + us_to_ticks(i, ticker_freq);
124+
lp_ticker_set_interrupt(next_match_timestamp);
125+
126+
sleep();
127+
128+
TEST_ASSERT_UINT32_WITHIN(us_to_ticks(deepsleep_mode_delta_us, ticker_freq), next_match_timestamp,
129+
lp_ticker_read());
130+
}
131+
132+
set_lp_ticker_irq_handler(lp_ticker_irq_handler_org);
133+
134+
}
135+
136+
void deepsleep_high_speed_clocks_turned_off_test()
137+
{
138+
const ticker_data_t * us_ticker = get_us_ticker_data();
139+
const ticker_data_t * lp_ticker = get_lp_ticker_data();
140+
const unsigned int us_ticker_freq = us_ticker->interface->get_info()->frequency;
141+
const unsigned int lp_ticker_freq = lp_ticker->interface->get_info()->frequency;
142+
143+
/* Give some time Green Tea to finish UART transmission before entering
144+
* deep-sleep mode.
145+
*/
146+
wait_ms(10);
147+
148+
TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should not be locked");
149+
150+
const unsigned int us_ticks_before_sleep = us_ticker_read();
151+
152+
const timestamp_t wakeup_time = lp_ticker_read() + us_to_ticks(200000, lp_ticker_freq);
153+
lp_ticker_set_interrupt(wakeup_time);
154+
155+
sleep();
156+
157+
const unsigned int us_ticks_after_sleep = us_ticker_read();
158+
const unsigned int lp_ticks_after_sleep = lp_ticker_read();
159+
160+
/* High freqency ticker should be disabled in deep-sleep mode. We expect that time difference between
161+
* ticker reads before and after the sleep represents only code execution time between calls.
162+
* Since we went to sleep for about 200 ms check if time counted by high frequency timer does not
163+
* exceed 1 ms.
164+
*/
165+
TEST_ASSERT_UINT32_WITHIN(1000, 0, ticks_to_us(us_ticks_after_sleep - us_ticks_before_sleep, us_ticker_freq));
166+
167+
/* Check if we have woken-up after expected time. */
168+
TEST_ASSERT_UINT32_WITHIN(us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), wakeup_time, lp_ticks_after_sleep);
169+
}
170+
171+
#endif
172+
173+
utest::v1::status_t greentea_failure_handler(const Case * const source, const failure_t reason)
174+
{
175+
greentea_case_failure_abort_handler(source, reason);
176+
return STATUS_CONTINUE;
177+
}
178+
179+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
180+
{
181+
GREENTEA_SETUP(60, "default_auto");
182+
us_ticker_init();
183+
#if DEVICE_LOWPOWERTIMER
184+
lp_ticker_init();
185+
#endif
186+
/* Suspend RTOS Kernel to enable sleep modes. */
187+
osKernelSuspend();
188+
return greentea_test_setup_handler(number_of_cases);
189+
}
190+
191+
Case cases[] = {
192+
Case("sleep - source of wake-up - us ticker", sleep_usticker_test, greentea_failure_handler),
193+
#if DEVICE_LOWPOWERTIMER
194+
Case("deep-sleep - source of wake-up - lp ticker",deepsleep_lpticker_test, greentea_failure_handler),
195+
Case("deep-sleep - high-speed clocks are turned off",deepsleep_high_speed_clocks_turned_off_test, greentea_failure_handler),
196+
#endif
197+
};
198+
199+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
200+
201+
int main() {
202+
Harness::run(specification);
203+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
17+
/** \addtogroup hal_sleep_tests */
18+
/** @{*/
19+
20+
#ifndef MBED_SLEEP_API_TESTS_H
21+
#define MBED_SLEEP_API_TESTS_H
22+
23+
#include "device.h"
24+
25+
#if DEVICE_SLEEP
26+
27+
#ifdef __cplusplus
28+
extern "C" {
29+
#endif
30+
31+
/** High frequency ticker interrupt can wake up from sleep (locked deep-sleep).
32+
*
33+
* Given is an environment with high frequency ticker.
34+
* When the board enters sleep mode.
35+
* Then the board can be wake up from the sleep by high frequency ticker interrupt and
36+
* wake-up time should be less than 10 us.
37+
*/
38+
void sleep_usticker_test();
39+
40+
/** Low power ticker interrupt to wake up from deep-sleep (unlocked deep-sleep).
41+
*
42+
* Given is an environment with low power ticker.
43+
* When the board enters deep-sleep mode.
44+
* Then the board can be wake up from the sleep by low power ticker interrupt and
45+
* wake-up time should be less than 10 ms.
46+
*
47+
*/
48+
void deepsleep_lpticker_test();
49+
50+
/** High speed clocks are turned off in deep-sleep (unlocked deep-sleep)
51+
*
52+
* Given is an environment with high frequency ticker.
53+
* When the board enters deep-sleep mode.
54+
* Then high frequency ticker does not count while the board is in the deep-sleep mode.
55+
*
56+
*/
57+
void deepsleep_high_speed_clocks_turned_off_test();
58+
59+
/**@}*/
60+
61+
#ifdef __cplusplus
62+
}
63+
#endif
64+
65+
#endif
66+
67+
#endif
68+
69+
/**@}*/

hal/sleep_api.h

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,42 @@
2727
extern "C" {
2828
#endif
2929

30+
/**
31+
* \defgroup hal_sleep sleep hal requirements
32+
* Low level interface to the sleep mode of a target.
33+
*
34+
* # Defined behaviour
35+
*
36+
* * Sleep mode
37+
* * wake-up time should be less than 10 us - Verified by sleep_usticker_test().
38+
* * the processor can be woken up by any internal peripheral interrupt - Verified by sleep_usticker_test().
39+
* * all peripherals operate as in run mode - not verified.
40+
* * the processor can be woken up by external pin interrupt - not verified.
41+
* * Deep sleep
42+
* * the wake-up time should be less than 10 ms - Verified by deepsleep_lpticker_test().
43+
* * lp ticker should wake up a target from this mode - Verified by deepsleep_lpticker_test().
44+
* * RTC should wake up a target from this mode - not verified.
45+
* * an external interrupt on a pin should wake up a target from this mode - not verified.
46+
* * a watchdog timer should wake up a target from this mode - not verified.
47+
* * High-speed clocks are turned off - Verified by deepsleep_high_speed_clocks_turned_off_test().
48+
* * RTC keeps time - Verified by rtc_sleep_test().
49+
*
50+
* # Undefined behaviour
51+
*
52+
* * peripherals aside from RTC, GPIO and lp ticker result in undefined behaviour in deep sleep.
53+
* @{
54+
*/
55+
56+
/**
57+
* \defgroup hal_sleep_tests sleep hal tests
58+
* The sleep HAL tests ensure driver conformance to defined behaviour.
59+
*
60+
* To run the sleep hal tests use the command:
61+
*
62+
* mbed test -t <toolchain> -m <target> -n tests-mbed_hal-sleep*
63+
*
64+
*/
65+
3066
/** Send the microcontroller to sleep
3167
*
3268
* The processor is setup ready for sleep, and sent to sleep. In this mode, the
@@ -53,6 +89,8 @@ void hal_sleep(void);
5389
*/
5490
void hal_deepsleep(void);
5591

92+
/**@}*/
93+
5694
#ifdef __cplusplus
5795
}
5896
#endif
@@ -61,4 +99,4 @@ void hal_deepsleep(void);
6199

62100
#endif
63101

64-
/** @}*/
102+
/**@}*/

0 commit comments

Comments
 (0)