Skip to content

RTC specification (branch feature-hal-spec-rtc) #5008

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

Closed
Closed
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
119 changes: 119 additions & 0 deletions TESTS/host_tests/rtc_reset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""
mbed SDK
Copyright (c) 2017-2017 ARM Limited

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.
"""
from __future__ import print_function

from mbed_host_tests import BaseHostTest
from time import sleep


class RtcResetTest(BaseHostTest):
"""This test checks that a device's RTC keeps count through a reset

It does this by setting the RTC's time, triggering a reset,
delaying and then reading the RTC's time again to ensure
that the RTC is still counting.
"""

"""Start of the RTC"""
START_TIME = 50000
START_TIME_TOLERANCE = 10
"""Time to delay after sending reset"""
DELAY_TIME = 4.0
DELAY_TOLERANCE = 1.0
VALUE_PLACEHOLDER = "0"

def setup(self):
"""Register callbacks required for the test"""
self._error = False
generator = self.rtc_reset_test()
generator.next()

def run_gen(key, value, time):
"""Run the generator, and fail testing if the iterator stops"""
if self._error:
return
try:
print("Calling generator")
generator.send((key, value, time))
except StopIteration:
self._error = True

for resp in ("start", "read"):
self.register_callback(resp, run_gen)

def teardown(self):
"""No work to do here"""
pass

def rtc_reset_test(self):
"""Generator for running the reset test

