Update deep sleep lock check in tests

When the define LPTICKER_DELAY_TICKS is set deep sleep can be randomly
disallowed when using the low power ticker. This is because a Timer
object, which locks deep sleep, is used to protect from back-to-back
writes to lp tickers which can't support that. This causes tests which
assert that deep sleep is allowed to intermittently fail.

To fix this intermittent failure this patch adds the function
sleep_manager_can_deep_sleep_test_check() which checks if deep sleep
is allowed over a duration. It updates all the tests to use
sleep_manager_can_deep_sleep_test_check() rather
than sleep_manager_can_deep_sleep() so the tests work even if deep
sleep is spuriously blocked.
pull/7524/head
Russ Butler 2018-07-12 11:36:13 -05:00
parent 1bbf43ad38
commit 472ababfef
9 changed files with 57 additions and 32 deletions

View File

@ -29,90 +29,90 @@ using namespace utest::v1;
void deep_sleep_lock_lock_test()
{
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Check basic usage works
DeepSleepLock lock;
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep_test_check());
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Check that unlock and lock change can deep sleep as expected
DeepSleepLock lock;
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep_test_check());
lock.unlock();
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
lock.lock();
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep_test_check());
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Check that unlock releases sleep based on count
DeepSleepLock lock;
lock.lock();
lock.lock();
lock.unlock();
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep_test_check());
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Check that unbalanced locks do not leave deep sleep locked
DeepSleepLock lock;
lock.lock();
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep_test_check());
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
}
void timer_lock_test()
{
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Just creating a timer object does not lock sleep
Timer timer;
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Starting a timer does lock sleep
Timer timer;
timer.start();
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(false, sleep_manager_can_deep_sleep_test_check());
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Stopping a timer after starting it allows sleep
Timer timer;
timer.start();
timer.stop();
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Starting a timer multiple times still lets you sleep
Timer timer;
timer.start();
timer.start();
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
{
// Stopping a timer multiple times still lets you sleep
Timer timer;
timer.start();
timer.stop();
timer.stop();
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
}
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep());
TEST_ASSERT_EQUAL(true, sleep_manager_can_deep_sleep_test_check());
}
Case cases[] = {

View File

@ -263,7 +263,7 @@ void test_sleep(void)
timer.start();
timeout.attach_callback(mbed::callback(sem_callback, &sem), delay_us);
bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
bool deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_FALSE_MESSAGE(deep_sleep_allowed, "Deep sleep should be disallowed");
while (sem.wait(0) != 1) {
sleep();
@ -322,7 +322,7 @@ void test_deepsleep(void)
timer.start();
timeout.attach_callback(mbed::callback(sem_callback, &sem), delay_us);
bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
bool deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed");
while (sem.wait(0) != 1) {
sleep();

View File

@ -130,7 +130,7 @@ void lp_ticker_deepsleep_test()
* tick_count + TICKER_INT_VAL. */
lp_ticker_set_interrupt(tick_count + TICKER_INT_VAL);
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check());
while (!intFlag) {
sleep();

View File

@ -74,7 +74,7 @@ void rtc_sleep_test_support(bool deepsleep_mode)
timeout.attach(callback, DELAY_4S);
TEST_ASSERT(sleep_manager_can_deep_sleep() == deepsleep_mode);
TEST_ASSERT(sleep_manager_can_deep_sleep_test_check() == deepsleep_mode);
while (!expired) {
sleep();

View File

@ -25,15 +25,15 @@ using namespace utest::v1;
void sleep_manager_deepsleep_counter_test()
{
bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
bool deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_TRUE(deep_sleep_allowed);
sleep_manager_lock_deep_sleep();
deep_sleep_allowed = sleep_manager_can_deep_sleep();
deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_FALSE(deep_sleep_allowed);
sleep_manager_unlock_deep_sleep();
deep_sleep_allowed = sleep_manager_can_deep_sleep();
deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_TRUE(deep_sleep_allowed);
}

View File

@ -55,7 +55,7 @@ void sleep_manager_multithread_test()
t2.join();
}
bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
bool deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed");
}
@ -83,7 +83,7 @@ void sleep_manager_irq_test()
timer.stop();
}
bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
bool deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed");
}

View File

@ -313,7 +313,7 @@ void test_deepsleep(void)
lptimer.start();
st.schedule_tick(TEST_TICKS);
TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be allowed");
TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep_test_check(), "Deep sleep should be allowed");
while (st.sem_wait(0) != 1) {
sleep();
}

View File

@ -21,6 +21,7 @@
#include "mbed_error.h"
#include "mbed_debug.h"
#include "mbed_stats.h"
#include "us_ticker_api.h"
#include "lp_ticker_api.h"
#include <limits.h>
#include <stdio.h>
@ -183,6 +184,19 @@ bool sleep_manager_can_deep_sleep(void)
return deep_sleep_lock == 0 ? true : false;
}
bool sleep_manager_can_deep_sleep_test_check()
{
const uint32_t check_time_us = 2000;
const ticker_data_t *const ticker = get_us_ticker_data();
uint32_t start = ticker_read(ticker);
while ((ticker_read(ticker) - start) < check_time_us) {
if (sleep_manager_can_deep_sleep()) {
return true;
}
}
return false;
}
void sleep_manager_sleep_auto(void)
{
#ifdef MBED_SLEEP_TRACING_ENABLED

View File

@ -122,6 +122,17 @@ void sleep_manager_unlock_deep_sleep_internal(void);
*/
bool sleep_manager_can_deep_sleep(void);
/** Check if the target can deep sleep within a period of time
*
* This function in intended for use in testing. The amount
* of time this functions waits for deeps sleep to be available
* is currently 2ms. This may change in the future depending
* on testing requirements.
*
* @return true if a target can go to deepsleep, false otherwise
*/
bool sleep_manager_can_deep_sleep_test_check(void);
/** Enter auto selected sleep mode. It chooses the sleep or deeepsleep modes based
* on the deepsleep locking counter
*