|
28 | 28 |
|
29 | 29 | #define SLEEP_DURATION_US 20000ULL
|
30 | 30 | #define DEEP_SLEEP_TEST_CHECK_WAIT_US 2000
|
31 |
| -#define DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US 500 |
| 31 | +#define DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US 600 |
32 | 32 |
|
33 | 33 | using utest::v1::Case;
|
34 | 34 | using utest::v1::Specification;
|
@@ -86,29 +86,31 @@ utest::v1::status_t testcase_setup(const Case *const source, const size_t index_
|
86 | 86 | {
|
87 | 87 | // Suspend the RTOS kernel scheduler to prevent interference with duration of sleep.
|
88 | 88 | osKernelSuspend();
|
89 |
| - |
90 | 89 | #if DEVICE_LPTICKER
|
| 90 | + ticker_suspend(get_lp_ticker_data()); |
91 | 91 | #if (LPTICKER_DELAY_TICKS > 0)
|
92 | 92 | // Suspend the low power ticker wrapper to prevent interference with deep sleep lock.
|
93 | 93 | lp_ticker_wrapper_suspend();
|
94 | 94 | #endif
|
95 |
| - lp_ticker_init(); |
96 | 95 | #endif
|
97 |
| -#if DEVICE_USTICKER |
| 96 | + ticker_suspend(get_us_ticker_data()); |
98 | 97 | // Make sure HAL tickers are initialized.
|
99 | 98 | us_ticker_init();
|
| 99 | +#if DEVICE_LPTICKER |
| 100 | + lp_ticker_init(); |
100 | 101 | #endif
|
101 |
| - |
102 | 102 | return utest::v1::greentea_case_setup_handler(source, index_of_case);
|
103 | 103 | }
|
104 | 104 |
|
105 | 105 | utest::v1::status_t testcase_teardown(const Case *const source, const size_t passed, const size_t failed,
|
106 | 106 | const utest::v1::failure_t failure)
|
107 | 107 | {
|
| 108 | + ticker_resume(get_us_ticker_data()); |
108 | 109 | #if DEVICE_LPTICKER
|
109 | 110 | #if (LPTICKER_DELAY_TICKS > 0)
|
110 | 111 | lp_ticker_wrapper_resume();
|
111 | 112 | #endif
|
| 113 | + ticker_resume(get_lp_ticker_data()); |
112 | 114 | #endif
|
113 | 115 | osKernelResume(0);
|
114 | 116 | return utest::v1::greentea_case_teardown_handler(source, passed, failed, failure);
|
@@ -209,53 +211,88 @@ void test_sleep_auto()
|
209 | 211 | }
|
210 | 212 | #endif
|
211 | 213 |
|
| 214 | +#define US_PER_S 1000000 |
| 215 | + |
| 216 | +uint32_t diff_us(uint32_t start_ticks, uint32_t stop_ticks, const ticker_info_t *info) |
| 217 | +{ |
| 218 | + uint32_t counter_mask = ((1 << info->bits) - 1); |
| 219 | + |
| 220 | + uint32_t diff_ticks = ((stop_ticks - start_ticks) & counter_mask); |
| 221 | + |
| 222 | + return (uint32_t)((uint64_t) diff_ticks * US_PER_S / info->frequency); |
| 223 | +} |
| 224 | + |
| 225 | +uint32_t us_to_ticks(uint32_t us, const ticker_info_t *info) |
| 226 | +{ |
| 227 | + return (uint32_t)((uint32_t) us * info->frequency / US_PER_S); |
| 228 | +} |
| 229 | + |
| 230 | +volatile bool unlock_deep_sleep = false; |
| 231 | + |
| 232 | +void ticker_event_handler_stub(const ticker_data_t *const ticker) |
| 233 | +{ |
| 234 | + if (unlock_deep_sleep) { |
| 235 | + sleep_manager_unlock_deep_sleep_internal(); |
| 236 | + unlock_deep_sleep = false; |
| 237 | + } |
| 238 | +} |
| 239 | + |
| 240 | +ticker_irq_handler_type prev_irq_handler; |
| 241 | + |
212 | 242 | void test_lock_unlock_test_check()
|
213 | 243 | {
|
214 |
| - // Make sure HAL tickers are initialized. |
215 |
| - ticker_read(get_us_ticker_data()); |
216 |
| - ticker_read(get_lp_ticker_data()); |
| 244 | + prev_irq_handler = set_lp_ticker_irq_handler(ticker_event_handler_stub); |
217 | 245 |
|
218 |
| - // Use LowPowerTimer instead of Timer to prevent deep sleep lock. |
219 |
| - LowPowerTimer lp_timer; |
220 |
| - us_timestamp_t exec_time_unlocked, exec_time_locked; |
221 |
| - LowPowerTimeout lp_timeout; |
| 246 | + for (int i = 0; i < 1000; i++) { |
222 | 247 |
|
223 |
| - // Deep sleep unlocked: |
224 |
| - // * sleep_manager_can_deep_sleep() returns true, |
225 |
| - // * sleep_manager_can_deep_sleep_test_check() returns true instantly. |
226 |
| - TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check()); |
227 |
| - lp_timer.start(); |
228 |
| - TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check()); |
229 |
| - lp_timer.stop(); |
230 |
| - exec_time_unlocked = lp_timer.read_high_resolution_us(); |
| 248 | + wraparound_lp_protect(); |
231 | 249 |
|
232 |
| - // Deep sleep locked: |
233 |
| - // * sleep_manager_can_deep_sleep() returns false, |
234 |
| - // * sleep_manager_can_deep_sleep_test_check() returns false with 2 ms delay. |
235 |
| - sleep_manager_lock_deep_sleep(); |
236 |
| - TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); |
237 |
| - lp_timer.reset(); |
238 |
| - lp_timer.start(); |
239 |
| - TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep_test_check()); |
240 |
| - lp_timer.stop(); |
241 |
| - exec_time_locked = lp_timer.read_high_resolution_us(); |
242 |
| - TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US, DEEP_SLEEP_TEST_CHECK_WAIT_US, |
243 |
| - exec_time_locked - exec_time_unlocked); |
244 |
| - |
245 |
| - // Deep sleep unlocked with a 1 ms delay: |
246 |
| - // * sleep_manager_can_deep_sleep() returns false, |
247 |
| - // * sleep_manager_can_deep_sleep_test_check() returns true with a 1 ms delay, |
248 |
| - // * sleep_manager_can_deep_sleep() returns true when checked again. |
249 |
| - lp_timer.reset(); |
250 |
| - lp_timeout.attach_us(mbed::callback(sleep_manager_unlock_deep_sleep_internal), |
251 |
| - DEEP_SLEEP_TEST_CHECK_WAIT_US / 2); |
252 |
| - lp_timer.start(); |
253 |
| - TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); |
254 |
| - TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check()); |
255 |
| - lp_timer.stop(); |
256 |
| - TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US, DEEP_SLEEP_TEST_CHECK_WAIT_US / 2, |
257 |
| - lp_timer.read_high_resolution_us()); |
258 |
| - TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); |
| 250 | + const ticker_info_t *p_ticker_info = get_lp_ticker_data()->interface->get_info(); |
| 251 | + |
| 252 | + // Use LowPowerTimer instead of Timer to prevent deep sleep lock. |
| 253 | + us_timestamp_t exec_time_unlocked, exec_time_locked; |
| 254 | + uint32_t start, stop; |
| 255 | + |
| 256 | + // Deep sleep unlocked: |
| 257 | + // * sleep_manager_can_deep_sleep() returns true, |
| 258 | + // * sleep_manager_can_deep_sleep_test_check() returns true instantly. |
| 259 | + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); |
| 260 | + start = lp_ticker_read(); |
| 261 | + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check()); |
| 262 | + stop = lp_ticker_read(); |
| 263 | + exec_time_unlocked = diff_us(start, stop, p_ticker_info); |
| 264 | + |
| 265 | + // Deep sleep locked: |
| 266 | + // * sleep_manager_can_deep_sleep() returns false, |
| 267 | + // * sleep_manager_can_deep_sleep_test_check() returns false with 2 ms delay. |
| 268 | + sleep_manager_lock_deep_sleep(); |
| 269 | + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); |
| 270 | + start = lp_ticker_read(); |
| 271 | + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep_test_check()); |
| 272 | + stop = lp_ticker_read(); |
| 273 | + exec_time_locked = diff_us(start, stop, p_ticker_info); |
| 274 | + TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US, DEEP_SLEEP_TEST_CHECK_WAIT_US, |
| 275 | + exec_time_locked - exec_time_unlocked); |
| 276 | + |
| 277 | + // Deep sleep unlocked with a 1 ms delay: |
| 278 | + // * sleep_manager_can_deep_sleep() returns false, |
| 279 | + // * sleep_manager_can_deep_sleep_test_check() returns true with a 1 ms delay, |
| 280 | + // * sleep_manager_can_deep_sleep() returns true when checked again. |
| 281 | + unlock_deep_sleep = true; |
| 282 | + lp_ticker_set_interrupt(lp_ticker_read() + us_to_ticks(DEEP_SLEEP_TEST_CHECK_WAIT_US / 2, p_ticker_info)); |
| 283 | + |
| 284 | + start = lp_ticker_read(); |
| 285 | + // Extra wait after setting interrupt to handle CMPOK |
| 286 | + wait_ns(100000); |
| 287 | + TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep()); |
| 288 | + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check()); |
| 289 | + stop = lp_ticker_read(); |
| 290 | + TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US, DEEP_SLEEP_TEST_CHECK_WAIT_US / 2, |
| 291 | + diff_us(start, stop, p_ticker_info)); |
| 292 | + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); |
| 293 | + } |
| 294 | + |
| 295 | + set_lp_ticker_irq_handler(prev_irq_handler); |
259 | 296 | }
|
260 | 297 | #endif
|
261 | 298 |
|
@@ -284,7 +321,7 @@ Case cases[] = {
|
284 | 321 | Case("deep sleep lock/unlock test_check",
|
285 | 322 | (utest::v1::case_setup_handler_t) testcase_setup,
|
286 | 323 | test_lock_unlock_test_check,
|
287 |
| - (utest::v1::case_teardown_handler_t) testcase_teardown), |
| 324 | + (utest::v1::case_teardown_handler_t) testcase_teardown) |
288 | 325 | #endif
|
289 | 326 | };
|
290 | 327 |
|
|
0 commit comments