This function calls yield to wait for the next event from
the device. If the device gives the wrong response, then the
generator terminates by returing which raises a StopIteration
exception and fails the test.
"""

# Wait for start token
key, value, time = yield()
if key != "start":
return

# Initialize, and set the time
self.send_kv("init", self.VALUE_PLACEHOLDER)
self.send_kv("write", str(self.START_TIME))
self.send_kv("read", self.VALUE_PLACEHOLDER)
key, value, time = yield()
if key != "read":
return
dev_time_start = int(value)

# Unitialize, and reset
self.send_kv("free", self.VALUE_PLACEHOLDER)
self.send_kv("reset", self.VALUE_PLACEHOLDER)
sleep(self.DELAY_TIME)

# Restart the test, and send the sync token
self.send_kv("__sync", "00000000-0000-000000000-000000000000")
key, value, time = yield()
if key != "start":
return

# Initialize, and read the time
self.send_kv("init", self.VALUE_PLACEHOLDER)
self.send_kv("read", self.VALUE_PLACEHOLDER)
key, value, time = yield()
if key != "read":
return
dev_time_end = int(value)

# Check result
elapsed = dev_time_end - dev_time_start
start_time_valid = (self.START_TIME <= dev_time_start <
self.START_TIME + self.START_TIME_TOLERANCE)
elapsed_time_valid = elapsed >= self.DELAY_TIME - self.DELAY_TOLERANCE
passed = start_time_valid and elapsed_time_valid
if not start_time_valid:
self.log("FAIL: Expected start time of %i got %i" %
(self.START_TIME, dev_time_start))
elif not passed:
self.log("FAIL: Delayed for %fs but device "
"reported elapsed time of %fs" %
(self.DELAY_TIME, elapsed))
self.send_kv("exit", "pass" if passed else "fail")
yield() # No more events expected

146 changes: 146 additions & 0 deletions TESTS/mbed_hal/rtc/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* 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_RTC
#error [NOT_SUPPORTED] RTC API not supported for this target
#endif

#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"

#include "mbed.h"
#include "rtc_api.h"

using namespace utest::v1;

static const uint32_t WAIT_TIME = 4;
static const uint32_t WAIT_TOLERANCE = 1;


/** \addtogroup hal_rtc_tests
* @{
*/

/** Test that ::rtc_init can be called multiple times
*
*/
static void rtc_init_test()
{
for (int i = 0; i < 10; i++) {
rtc_init();
}
}

/** Test that the RTC keeps counting in the various sleep modes
*
*/
static void rtc_sleep_test()
{
const uint32_t start = 100;
rtc_init();

rtc_write(start);
wait(WAIT_TIME);
const uint32_t stop = rtc_read();

rtc_free();

TEST_ASSERT_UINT32_WITHIN(WAIT_TOLERANCE, WAIT_TIME, stop - start);
}

/** Test that the RTC keeps counting even after ::rtc_free has been called
*
*/
static void rtc_persist_test()
{
const uint32_t start = 100;
rtc_init();
rtc_write(start);
rtc_free();

wait(WAIT_TIME);

rtc_init();
const uint32_t stop = rtc_read();
const int enabled = rtc_isenabled();
rtc_free();

TEST_ASSERT_TRUE(enabled);
TEST_ASSERT_UINT32_WITHIN(WAIT_TOLERANCE, WAIT_TIME, stop - start);
}

/** Test time does not glitch backwards due to an incorrectly implemented ripple counter driver
*
*/
static void rtc_glitch_test()
{
const uint32_t start = 0xffffe;
rtc_init();

rtc_write(start);
uint32_t last = start;
while (last < start + 4) {
const uint32_t cur = rtc_read();
TEST_ASSERT(cur >= last);
last = cur;
}

rtc_free();
}

/** Test that the RTC correctly handles large time values
*
*/
static void rtc_range_test()
{
static const uint32_t starts[] = {
0x00000000,
0xEFFFFFFF,
0x00001000,
};

rtc_init();
for (uint32_t i = 0; i < sizeof(starts) / sizeof(starts[0]); i++) {
const uint32_t start = starts[i];
rtc_write(start);
wait(WAIT_TIME);
const uint32_t stop = rtc_read();
TEST_ASSERT_UINT32_WITHIN(WAIT_TOLERANCE, WAIT_TIME, stop - start);
}
rtc_free();
}

/** @}*/

Case cases[] = {
Case("RTC - init", rtc_init_test),
Case("RTC - sleep", rtc_sleep_test),
Case("RTC - persist", rtc_persist_test),
Case("RTC - glitch", rtc_glitch_test),
Case("RTC - range", rtc_range_test),
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(30, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main() {
Harness::run(specification);
}
99 changes: 99 additions & 0 deletions TESTS/mbed_hal/rtc_reset/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* 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_RTC
#error [NOT_SUPPORTED] RTC API not supported for this target
#endif

#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"

#include "mbed.h"
#include "rtc_api.h"

typedef enum {
CMD_STATUS_PASS,
CMD_STATUS_FAIL,
CMD_STATUS_CONTINUE,
CMD_STATUS_ERROR
} cmd_status_t;

static cmd_status_t handle_command(const char *key, const char *value)
{
if (strcmp(key, "init") == 0) {
rtc_init();
return CMD_STATUS_CONTINUE;

} else if (strcmp(key, "free") == 0) {
rtc_free();
return CMD_STATUS_CONTINUE;

} else if (strcmp(key, "read") == 0) {
static char time_buf[64];
memset(time_buf, 0, sizeof(time_buf));
sprintf(time_buf, "%lu", (uint32_t)rtc_read());
greentea_send_kv("read", time_buf);
return CMD_STATUS_CONTINUE;

} else if (strcmp(key, "write") == 0) {
uint32_t time;
sscanf(value, "%lu", &time);
rtc_write(time);
return CMD_STATUS_CONTINUE;

} else if (strcmp(key, "reset") == 0) {
NVIC_SystemReset();
// Code shouldn't read this due to the reset
return CMD_STATUS_ERROR;

} else if (strcmp(key, "exit") == 0) {
return strcmp(value, "pass") == 0 ? CMD_STATUS_PASS : CMD_STATUS_FAIL;

} else {
return CMD_STATUS_ERROR;

}
}

/** Test that the RTC does not stop counting after a software reset
* \ingroup hal_rtc_tests
*/
static void rtc_reset_test()
{
GREENTEA_SETUP(60, "rtc_reset");

static char _key[10 + 1] = {};
static char _value[128 + 1] = {};

greentea_send_kv("start", 1);

// Handshake with host
cmd_status_t cmd_status = CMD_STATUS_CONTINUE;
while (CMD_STATUS_CONTINUE == cmd_status) {
memset(_key, 0, sizeof(_key));
memset(_value, 0, sizeof(_value));
greentea_parse_kv(_key, _value, sizeof(_key) - 1, sizeof(_value) - 1);
cmd_status = handle_command(_key, _value);
}

GREENTEA_TESTSUITE_RESULT(CMD_STATUS_PASS == cmd_status);
}

int main()
{
rtc_reset_test();
}
4 changes: 2 additions & 2 deletions doxyfile_options
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ INPUT_ENCODING = UTF-8
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.

FILE_PATTERNS = *.h
FILE_PATTERNS = *.h *.c *.cpp

# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
Expand Down Expand Up @@ -837,7 +837,6 @@ EXCLUDE_SYMLINKS = YES
# exclude all test directories for example use the pattern */test/*

EXCLUDE_PATTERNS = */tools/* \
*/TESTS/* \
*/targets/* \
*/BUILD/* \
*/rtos/TARGET_CORTEX/rtx* \
Expand All @@ -847,6 +846,7 @@ EXCLUDE_PATTERNS = */tools/* \
*/features/storage/* \
*/features/unsupported/* \
*/features/filesystem/* \
*/features/frameworks/*/source/* \

# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
Expand Down
3 changes: 2 additions & 1 deletion doxygen_options.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
"PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_LOWPOWERTIMER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\"",
"EXPAND_AS_DEFINED": "",
"SKIP_FUNCTION_MACROS": "NO",
"EXCLUDE_PATTERNS": "*/tools/* */TESTS/* */targets/* */FEATURE_*/* */features/mbedtls/* */features/storage/* */features/unsupported/* */features/filesystem/* */BUILD/* */rtos/TARGET_CORTEX/rtx*/* */cmsis/* */features/FEATURES_*"
"FILE_PATTERNS": "*.h *.c *.cpp",
"EXCLUDE_PATTERNS": "*/tools/* */targets/* */FEATURE_*/* */features/mbedtls/* */features/storage/* */features/unsupported/* */features/filesystem/* */BUILD/* */rtos/TARGET_CORTEX/rtx*/* */cmsis/* */features/FEATURES_* */features/frameworks/*/source/*"
}
Loading