|
1 | 1 | /* mbed Microcontroller Library
|
2 |
| - * Copyright (c) 2016 ARM Limited |
| 2 | + * Copyright (c) 2017 ARM Limited |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
13 | 13 | * See the License for the specific language governing permissions and
|
14 | 14 | * limitations under the License.
|
15 | 15 | */
|
| 16 | +#include "mbed.h" |
| 17 | +#include "greentea-client/test_env.h" |
| 18 | +#include "unity.h" |
| 19 | +#include "utest.h" |
| 20 | +#include "rtos.h" |
| 21 | +#include "lp_ticker_api_tests.h" |
| 22 | +#include "hal/lp_ticker_api.h" |
16 | 23 |
|
17 | 24 | #if !DEVICE_LOWPOWERTIMER
|
18 |
| - #error [NOT_SUPPORTED] Low power timer not supported for this target |
| 25 | +#error [NOT_SUPPORTED] test not supported |
19 | 26 | #endif
|
20 | 27 |
|
21 |
| -#include "utest/utest.h" |
22 |
| -#include "unity/unity.h" |
23 |
| -#include "greentea-client/test_env.h" |
24 |
| - |
25 |
| -#include "mbed.h" |
26 |
| -#include "lp_ticker_api.h" |
27 |
| - |
28 | 28 | using namespace utest::v1;
|
29 | 29 |
|
30 |
| -static volatile bool complete; |
31 |
| -static volatile timestamp_t complete_time; |
32 |
| -static ticker_event_t delay_event; |
33 |
| -static const ticker_data_t *lp_ticker_data = get_lp_ticker_data(); |
34 |
| -static Timer timer; |
35 |
| -static LowPowerTimer lp_timer; |
36 |
| - |
37 |
| -/* Timeouts are quite arbitrary due to large number of boards with varying level of accuracy */ |
38 |
| -#define LONG_TIMEOUT (100000) |
39 |
| -#define SHORT_TIMEOUT (600) |
40 |
| - |
41 |
| -void cb_done(uint32_t id) { |
42 |
| - if ((uint32_t)&delay_event == id) { |
43 |
| - complete_time = timer.read_us(); |
44 |
| - complete = true; |
45 |
| - } else { |
46 |
| - // Normal ticker handling |
47 |
| - TimerEvent::irq(id); |
48 |
| - } |
49 |
| -} |
| 30 | +volatile int intFlag = 0; |
50 | 31 |
|
51 |
| -void cb_done_deepsleep(uint32_t id) { |
52 |
| - if ((uint32_t)&delay_event == id) { |
53 |
| - complete_time = lp_timer.read_us(); |
54 |
| - complete = true; |
55 |
| - } else { |
56 |
| - // Normal ticker handling |
57 |
| - TimerEvent::irq(id); |
58 |
| - } |
59 |
| -} |
| 32 | +#define TICKER_INT_VAL 5000 |
| 33 | +#define TICKER_DELTA 50 |
60 | 34 |
|
61 |
| -void lp_ticker_delay_us(uint32_t delay_us, uint32_t tolerance) |
| 35 | +void ticker_event_handler_stub(const ticker_data_t * const ticker) |
62 | 36 | {
|
63 |
| - complete = false; |
64 |
| - uint32_t delay_ts; |
65 |
| - |
66 |
| - ticker_set_handler(lp_ticker_data, cb_done); |
67 |
| - ticker_remove_event(lp_ticker_data, &delay_event); |
68 |
| - delay_ts = ticker_read(lp_ticker_data) + delay_us; |
69 |
| - |
70 |
| - timer.reset(); |
71 |
| - timer.start(); |
72 |
| - ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event); |
73 |
| - while (!complete); |
74 |
| - timer.stop(); |
| 37 | + /* Indicate that ISR has been executed in interrupt context. */ |
| 38 | + if (IS_IRQ_MODE()) { |
| 39 | + intFlag++; |
| 40 | + } |
75 | 41 |
|
76 |
| - TEST_ASSERT_UINT32_WITHIN(tolerance, delay_us, complete_time); |
77 |
| - TEST_ASSERT_TRUE(complete); |
| 42 | + /* Clear and disable ticker interrupt. */ |
| 43 | + lp_ticker_clear_interrupt(); |
| 44 | + lp_ticker_disable_interrupt(); |
78 | 45 | }
|
79 | 46 |
|
80 |
| -#if DEVICE_SLEEP |
81 |
| -void lp_ticker_1s_deepsleep() |
| 47 | +void wait_cycles(volatile unsigned int cycles) |
82 | 48 | {
|
83 |
| - complete = false; |
84 |
| - uint32_t delay_ts; |
85 |
| - |
86 |
| - /* |
87 |
| - * Since deepsleep() may shut down the UART peripheral, we wait for 10ms |
88 |
| - * to allow for hardware serial buffers to completely flush. |
89 |
| -
|
90 |
| - * This should be replaced with a better function that checks if the |
91 |
| - * hardware buffers are empty. However, such an API does not exist now, |
92 |
| - * so we'll use the wait_ms() function for now. |
93 |
| - */ |
94 |
| - wait_ms(10); |
95 |
| - |
96 |
| - ticker_set_handler(lp_ticker_data, cb_done_deepsleep); |
97 |
| - ticker_remove_event(lp_ticker_data, &delay_event); |
98 |
| - delay_ts = ticker_read(lp_ticker_data) + 1000000; |
99 |
| - |
100 |
| - /* |
101 |
| - * We use here the low power timer instead of microsecond timer for start and |
102 |
| - * end because the microseconds timer might be disable during deepsleep. |
103 |
| - */ |
104 |
| - lp_timer.reset(); |
105 |
| - lp_timer.start(); |
106 |
| - ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event); |
107 |
| - /* Make sure deepsleep is allowed, to go to deepsleep */ |
108 |
| - bool deep_sleep_allowed = sleep_manager_can_deep_sleep(); |
109 |
| - TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed"); |
110 |
| - sleep(); |
111 |
| - while (!complete); |
112 |
| - lp_timer.stop(); |
113 |
| - |
114 |
| - TEST_ASSERT_UINT32_WITHIN(LONG_TIMEOUT, 1000000, complete_time); |
115 |
| - TEST_ASSERT_TRUE(complete); |
| 49 | + while (cycles--); |
116 | 50 | }
|
117 | 51 |
|
118 |
| -void lp_ticker_1s_sleep() |
| 52 | +/* Test that the ticker has the correct frequency and number of bits. */ |
| 53 | +void lp_ticker_info_test() |
119 | 54 | {
|
120 |
| - complete = false; |
121 |
| - uint32_t delay_ts; |
122 |
| - |
123 |
| - ticker_set_handler(lp_ticker_data, cb_done); |
124 |
| - ticker_remove_event(lp_ticker_data, &delay_event); |
125 |
| - delay_ts = ticker_read(lp_ticker_data) + 1000000; |
126 |
| - |
127 |
| - sleep_manager_lock_deep_sleep(); |
128 |
| - timer.reset(); |
129 |
| - timer.start(); |
130 |
| - bool deep_sleep_allowed = sleep_manager_can_deep_sleep(); |
131 |
| - TEST_ASSERT_FALSE_MESSAGE(deep_sleep_allowed, "Deep sleep should be disallowed"); |
132 |
| - ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event); |
133 |
| - sleep(); |
134 |
| - while (!complete); |
135 |
| - timer.stop(); |
136 |
| - sleep_manager_unlock_deep_sleep(); |
137 |
| - |
138 |
| - TEST_ASSERT_UINT32_WITHIN(LONG_TIMEOUT, 1000000, complete_time); |
139 |
| - TEST_ASSERT_TRUE(complete); |
140 |
| -} |
141 |
| -#endif /* DEVICE_SLEEP */ |
| 55 | + const ticker_info_t* p_ticker_info = lp_ticker_get_info(); |
142 | 56 |
|
143 |
| -void lp_ticker_500us(void) |
144 |
| -{ |
145 |
| - lp_ticker_delay_us(500, SHORT_TIMEOUT); |
| 57 | + TEST_ASSERT(p_ticker_info->frequency >= 8000); |
| 58 | + TEST_ASSERT(p_ticker_info->frequency <= 64000); |
| 59 | + TEST_ASSERT(p_ticker_info->bits >= 12); |
146 | 60 | }
|
147 | 61 |
|
148 |
| -void lp_ticker_1ms(void) |
| 62 | +/* Test that the ticker continues operating in deep sleep mode. */ |
| 63 | +void lp_ticker_deepsleep_test() |
149 | 64 | {
|
150 |
| - lp_ticker_delay_us(1000, SHORT_TIMEOUT); |
151 |
| -} |
| 65 | + intFlag = 0; |
152 | 66 |
|
153 |
| -void lp_ticker_1s(void) |
154 |
| -{ |
155 |
| - lp_ticker_delay_us(1000000, LONG_TIMEOUT); |
156 |
| -} |
| 67 | + set_lp_ticker_irq_handler(ticker_event_handler_stub); |
157 | 68 |
|
158 |
| -void lp_ticker_5s(void) |
159 |
| -{ |
160 |
| - lp_ticker_delay_us(5000000, LONG_TIMEOUT); |
| 69 | + lp_ticker_init(); |
| 70 | + |
| 71 | + /* Wait for green tea UART transmission before entering deep-sleep mode. */ |
| 72 | + wait_cycles(40000); |
| 73 | + |
| 74 | + const uint32_t tick_count = lp_ticker_read(); |
| 75 | + |
| 76 | + /* Set interrupt. Interrupt should be fired when tick count is equal to: |
| 77 | + * tick_count + TICKER_INT_VAL. */ |
| 78 | + lp_ticker_set_interrupt(tick_count + TICKER_INT_VAL); |
| 79 | + |
| 80 | + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); |
| 81 | + |
| 82 | + while (!intFlag) { |
| 83 | + sleep(); |
| 84 | + } |
| 85 | + |
| 86 | + TEST_ASSERT_EQUAL(1, intFlag); |
161 | 87 | }
|
162 | 88 |
|
163 |
| -utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) { |
164 |
| - greentea_case_failure_abort_handler(source, reason); |
165 |
| - return STATUS_CONTINUE; |
| 89 | +utest::v1::status_t test_setup(const size_t number_of_cases) |
| 90 | +{ |
| 91 | + GREENTEA_SETUP(20, "default_auto"); |
| 92 | + return verbose_test_setup_handler(number_of_cases); |
166 | 93 | }
|
167 | 94 |
|
168 | 95 | Case cases[] = {
|
169 |
| - Case("500us lp_ticker", lp_ticker_500us, greentea_failure_handler), |
170 |
| - Case("1ms lp_ticker", lp_ticker_1ms, greentea_failure_handler), |
171 |
| - Case("1s lp_ticker", lp_ticker_1s, greentea_failure_handler), |
172 |
| - Case("5s lp_ticker", lp_ticker_5s, greentea_failure_handler), |
173 |
| -#if DEVICE_SLEEP |
174 |
| - Case("1s lp_ticker sleep", lp_ticker_1s_sleep, greentea_failure_handler), |
175 |
| - Case("1s lp_ticker deepsleep", lp_ticker_1s_deepsleep, greentea_failure_handler), |
176 |
| -#endif /* DEVICE_SLEEP */ |
| 96 | + Case("lp ticker info test", lp_ticker_info_test), |
| 97 | + Case("lp ticker sleep test", lp_ticker_deepsleep_test), |
177 | 98 | };
|
178 | 99 |
|
179 |
| -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) { |
180 |
| - GREENTEA_SETUP(20, "default_auto"); |
181 |
| - lp_ticker_data->interface->init(); |
182 |
| - return greentea_test_setup_handler(number_of_cases); |
183 |
| -} |
| 100 | +Specification specification(test_setup, cases); |
184 | 101 |
|
185 |
| -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); |
186 |
| - |
187 |
| -int main() { |
188 |
| - Harness::run(specification); |
| 102 | +int main() |
| 103 | +{ |
| 104 | + return !Harness::run(specification); |
189 | 105 | }
|
0 commit comments