Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ladislas/feature/deep sleep core buffered serial #1162

Merged
merged 4 commits into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions drivers/CoreBufferedSerial/include/CoreBufferedSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class CoreBufferedSerial : public interface::BufferedSerial

auto readable() -> bool final;

void enable_input() final;
void disable_input() final;

void sigio(mbed::Callback<void()> func) final;

private:
Expand Down
10 changes: 10 additions & 0 deletions drivers/CoreBufferedSerial/source/CoreBufferedSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ auto CoreBufferedSerial::readable() -> bool
return _serial.readable();
}

void CoreBufferedSerial::enable_input()
{
_serial.enable_input(true);
}

void CoreBufferedSerial::disable_input()
{
_serial.enable_input(false);
}

void CoreBufferedSerial::sigio(mbed::Callback<void()> func)
{
_serial.sigio(func);
Expand Down
3 changes: 3 additions & 0 deletions include/interface/drivers/BufferedSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class BufferedSerial

virtual auto readable() -> bool = 0;

virtual void disable_input() = 0;
virtual void enable_input() = 0;

virtual void sigio(mbed::Callback<void()> func) = 0; // TODO (@HPezz) replace mbed callback by std function
};

Expand Down
1 change: 1 addition & 0 deletions tests/functional/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ endfunction()
add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/boost_ut)

add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/core_imu)
add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/deep_sleep_core_buffered_serial)
add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/deep_sleep_log_kit)
add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/deep_sleep_mbed_hal)
add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/file_manager)
Expand Down
25 changes: 25 additions & 0 deletions tests/functional/include/tests/utils_sleep.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,29 @@ inline void lp_ticker_isr(const ticker_data_t *const ticker_data)
}
#endif

struct DeepSleepStatus {
bool can_deep_sleep = {false};
bool test_check_ok = {false};
};

using deep_sleep_status_t = DeepSleepStatus;

inline auto system_deep_sleep_check() -> deep_sleep_status_t
{
const ticker_data_t *lp_ticker = get_lp_ticker_data();
const unsigned int lp_ticker_freq = lp_ticker->interface->get_info()->frequency;

// ? Give time to test to finish UART transmission before entering deep sleep mode
utils::sleep::busy_wait(utils::sleep::SERIAL_FLUSH_TIME_MS);

auto can_deep_sleep = sleep_manager_can_deep_sleep();

const timestamp_t wakeup_time = lp_ticker_read() + utils::sleep::us_to_ticks(20000, lp_ticker_freq);
lp_ticker_set_interrupt(wakeup_time);

auto can_deep_sleep_test_check = sleep_manager_can_deep_sleep_test_check();

return {can_deep_sleep, can_deep_sleep_test_check};
}

} // namespace utils::sleep
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Leka - LekaOS
# Copyright 2022 APF France handicap
# SPDX-License-Identifier: Apache-2.0

