Skip to content

RTC specification (branch feature-hal-spec) #4931

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
wants to merge 2 commits into from
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

125 changes: 125 additions & 0 deletions TESTS/mbed_hal/rtc/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* 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"
#include "rtc_api_tests.h"

using namespace utest::v1;

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

void rtc_init_test()
{
for (int i = 0; i < 10; i++) {
rtc_init();
}
}

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);
}

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);
}

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();
}

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);
}
97 changes: 97 additions & 0 deletions TESTS/mbed_hal/rtc_reset/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* 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"
#include "rtc_api_tests.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;

}
}

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();
}
Loading