mirror of https://github.com/ARMmbed/mbed-os.git
Test: Watchdog: Add new driver tests
parent
db52d0068e
commit
9c6cd2b669
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_DRIVERS_WATCHDOG_TESTS_H
|
||||
#define MBED_DRIVERS_WATCHDOG_TESTS_H
|
||||
|
||||
#if DEVICE_WATCHDOG
|
||||
|
||||
/** Test Watchdog max_timeout validity
|
||||
*
|
||||
* Given a device supporting Watchdog driver API,
|
||||
* when @a Watchdog::get_max_timeout() is called,
|
||||
* then the returned value is greater than 1.
|
||||
*/
|
||||
void test_max_timeout_is_valid();
|
||||
|
||||
/** Test Watchdog stop
|
||||
*
|
||||
* Given a device without a support for the @a disable_watchdog feature,
|
||||
* when @a Watchdog::stop() is called,
|
||||
* then false is returned.
|
||||
*
|
||||
* Otherwise, given the device with @a disable_watchdog feature support:
|
||||
*
|
||||
* Given the Watchdog is *NOT* running,
|
||||
* when @a Watchdog::stop() is called,
|
||||
* then false is returned.
|
||||
*
|
||||
* Given the Watchdog is running,
|
||||
* when @a Watchdog::stop() is called before the timeout expires,
|
||||
* then true is returned and the device is not restarted.
|
||||
*
|
||||
* Given the Watchdog is *NOT* running (it has already been stopped),
|
||||
* when @a Watchdog::stop() is called,
|
||||
* then false is returned.
|
||||
*/
|
||||
void test_stop();
|
||||
|
||||
/** Test Watchdog start multiple times
|
||||
*
|
||||
* Given a set of unique timeout values,
|
||||
* when Watchdog::start(T) is called for each value T,
|
||||
* then, for every T, Watchdog::start() returns true
|
||||
* and Watchdog::get_timeout() returns an actual timeout value R
|
||||
* and T <= R < 2 * T.
|
||||
*/
|
||||
void test_restart();
|
||||
|
||||
/** Test Watchdog start with a valid config
|
||||
*
|
||||
* Given a value of T ms which is within supported Watchdog timeout range,
|
||||
* when Watchdog::start(T) is called,
|
||||
* then true is returned
|
||||
* and Watchdog::get_timeout() returns an actual timeout value R
|
||||
* and T <= R < 2 * T.
|
||||
*/
|
||||
template<uint32_t timeout_ms>
|
||||
void test_start();
|
||||
|
||||
/** Test Watchdog start with max_timeout
|
||||
*
|
||||
* Given max_timeout value returned by @a Watchdog::get_max_timeout(),
|
||||
* when @a Watchdog::start(max_timeout) is called,
|
||||
* then true is returned
|
||||
* and @a Watchdog::get_timeout() returns max_timeout.
|
||||
*/
|
||||
void test_start_max_timeout();
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#if !DEVICE_WATCHDOG
|
||||
#error [NOT_SUPPORTED] Watchdog not supported for this target
|
||||
#endif
|
||||
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
#include "utest/utest.h"
|
||||
#include "mbed.h"
|
||||
#include "drivers/Watchdog.h"
|
||||
#include "hal/watchdog_api.h"
|
||||
#include "Watchdog_tests.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* The shortest timeout value, this test suite is able to handle correctly. */
|
||||
#define WDG_MIN_TIMEOUT_MS 50UL
|
||||
|
||||
// Do not set watchdog timeout shorter than WDG_MIN_TIMEOUT_MS, as it may
|
||||
// cause the host-test-runner return 'TIMEOUT' instead of 'FAIL' / 'PASS'
|
||||
// if watchdog performs reset during test suite teardown.
|
||||
#define WDG_TIMEOUT_MS 100UL
|
||||
|
||||
#define MSG_VALUE_DUMMY "0"
|
||||
#define MSG_VALUE_LEN 24
|
||||
#define MSG_KEY_LEN 24
|
||||
|
||||
#define MSG_KEY_DEVICE_READY "ready"
|
||||
#define MSG_KEY_START_CASE "start_case"
|
||||
#define MSG_KEY_DEVICE_RESET "reset_on_case_teardown"
|
||||
|
||||
/* To prevent a loss of Greentea data, the serial buffers have to be flushed
|
||||
* before the UART peripheral shutdown. The UART shutdown happens when the
|
||||
* device is entering the deepsleep mode or performing a reset.
|
||||
*
|
||||
* With the current API, it is not possible to check if the hardware buffers
|
||||
* are empty. However, it is possible to determine the time required for the
|
||||
* buffers to flush.
|
||||
*
|
||||
* Take NUMAKER_PFM_NUC472 as an example:
|
||||
* The UART peripheral has 16-byte Tx FIFO. With a baud rate set to 9600,
|
||||
* flushing the Tx FIFO would take: 16 * 8 * 1000 / 9600 = 13.3 ms.
|
||||
* To be on the safe side, set the wait time to 20 ms.
|
||||
*/
|
||||
#define SERIAL_FLUSH_TIME_MS 20
|
||||
|
||||
int CASE_INDEX_START;
|
||||
int CASE_INDEX_CURRENT;
|
||||
|
||||
using utest::v1::Case;
|
||||
using utest::v1::Specification;
|
||||
using utest::v1::Harness;
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
Thread wdg_kicking_thread;
|
||||
Semaphore kick_wdg_during_test_teardown(0, 1);
|
||||
|
||||
void wdg_kicking_thread_fun()
|
||||
{
|
||||
kick_wdg_during_test_teardown.wait();
|
||||
while (true) {
|
||||
hal_watchdog_kick();
|
||||
wait_ms(20);
|
||||
}
|
||||
}
|
||||
|
||||
void test_max_timeout_is_valid()
|
||||
{
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
TEST_ASSERT(watchdog.get_max_timeout() > 1UL);
|
||||
}
|
||||
|
||||
void test_stop()
|
||||
{
|
||||
watchdog_features_t features = hal_watchdog_get_platform_features();
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
if (!features.disable_watchdog) {
|
||||
TEST_ASSERT_FALSE(watchdog.stop());
|
||||
TEST_IGNORE_MESSAGE("Disabling watchdog not supported for this platform");
|
||||
return;
|
||||
}
|
||||
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
TEST_ASSERT_FALSE(watchdog.stop());
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
|
||||
TEST_ASSERT_TRUE(watchdog.start(WDG_TIMEOUT_MS));
|
||||
TEST_ASSERT_TRUE(watchdog.is_running());
|
||||
TEST_ASSERT_TRUE(watchdog.stop());
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
// Make sure that a disabled watchdog does not reset the core.
|
||||
wait_ms(2 * WDG_TIMEOUT_MS); // Watchdog should fire before twice the timeout value.
|
||||
|
||||
TEST_ASSERT_FALSE(watchdog.stop());
|
||||
}
|
||||
|
||||
|
||||
void test_restart()
|
||||
{
|
||||
watchdog_features_t features = hal_watchdog_get_platform_features();
|
||||
if (!features.update_config) {
|
||||
TEST_IGNORE_MESSAGE("Updating watchdog config not supported for this platform");
|
||||
return;
|
||||
}
|
||||
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
uint32_t max_timeout = watchdog.get_max_timeout();
|
||||
uint32_t timeouts[] = {
|
||||
max_timeout / 4,
|
||||
max_timeout / 8,
|
||||
max_timeout / 16
|
||||
};
|
||||
int num_timeouts = sizeof timeouts / sizeof timeouts[0];
|
||||
|
||||
for (size_t i = 0; i < num_timeouts; i++) {
|
||||
if (timeouts[i] < WDG_MIN_TIMEOUT_MS) {
|
||||
TEST_IGNORE_MESSAGE("Requested timeout value is too short -- ignoring test case.");
|
||||
return;
|
||||
}
|
||||
|
||||
TEST_ASSERT_TRUE(watchdog.start(timeouts[i]));
|
||||
TEST_ASSERT_TRUE(watchdog.is_running());
|
||||
uint32_t actual_timeout = watchdog.get_timeout();
|
||||
TEST_ASSERT_TRUE(watchdog.stop());
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
// The watchdog should trigger at, or after the timeout value.
|
||||
TEST_ASSERT(actual_timeout >= timeouts[i]);
|
||||
// The watchdog should trigger before twice the timeout value.
|
||||
TEST_ASSERT(actual_timeout < 2 * timeouts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
utest::v1::status_t case_setup_sync_on_reset(const Case *const source, const size_t index_of_case)
|
||||
{
|
||||
CASE_INDEX_CURRENT = index_of_case;
|
||||
return utest::v1::greentea_case_setup_handler(source, index_of_case);
|
||||
}
|
||||
|
||||
utest::v1::status_t case_teardown_sync_on_reset(const Case *const source, const size_t passed, const size_t failed,
|
||||
const utest::v1::failure_t failure)
|
||||
{
|
||||
// Unlock kicking the watchdog during teardown.
|
||||
kick_wdg_during_test_teardown.release();
|
||||
utest::v1::status_t status = utest::v1::greentea_case_teardown_handler(source, passed, failed, failure);
|
||||
if (failed) {
|
||||
/* Return immediately and skip the device reset, if the test case failed.
|
||||
* Provided that the device won't be restarted by other means (i.e. watchdog timer),
|
||||
* this should allow the test suite to finish in a defined manner
|
||||
* and report failure to host.
|
||||
* In case of watchdog reset during test suite teardown, the loss of serial
|
||||
* connection is possible, so the host-test-runner may return 'TIMEOUT'
|
||||
* instead of 'FAIL'.
|
||||
*/
|
||||
return status;
|
||||
}
|
||||
greentea_send_kv(MSG_KEY_DEVICE_RESET, CASE_INDEX_START + CASE_INDEX_CURRENT);
|
||||
utest_printf("The device will now restart.\n");
|
||||
wait_ms(SERIAL_FLUSH_TIME_MS); // Wait for the serial buffers to flush.
|
||||
NVIC_SystemReset();
|
||||
return status; // Reset is instant so this line won't be reached.
|
||||
}
|
||||
|
||||
utest::v1::status_t case_teardown_wdg_stop_or_reset(const Case *const source, const size_t passed, const size_t failed,
|
||||
const utest::v1::failure_t failure)
|
||||
{
|
||||
watchdog_features_t features = hal_watchdog_get_platform_features();
|
||||
if (features.disable_watchdog) {
|
||||
hal_watchdog_stop();
|
||||
return utest::v1::greentea_case_teardown_handler(source, passed, failed, failure);
|
||||
}
|
||||
|
||||
return case_teardown_sync_on_reset(source, passed, failed, failure);
|
||||
}
|
||||
|
||||
template<uint32_t timeout_ms>
|
||||
void test_start()
|
||||
{
|
||||
if (timeout_ms < WDG_MIN_TIMEOUT_MS) {
|
||||
TEST_IGNORE_MESSAGE("Requested timeout value is too short -- ignoring test case.");
|
||||
return;
|
||||
}
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
TEST_ASSERT_TRUE(watchdog.start(timeout_ms));
|
||||
uint32_t actual_timeout = watchdog.get_timeout();
|
||||
// The watchdog should trigger at, or after the timeout value.
|
||||
TEST_ASSERT(actual_timeout >= timeout_ms);
|
||||
// The watchdog should trigger before twice the timeout value.
|
||||
TEST_ASSERT(actual_timeout < 2 * timeout_ms);
|
||||
}
|
||||
|
||||
void test_start_max_timeout()
|
||||
{
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
uint32_t max_timeout = watchdog.get_max_timeout();
|
||||
TEST_ASSERT_TRUE(watchdog.start(max_timeout));
|
||||
// The watchdog should trigger at, or after the timeout value.
|
||||
TEST_ASSERT(watchdog.get_timeout() >= max_timeout);
|
||||
}
|
||||
|
||||
int testsuite_setup_sync_on_reset(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(45, "sync_on_reset");
|
||||
utest::v1::status_t status = utest::v1::greentea_test_setup_handler(number_of_cases);
|
||||
if (status != utest::v1::STATUS_CONTINUE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
char key[MSG_KEY_LEN + 1] = { };
|
||||
char value[MSG_VALUE_LEN + 1] = { };
|
||||
|
||||
greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY);
|
||||
greentea_parse_kv(key, value, MSG_KEY_LEN, MSG_VALUE_LEN);
|
||||
|
||||
if (strcmp(key, MSG_KEY_START_CASE) != 0) {
|
||||
utest_printf("Invalid message key.\n");
|
||||
return utest::v1::STATUS_ABORT;
|
||||
}
|
||||
|
||||
char *tailptr = NULL;
|
||||
CASE_INDEX_START = (int) strtol(value, &tailptr, 10);
|
||||
if (*tailptr != '\0' || CASE_INDEX_START < 0) {
|
||||
utest_printf("Invalid start case index received from host\n");
|
||||
return utest::v1::STATUS_ABORT;
|
||||
}
|
||||
|
||||
// The thread is started here, but feeding the watchdog will start
|
||||
// when the semaphore is released during a test case teardown.
|
||||
wdg_kicking_thread.start(mbed::callback(wdg_kicking_thread_fun));
|
||||
|
||||
utest_printf("Starting with test case index %i of all %i defined test cases.\n", CASE_INDEX_START, number_of_cases);
|
||||
return CASE_INDEX_START;
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("max_timeout is valid", test_max_timeout_is_valid),
|
||||
Case("Stop", test_stop),
|
||||
Case("Restart multiple times",
|
||||
(utest::v1::case_setup_handler_t) case_setup_sync_on_reset,
|
||||
test_restart, (utest::v1::case_teardown_handler_t) case_teardown_wdg_stop_or_reset),
|
||||
Case("Start, 100 ms", (utest::v1::case_setup_handler_t) case_setup_sync_on_reset,
|
||||
test_start<100UL>, (utest::v1::case_teardown_handler_t) case_teardown_sync_on_reset),
|
||||
Case("Start, max_timeout", (utest::v1::case_setup_handler_t) case_setup_sync_on_reset,
|
||||
test_start_max_timeout, (utest::v1::case_teardown_handler_t) case_teardown_sync_on_reset),
|
||||
};
|
||||
|
||||
Specification specification((utest::v1::test_setup_handler_t) testsuite_setup_sync_on_reset, cases);
|
||||
|
||||
int main()
|
||||
{
|
||||
// Harness will start with a test case index provided by host script.
|
||||
return !Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_DRIVERS_WATCHDOG_RESET_TESTS_H
|
||||
#define MBED_DRIVERS_WATCHDOG_RESET_TESTS_H
|
||||
|
||||
#if DEVICE_WATCHDOG
|
||||
|
||||
/** Test Watchdog reset
|
||||
*
|
||||
* Given a device with a Watchdog started,
|
||||
* when a Watchdog timeout expires,
|
||||
* then the device is restarted.
|
||||
*/
|
||||
void test_simple_reset();
|
||||
|
||||
/** Test Watchdog reset in sleep mode
|
||||
*
|
||||
* Given a device with a Watchdog started,
|
||||
* when the Watchdog timeout expires while the device is in sleep mode,
|
||||
* then the device is restarted.
|
||||
*/
|
||||
void test_sleep_reset();
|
||||
|
||||
/** Test Watchdog reset in deepsleep mode
|
||||
*
|
||||
* Given a device with a Watchdog started,
|
||||
* when the Watchdog timeout expires while the device is in deepsleep mode,
|
||||
* then the device is restarted.
|
||||
*/
|
||||
void test_deepsleep_reset();
|
||||
|
||||
/** Test Watchdog reset after Watchdog restart
|
||||
*
|
||||
* Given a device with a Watchdog started,
|
||||
* when the Watchdog is stopped before its timeout expires,
|
||||
* then the device is not restarted.
|
||||
* When the Watchdog is started again and its timeout expires,
|
||||
* then the device is restarted.
|
||||
*/
|
||||
void test_restart_reset();
|
||||
|
||||
/** Test Watchdog kick
|
||||
*
|
||||
* Given a device with a Watchdog started,
|
||||
* when the Watchdog is kicked before its timeout expires,
|
||||
* then the device restart is prevented.
|
||||
* When the Watchdog is *NOT* kicked again before next timeout expires,
|
||||
* then the device is restarted.
|
||||
*/
|
||||
void test_kick_reset();
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#if !DEVICE_WATCHDOG
|
||||
#error [NOT_SUPPORTED] Watchdog not supported for this target
|
||||
#endif
|
||||
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "utest/utest.h"
|
||||
#include "unity/unity.h"
|
||||
#include "drivers/Watchdog.h"
|
||||
#include "Watchdog_reset_tests.h"
|
||||
#include "mbed.h"
|
||||
|
||||
#define TIMEOUT_MS 100UL
|
||||
#define KICK_ADVANCE_MS 10UL
|
||||
|
||||
#define MSG_VALUE_DUMMY "0"
|
||||
#define CASE_DATA_INVALID 0xffffffffUL
|
||||
#define CASE_DATA_PHASE2_OK 0xfffffffeUL
|
||||
|
||||
#define MSG_VALUE_LEN 24
|
||||
#define MSG_KEY_LEN 24
|
||||
|
||||
#define MSG_KEY_DEVICE_READY "ready"
|
||||
#define MSG_KEY_START_CASE "start_case"
|
||||
#define MSG_KEY_DEVICE_RESET "dev_reset"
|
||||
|
||||
/* To prevent a loss of Greentea data, the serial buffers have to be flushed
|
||||
* before the UART peripheral shutdown. The UART shutdown happens when the
|
||||
* device is entering the deepsleep mode or performing a reset.
|
||||
*
|
||||
* With the current API, it is not possible to check if the hardware buffers
|
||||
* are empty. However, it is possible to determine the time required for the
|
||||
* buffers to flush.
|
||||
*
|
||||
* Take NUMAKER_PFM_NUC472 as an example:
|
||||
* The UART peripheral has 16-byte Tx FIFO. With a baud rate set to 9600,
|
||||
* flushing the Tx FIFO would take: 16 * 8 * 1000 / 9600 = 13.3 ms.
|
||||
* To be on the safe side, set the wait time to 20 ms.
|
||||
*/
|
||||
#define SERIAL_FLUSH_TIME_MS 20
|
||||
|
||||
using utest::v1::Case;
|
||||
using utest::v1::Specification;
|
||||
using utest::v1::Harness;
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
struct testcase_data {
|
||||
int index;
|
||||
int start_index;
|
||||
uint32_t received_data;
|
||||
};
|
||||
|
||||
void release_sem(Semaphore *sem)
|
||||
{
|
||||
sem->release();
|
||||
}
|
||||
|
||||
testcase_data current_case;
|
||||
|
||||
bool send_reset_notification(testcase_data *tcdata, uint32_t delay_ms)
|
||||
{
|
||||
char msg_value[12];
|
||||
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
||||
if (str_len != (sizeof msg_value) - 1) {
|
||||
utest_printf("Failed to compose a value string to be sent to host.");
|
||||
return false;
|
||||
}
|
||||
greentea_send_kv(MSG_KEY_DEVICE_RESET, msg_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
void test_simple_reset()
|
||||
{
|
||||
// Phase 2. -- verify the test results.
|
||||
// Verify if this test case passed based on data received from host.
|
||||
if (current_case.received_data != CASE_DATA_INVALID) {
|
||||
TEST_ASSERT_EQUAL(CASE_DATA_PHASE2_OK, current_case.received_data);
|
||||
current_case.received_data = CASE_DATA_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
// Phase 1. -- run the test code.
|
||||
// Init the watchdog and wait for a device reset.
|
||||
if (send_reset_notification(¤t_case, 2 * TIMEOUT_MS) == false) {
|
||||
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
|
||||
return;
|
||||
}
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
|
||||
TEST_ASSERT_TRUE(watchdog.is_running());
|
||||
// Watchdog should fire before twice the timeout value.
|
||||
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
|
||||
|
||||
// Watchdog reset should have occurred during wait_ms() above;
|
||||
|
||||
watchdog.kick(); // Just to buy some time for testsuite failure handling.
|
||||
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
|
||||
}
|
||||
|
||||
#if DEVICE_SLEEP
|
||||
void test_sleep_reset()
|
||||
{
|
||||
// Phase 2. -- verify the test results.
|
||||
if (current_case.received_data != CASE_DATA_INVALID) {
|
||||
TEST_ASSERT_EQUAL(CASE_DATA_PHASE2_OK, current_case.received_data);
|
||||
current_case.received_data = CASE_DATA_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
// Phase 1. -- run the test code.
|
||||
Semaphore sem(0, 1);
|
||||
Timeout timeout;
|
||||
if (send_reset_notification(¤t_case, 2 * TIMEOUT_MS) == false) {
|
||||
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
|
||||
return;
|
||||
}
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
|
||||
TEST_ASSERT_TRUE(watchdog.is_running());
|
||||
sleep_manager_lock_deep_sleep();
|
||||
// Watchdog should fire before twice the timeout value.
|
||||
timeout.attach_us(mbed::callback(release_sem, &sem), 1000ULL * (2 * TIMEOUT_MS));
|
||||
if (sleep_manager_can_deep_sleep()) {
|
||||
TEST_ASSERT_MESSAGE(0, "Deepsleep should be disallowed.");
|
||||
return;
|
||||
}
|
||||
sem.wait(); // Device reset expected.
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
|
||||
// Watchdog reset should have occurred during sem.wait() (sleep) above;
|
||||
|
||||
watchdog.kick(); // Just to buy some time for testsuite failure handling.
|
||||
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
|
||||
}
|
||||
|
||||
#if DEVICE_LOWPOWERTIMER
|
||||
void test_deepsleep_reset()
|
||||
{
|
||||
// Phase 2. -- verify the test results.
|
||||
if (current_case.received_data != CASE_DATA_INVALID) {
|
||||
TEST_ASSERT_EQUAL(CASE_DATA_PHASE2_OK, current_case.received_data);
|
||||
current_case.received_data = CASE_DATA_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
// Phase 1. -- run the test code.
|
||||
Semaphore sem(0, 1);
|
||||
LowPowerTimeout lp_timeout;
|
||||
if (send_reset_notification(¤t_case, 2 * TIMEOUT_MS) == false) {
|
||||
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
|
||||
return;
|
||||
}
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
|
||||
TEST_ASSERT_TRUE(watchdog.is_running());
|
||||
// Watchdog should fire before twice the timeout value.
|
||||
lp_timeout.attach_us(mbed::callback(release_sem, &sem), 1000ULL * (2 * TIMEOUT_MS));
|
||||
wait_ms(SERIAL_FLUSH_TIME_MS); // Wait for the serial buffers to flush.
|
||||
if (!sleep_manager_can_deep_sleep()) {
|
||||
TEST_ASSERT_MESSAGE(0, "Deepsleep should be allowed.");
|
||||
}
|
||||
sem.wait(); // Device reset expected.
|
||||
|
||||
// Watchdog reset should have occurred during sem.wait() (deepsleep) above;
|
||||
|
||||
watchdog.kick(); // Just to buy some time for testsuite failure handling.
|
||||
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void test_restart_reset()
|
||||
{
|
||||
watchdog_features_t features = hal_watchdog_get_platform_features();
|
||||
if (!features.disable_watchdog) {
|
||||
TEST_IGNORE_MESSAGE("Disabling Watchdog not supported for this platform");
|
||||
return;
|
||||
}
|
||||
|
||||
// Phase 2. -- verify the test results.
|
||||
if (current_case.received_data != CASE_DATA_INVALID) {
|
||||
TEST_ASSERT_EQUAL(CASE_DATA_PHASE2_OK, current_case.received_data);
|
||||
current_case.received_data = CASE_DATA_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
// Phase 1. -- run the test code.
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
|
||||
TEST_ASSERT_TRUE(watchdog.is_running());
|
||||
wait_ms(TIMEOUT_MS / 2UL);
|
||||
TEST_ASSERT_TRUE(watchdog.stop());
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
// Check that stopping the Watchdog prevents a device reset.
|
||||
// The watchdog should trigger at, or after the timeout value.
|
||||
// The watchdog should trigger before twice the timeout value.
|
||||
wait_ms(TIMEOUT_MS / 2UL + TIMEOUT_MS);
|
||||
|
||||
if (send_reset_notification(¤t_case, 2 * TIMEOUT_MS) == false) {
|
||||
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
|
||||
return;
|
||||
}
|
||||
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
|
||||
TEST_ASSERT_TRUE(watchdog.is_running());
|
||||
// Watchdog should fire before twice the timeout value.
|
||||
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
|
||||
|
||||
// Watchdog reset should have occurred during that wait() above;
|
||||
|
||||
watchdog.kick(); // Just to buy some time for testsuite failure handling.
|
||||
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
|
||||
}
|
||||
|
||||
void test_kick_reset()
|
||||
{
|
||||
// Phase 2. -- verify the test results.
|
||||
if (current_case.received_data != CASE_DATA_INVALID) {
|
||||
TEST_ASSERT_EQUAL(CASE_DATA_PHASE2_OK, current_case.received_data);
|
||||
current_case.received_data = CASE_DATA_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
// Phase 1. -- run the test code.
|
||||
Watchdog& watchdog = Watchdog::get_instance();
|
||||
TEST_ASSERT_FALSE(watchdog.is_running());
|
||||
TEST_ASSERT_TRUE(watchdog.start(TIMEOUT_MS));
|
||||
TEST_ASSERT_TRUE(watchdog.is_running());
|
||||
for (int i = 3; i; i--) {
|
||||
// The reset is prevented as long as the watchdog is kicked
|
||||
// anytime before the timeout.
|
||||
wait_ms(TIMEOUT_MS - KICK_ADVANCE_MS);
|
||||
watchdog.kick();
|
||||
}
|
||||
if (send_reset_notification(¤t_case, 2 * TIMEOUT_MS) == false) {
|
||||
TEST_ASSERT_MESSAGE(0, "Dev-host communication error.");
|
||||
return;
|
||||
}
|
||||
// Watchdog should fire before twice the timeout value.
|
||||
wait_ms(2 * TIMEOUT_MS); // Device reset expected.
|
||||
|
||||
// Watchdog reset should have occurred during that wait() above;
|
||||
|
||||
watchdog.kick(); // Just to buy some time for testsuite failure handling.
|
||||
TEST_ASSERT_MESSAGE(0, "Watchdog did not reset the device as expected.");
|
||||
}
|
||||
|
||||
utest::v1::status_t case_setup(const Case *const source, const size_t index_of_case)
|
||||
{
|
||||
current_case.index = index_of_case;
|
||||
return utest::v1::greentea_case_setup_handler(source, index_of_case);
|
||||
}
|
||||
|
||||
int testsuite_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(90, "watchdog_reset");
|
||||
utest::v1::status_t status = utest::v1::greentea_test_setup_handler(number_of_cases);
|
||||
if (status != utest::v1::STATUS_CONTINUE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
char key[MSG_KEY_LEN + 1] = { };
|
||||
char value[MSG_VALUE_LEN + 1] = { };
|
||||
|
||||
greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY);
|
||||
greentea_parse_kv(key, value, MSG_KEY_LEN, MSG_VALUE_LEN);
|
||||
|
||||
if (strcmp(key, MSG_KEY_START_CASE) != 0) {
|
||||
utest_printf("Invalid message key.\n");
|
||||
return utest::v1::STATUS_ABORT;
|
||||
}
|
||||
|
||||
int num_args = sscanf(value, "%02x,%08lx", &(current_case.start_index), &(current_case.received_data));
|
||||
if (num_args == 0 || num_args == EOF) {
|
||||
utest_printf("Invalid data received from host\n");
|
||||
return utest::v1::STATUS_ABORT;
|
||||
}
|
||||
|
||||
utest_printf("This test suite is composed of %i test cases. Starting at index %i.\n", number_of_cases,
|
||||
current_case.start_index);
|
||||
return current_case.start_index;
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("Watchdog reset", case_setup, test_simple_reset),
|
||||
#if DEVICE_SLEEP
|
||||
Case("Watchdog reset in sleep mode", case_setup, test_sleep_reset),
|
||||
#if DEVICE_LOWPOWERTIMER
|
||||
Case("Watchdog reset in deepsleep mode", case_setup, test_deepsleep_reset),
|
||||
#endif
|
||||
#endif
|
||||
Case("Watchdog started again", case_setup, test_restart_reset),
|
||||
Case("Kicking the Watchdog prevents reset", case_setup, test_kick_reset),
|
||||
};
|
||||
|
||||
Specification specification((utest::v1::test_setup_handler_t) testsuite_setup, cases);
|
||||
|
||||
int main()
|
||||
{
|
||||
// Harness will start with a test case index provided by host script.
|
||||
return !Harness::run(specification);
|
||||
}
|
Loading…
Reference in New Issue