register_functional_test(
TARGET
functional_ut_deep_sleep_core_buffered_serial

INCLUDE_DIRECTORIES

SOURCES
suite_core_buffered_serial.cpp

LINK_LIBRARIES
CoreBufferedSerial
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include <cstddef>

#include "CoreBufferedSerial.h"
#include "tests/config.h"
#include "tests/utils.h"
#include "tests/utils_sleep.h"

using namespace leka;
using namespace boost::ut;
using namespace std::chrono;
using namespace boost::ut::bdd;

suite suite_core_buffered_serial = [] {
scenario("default configuration") = [] {
given("serial is in default configuration") = [] {
auto serial = CoreBufferedSerial(RFID_UART_TX, RFID_UART_RX, 57600);

expect(neq(&serial, nullptr));

when("I do nothing") = [] {
then("I expect deep sleep TO NOT BE possible") = [] {
ladislas marked this conversation as resolved.
Show resolved Hide resolved
auto status = utils::sleep::system_deep_sleep_check();

expect(not status.can_deep_sleep);
expect(not status.test_check_ok);
};
};
};
};

scenario("disable input") = [] {
given("serial is in default configuration") = [] {
auto serial = CoreBufferedSerial(RFID_UART_TX, RFID_UART_RX, 57600);

expect(neq(&serial, nullptr));

when("I disable input") = [&] {
serial.disable_input();
rtos::ThisThread::sleep_for(5ms);

then("I expect deep sleep TO BE possible") = [] {
auto status = utils::sleep::system_deep_sleep_check();

expect(status.can_deep_sleep);
expect(status.test_check_ok);
};
};
};
};

scenario("default, disable, enable, disable input") = [] {
given("serial is in default configuration") = [] {
auto serial = CoreBufferedSerial(RFID_UART_TX, RFID_UART_RX, 57600);

expect(neq(&serial, nullptr));

when("I do nothing") = [] {
then("I expect deep sleep TO NOT BE possible") = [] {
auto status = utils::sleep::system_deep_sleep_check();

expect(not status.can_deep_sleep);
expect(not status.test_check_ok);
};
};

when("I disable input") = [&] {
serial.disable_input();
rtos::ThisThread::sleep_for(5ms);

then("I expect deep sleep TO BE possible") = [] {
auto status = utils::sleep::system_deep_sleep_check();

expect(status.can_deep_sleep);
expect(status.test_check_ok);
};
};

when("I enable input") = [&] {
serial.enable_input();

then("I expect deep sleep TO NOT BE possible") = [] {
auto status = utils::sleep::system_deep_sleep_check();

expect(not status.can_deep_sleep);
expect(not status.test_check_ok);
};
};

when("I disable input") = [&] {
serial.disable_input();
rtos::ThisThread::sleep_for(5ms);

then("I expect deep sleep TO BE possible") = [] {
auto status = utils::sleep::system_deep_sleep_check();

expect(status.can_deep_sleep);
expect(status.test_check_ok);
};
};
};
};
};
51 changes: 9 additions & 42 deletions tests/functional/tests/deep_sleep_log_kit/suite_log_kit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ using namespace boost::ut;
using namespace std::chrono;
using namespace boost::ut::bdd;

// ? tests inspired from https://github.com/ARMmbed/mbed-os
// ? https://github.com/ARMmbed/mbed-os/blob/master/hal/tests/TESTS/mbed_hal/sleep/main.cpp

suite suite_log_kit = [] {
rtos::ThisThread::sleep_for(2000ms);

Expand All @@ -24,20 +21,10 @@ suite suite_log_kit = [] {
rtos::ThisThread::sleep_for(500ms);

then("I expect deep sleep to be possible") = [] {
const ticker_data_t *lp_ticker = get_lp_ticker_data();
const unsigned int lp_ticker_freq = lp_ticker->interface->get_info()->frequency;

// ? Give time to test to finish UART transmission before entering deep sleep mode
utils::sleep::busy_wait(utils::sleep::SERIAL_FLUSH_TIME_MS);

auto can_deep_sleep = sleep_manager_can_deep_sleep();
expect(can_deep_sleep) << "deep sleep not possible";
auto status = utils::sleep::system_deep_sleep_check();

const timestamp_t wakeup_time = lp_ticker_read() + utils::sleep::us_to_ticks(20000, lp_ticker_freq);
lp_ticker_set_interrupt(wakeup_time);

auto can_deep_sleep_test_check = sleep_manager_can_deep_sleep_test_check();
expect(can_deep_sleep_test_check);
expect(status.can_deep_sleep);
expect(status.test_check_ok);
};
};
};
Expand All @@ -49,20 +36,10 @@ suite suite_log_kit = [] {
rtos::ThisThread::sleep_for(500ms);

then("I expect deep sleep to NOT be possible") = [] {
const ticker_data_t *lp_ticker = get_lp_ticker_data();
const unsigned int lp_ticker_freq = lp_ticker->interface->get_info()->frequency;

// ? Give time to test to finish UART transmission before entering deep sleep mode
utils::sleep::busy_wait(utils::sleep::SERIAL_FLUSH_TIME_MS);
auto status = utils::sleep::system_deep_sleep_check();

auto can_deep_sleep = sleep_manager_can_deep_sleep();
expect(not can_deep_sleep) << "deep sleep STILL possible";

const timestamp_t wakeup_time = lp_ticker_read() + utils::sleep::us_to_ticks(20000, lp_ticker_freq);
lp_ticker_set_interrupt(wakeup_time);

auto can_deep_sleep_test_check = sleep_manager_can_deep_sleep_test_check();
expect(not can_deep_sleep_test_check);
expect(not status.can_deep_sleep);
expect(not status.test_check_ok);
};
};
};
Expand All @@ -74,20 +51,10 @@ suite suite_log_kit = [] {
rtos::ThisThread::sleep_for(500ms);

then("I expect deep sleep to NOT be possible") = [] {
const ticker_data_t *lp_ticker = get_lp_ticker_data();
const unsigned int lp_ticker_freq = lp_ticker->interface->get_info()->frequency;

// ? Give time to test to finish UART transmission before entering deep sleep mode
utils::sleep::busy_wait(utils::sleep::SERIAL_FLUSH_TIME_MS);

auto can_deep_sleep = sleep_manager_can_deep_sleep();
expect(can_deep_sleep) << "deep sleep not possible";

const timestamp_t wakeup_time = lp_ticker_read() + utils::sleep::us_to_ticks(20000, lp_ticker_freq);
lp_ticker_set_interrupt(wakeup_time);
auto status = utils::sleep::system_deep_sleep_check();

auto can_deep_sleep_test_check = sleep_manager_can_deep_sleep_test_check();
expect(can_deep_sleep_test_check);
expect(status.can_deep_sleep);
expect(status.test_check_ok);
};
};
};
Expand Down
5 changes: 3 additions & 2 deletions tests/functional/tests/deep_sleep_mbed_hal/suite_mbed_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,20 @@ suite suite_mbed_hal = [] {

mbed_sleep();

#if MBED_CONF_TARGET_LPTICKER_LPTIM

// ? On some targets like STM family boards with LPTIM enabled an interrupt is triggered on counter
// ? rollover. We need special handling for cases when next_match_timestamp < start_timestamp (interrupt
// ? is to be fired after rollover). In such case after first wake-up we need to reset interrupt and go
// ? back to sleep waiting for the valid one. NOTE: Above comment (CMPOK) applies also here.
#if MBED_CONF_TARGET_LPTICKER_LPTIM

if ((next_match_timestamp < start_timestamp) && lp_ticker_read() < next_match_timestamp) {
lp_ticker_set_interrupt(next_match_timestamp);
wait_ns(200000);
mbed_sleep();
}

#endif
#endif // MBED_CONF_TARGET_LPTICKER_LPTIM

const timestamp_t wakeup_timestamp = lp_ticker_read();

Expand Down
2 changes: 2 additions & 0 deletions tests/unit/mocks/mocks/leka/CoreBufferedSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class CoreBufferedSerial : public interface::BufferedSerial
MOCK_METHOD(std::size_t, read, (uint8_t *, std::size_t), (override));
MOCK_METHOD(std::size_t, write, (const uint8_t *, std::size_t), (override));
MOCK_METHOD(bool, readable, (), (override));
MOCK_METHOD(void, disable_input, (), (override));
MOCK_METHOD(void, enable_input, (), (override));
MOCK_METHOD(void, sigio, (mbed::Callback<void()>), (override));
};

Expand Down