tests/drivers/rtc: Add unit tests for RTC devices
This test suite adds tests for the following: - Setting and getting time - Validating time is incrementing correctly - Validating behavior of alarms with callback disabled - Validating behavior of alarms with callback enabled - Validating update callback The test suite uses the devicetree alias rtc to find the device to test. Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
This commit is contained in:
parent
b557a1d711
commit
ac697d153d
14 changed files with 687 additions and 0 deletions
|
@ -59,3 +59,8 @@ API Reference
|
||||||
*************
|
*************
|
||||||
|
|
||||||
.. doxygengroup:: rtc_interface
|
.. doxygengroup:: rtc_interface
|
||||||
|
|
||||||
|
RTC device driver test suite
|
||||||
|
****************************
|
||||||
|
|
||||||
|
See :ref:`rtc_api_test`
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
zephyr_library()
|
zephyr_library()
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c)
|
zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_RTC_EMUL rtc_emul.c)
|
||||||
|
|
||||||
|
|
13
dts/bindings/rtc/rtc-device.yaml
Normal file
13
dts/bindings/rtc/rtc-device.yaml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Copyright (c) 2022 Bjarki Arge Andreasen
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
include: base.yaml
|
||||||
|
|
||||||
|
description: RTC device common bindings
|
||||||
|
|
||||||
|
properties:
|
||||||
|
alarms-count:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
description: |
|
||||||
|
Number of alarms supported by RTC device
|
35
tests/drivers/rtc/rtc_api/CMakeLists.txt
Normal file
35
tests/drivers/rtc/rtc_api/CMakeLists.txt
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# Copyright (c) 2022 Bjarki Arge Andreasen
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
|
||||||
|
project(rtc_api)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE
|
||||||
|
src/main.c
|
||||||
|
src/test_time_incrementing.c
|
||||||
|
src/test_time.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if(DEFINED CONFIG_RTC_ALARM)
|
||||||
|
target_sources(app PRIVATE
|
||||||
|
src/test_alarm_callback.c
|
||||||
|
src/test_alarm.c
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED CONFIG_RTC_UPDATE)
|
||||||
|
target_sources(app PRIVATE
|
||||||
|
src/test_update_callback.c
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED CONFIG_RTC_CALIBRATION)
|
||||||
|
target_sources(app PRIVATE
|
||||||
|
src/test_calibrate.c
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(app PRIVATE inc)
|
31
tests/drivers/rtc/rtc_api/doc/rtc_test.rst
Normal file
31
tests/drivers/rtc/rtc_api/doc/rtc_test.rst
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
.. _rtc_api_test:
|
||||||
|
|
||||||
|
:Author: Bjarki Arge Andreasen
|
||||||
|
|
||||||
|
RTC Test suite
|
||||||
|
###############
|
||||||
|
|
||||||
|
Test RTC API implementation for RTC devices.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
********
|
||||||
|
|
||||||
|
This suite is design to be portable between boards. It uses the alias
|
||||||
|
``rtc`` to designate the RTC device to test.
|
||||||
|
|
||||||
|
This test suite tests the following:
|
||||||
|
|
||||||
|
* Setting and getting the time.
|
||||||
|
* RTC Time incrementing correctly.
|
||||||
|
* Alarms if supported by hardware, with and without callback enabled
|
||||||
|
* Calibration if supported by hardware.
|
||||||
|
|
||||||
|
The calibration test tests a range of values which are printed to the
|
||||||
|
console to be manually compared. The user must review the set and
|
||||||
|
gotten values to ensure they are valid.
|
||||||
|
|
||||||
|
By default, only the mandatory Setting and getting time is enabled
|
||||||
|
for testing. To test the optional alarms, update event callback
|
||||||
|
and clock calibration, these must be enabled by selecting
|
||||||
|
``CONFIG_RTC_ALARM``, ``CONFIG_RTC_UPDATE`` and
|
||||||
|
``CONFIG_RTC_CALIBRATION``.
|
6
tests/drivers/rtc/rtc_api/prj.conf
Normal file
6
tests/drivers/rtc/rtc_api/prj.conf
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Copyright (c) 2022 Bjarki Arge Andreasen
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
CONFIG_RTC=y
|
||||||
|
CONFIG_ZTEST=y
|
||||||
|
CONFIG_ZTEST_NEW_API=y
|
9
tests/drivers/rtc/rtc_api/src/main.c
Normal file
9
tests/drivers/rtc/rtc_api/src/main.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Bjarki Arge Andreasen
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
|
||||||
|
ZTEST_SUITE(rtc_api, NULL, NULL, NULL, NULL, NULL);
|
143
tests/drivers/rtc/rtc_api/src/test_alarm.c
Normal file
143
tests/drivers/rtc/rtc_api/src/test_alarm.c
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Bjarki Arge Andreasen
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/rtc.h>
|
||||||
|
#include <zephyr/sys/atomic.h>
|
||||||
|
#include <zephyr/sys/timeutil.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* Fri Jan 01 2021 13:29:50 GMT+0000 */
|
||||||
|
#define RTC_TEST_ALARM_SET_TIME (1609507790)
|
||||||
|
#define RTC_TEST_ALARM_TEST_NOT_PENDING_DELAY (3)
|
||||||
|
#define RTC_TEST_ALARM_TEST_PENDING_DELAY (10)
|
||||||
|
#define RTC_TEST_ALARM_TIME_MINUTE (30)
|
||||||
|
#define RTC_TEST_ALARM_TIME_HOUR (13)
|
||||||
|
|
||||||
|
static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
|
||||||
|
static const uint16_t alarms_count = DT_PROP(DT_ALIAS(rtc), alarms_count);
|
||||||
|
|
||||||
|
ZTEST(rtc_api, test_alarm)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
time_t timer_set;
|
||||||
|
struct rtc_time time_set;
|
||||||
|
struct rtc_time alarm_time_set;
|
||||||
|
uint16_t alarm_time_mask_supported;
|
||||||
|
uint16_t alarm_time_mask_set;
|
||||||
|
struct rtc_time alarm_time_get;
|
||||||
|
uint16_t alarm_time_mask_get;
|
||||||
|
|
||||||
|
/* Clear alarm alarm time */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_set_time(rtc, i, 0, NULL);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to clear alarm time");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable alarm callback */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_set_callback(rtc, i, NULL, NULL);
|
||||||
|
|
||||||
|
zassert_true((ret == 0) || (ret == -ENOTSUP),
|
||||||
|
"Failed to clear and disable alarm callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate alarms supported fields */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to get supported alarm fields");
|
||||||
|
|
||||||
|
/* Skip test if alarm does not support the minute and hour fields */
|
||||||
|
if (((RTC_ALARM_TIME_MASK_MINUTE & alarm_time_mask_supported) == 0) ||
|
||||||
|
((RTC_TEST_ALARM_TIME_HOUR & alarm_time_mask_supported) == 0)) {
|
||||||
|
ztest_test_skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set alarm time */
|
||||||
|
alarm_time_set.tm_min = RTC_TEST_ALARM_TIME_MINUTE;
|
||||||
|
alarm_time_set.tm_hour = RTC_TEST_ALARM_TIME_HOUR;
|
||||||
|
alarm_time_mask_set = (RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_set_time(rtc, i, alarm_time_mask_set, &alarm_time_set);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to set alarm time");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate alarm time */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_get_time(rtc, i, &alarm_time_mask_get, &alarm_time_get);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to set alarm time");
|
||||||
|
|
||||||
|
zassert_true(alarm_time_mask_get == alarm_time_mask_set,
|
||||||
|
"Incorrect alarm time mask");
|
||||||
|
|
||||||
|
zassert_true(alarm_time_get.tm_min == alarm_time_get.tm_min,
|
||||||
|
"Incorrect alarm time minute field");
|
||||||
|
|
||||||
|
zassert_true(alarm_time_get.tm_hour == alarm_time_get.tm_hour,
|
||||||
|
"Incorrect alarm time hour field");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize RTC time to set */
|
||||||
|
timer_set = RTC_TEST_ALARM_SET_TIME;
|
||||||
|
|
||||||
|
gmtime_r(&timer_set, (struct tm *)(&time_set));
|
||||||
|
|
||||||
|
time_set.tm_isdst = -1;
|
||||||
|
time_set.tm_nsec = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 2; i++) {
|
||||||
|
/* Set RTC time */
|
||||||
|
ret = rtc_set_time(rtc, &time_set);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to set time");
|
||||||
|
|
||||||
|
/* Clear alarm pending status */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_is_pending(rtc, i);
|
||||||
|
|
||||||
|
zassert_true(ret > -1, "Failed to clear alarm pending status");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait before validating alarm pending status has not been set prematurely */
|
||||||
|
k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_NOT_PENDING_DELAY));
|
||||||
|
|
||||||
|
/* Validate alarm are not pending */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_is_pending(rtc, i);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Alarm should not be pending");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for alarm to trigger */
|
||||||
|
k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_PENDING_DELAY));
|
||||||
|
|
||||||
|
/* Validate alarm is pending */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_is_pending(rtc, i);
|
||||||
|
|
||||||
|
zassert_true(ret == 1, "Alarm should be pending");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable and clear alarms */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_set_time(rtc, i, 0, NULL);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to disable alarm");
|
||||||
|
|
||||||
|
ret = rtc_alarm_is_pending(rtc, i);
|
||||||
|
|
||||||
|
zassert_true(ret > -1, "Failed to clear alarm pending state");
|
||||||
|
}
|
||||||
|
}
|
169
tests/drivers/rtc/rtc_api/src/test_alarm_callback.c
Normal file
169
tests/drivers/rtc/rtc_api/src/test_alarm_callback.c
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Bjarki Arge Andreasen
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/rtc.h>
|
||||||
|
#include <zephyr/sys/atomic.h>
|
||||||
|
#include <zephyr/sys/timeutil.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* Fri Jan 01 2021 13:29:50 GMT+0000 */
|
||||||
|
#define RTC_TEST_ALARM_SET_TIME (1609507790)
|
||||||
|
#define RTC_TEST_ALARM_TEST_NOT_CALLED_DELAY (3)
|
||||||
|
#define RTC_TEST_ALARM_TEST_CALLED_DELAY (10)
|
||||||
|
#define RTC_TEST_ALARM_TIME_MINUTE (30)
|
||||||
|
#define RTC_TEST_ALARM_TIME_HOUR (13)
|
||||||
|
|
||||||
|
static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
|
||||||
|
static const uint16_t alarms_count = DT_PROP(DT_ALIAS(rtc), alarms_count);
|
||||||
|
static uint32_t callback_user_data_odd = 0x4321;
|
||||||
|
static uint32_t callback_user_data_even = 0x1234;
|
||||||
|
static atomic_t callback_called_mask_odd;
|
||||||
|
static atomic_t callback_called_mask_even;
|
||||||
|
|
||||||
|
static void test_rtc_alarm_callback_handler_odd(const struct device *dev, uint16_t id,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called_mask_odd, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_rtc_alarm_callback_handler_even(const struct device *dev, uint16_t id,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called_mask_even, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(rtc_api, test_alarm_callback)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
time_t timer_set;
|
||||||
|
struct rtc_time time_set;
|
||||||
|
struct rtc_time alarm_time_set;
|
||||||
|
uint16_t alarm_time_mask_supported;
|
||||||
|
uint16_t alarm_time_mask_set;
|
||||||
|
atomic_val_t callback_called_mask_status_odd;
|
||||||
|
atomic_val_t callback_called_mask_status_even;
|
||||||
|
bool callback_called_status;
|
||||||
|
|
||||||
|
/* Disable alarm callback */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_set_callback(rtc, i, NULL, NULL);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to clear and disable alarm");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate alarms supported fields */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_get_supported_fields(rtc, i, &alarm_time_mask_supported);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to get supported alarm fields");
|
||||||
|
|
||||||
|
/* Skip test if alarm does not support the minute and hour fields */
|
||||||
|
if (((RTC_ALARM_TIME_MASK_MINUTE & alarm_time_mask_supported) == 0) ||
|
||||||
|
((RTC_TEST_ALARM_TIME_HOUR & alarm_time_mask_supported) == 0)) {
|
||||||
|
ztest_test_skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set alarm time */
|
||||||
|
alarm_time_set.tm_min = RTC_TEST_ALARM_TIME_MINUTE;
|
||||||
|
alarm_time_set.tm_hour = RTC_TEST_ALARM_TIME_HOUR;
|
||||||
|
alarm_time_mask_set = (RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_set_time(rtc, i, alarm_time_mask_set, &alarm_time_set);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to set alarm time");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize RTC time to set */
|
||||||
|
timer_set = RTC_TEST_ALARM_SET_TIME;
|
||||||
|
|
||||||
|
gmtime_r(&timer_set, (struct tm *)(&time_set));
|
||||||
|
|
||||||
|
time_set.tm_isdst = -1;
|
||||||
|
time_set.tm_nsec = 0;
|
||||||
|
|
||||||
|
/* Set RTC time */
|
||||||
|
ret = rtc_set_time(rtc, &time_set);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to set time");
|
||||||
|
|
||||||
|
/* Clear alarm pending status */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_is_pending(rtc, i);
|
||||||
|
|
||||||
|
zassert_true(ret > -1, "Failed to clear alarm pending status");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set and enable alarm callback */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
if (i % 2) {
|
||||||
|
ret = rtc_alarm_set_callback(rtc, i,
|
||||||
|
test_rtc_alarm_callback_handler_odd,
|
||||||
|
&callback_user_data_odd);
|
||||||
|
} else {
|
||||||
|
ret = rtc_alarm_set_callback(rtc, i,
|
||||||
|
test_rtc_alarm_callback_handler_even,
|
||||||
|
&callback_user_data_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to set alarm callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 2; i++) {
|
||||||
|
/* Clear callback called atomics */
|
||||||
|
atomic_set(&callback_called_mask_odd, 0);
|
||||||
|
atomic_set(&callback_called_mask_even, 0);
|
||||||
|
|
||||||
|
/* Wait before validating alarm callbacks have not been called prematurely */
|
||||||
|
k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_NOT_CALLED_DELAY));
|
||||||
|
|
||||||
|
/* Validate alarm callbacks have not been called prematurely */
|
||||||
|
callback_called_mask_status_odd = atomic_get(&callback_called_mask_odd);
|
||||||
|
callback_called_mask_status_even = atomic_get(&callback_called_mask_even);
|
||||||
|
|
||||||
|
zassert_true(callback_called_mask_status_odd == 0,
|
||||||
|
"Alarm callback called prematurely");
|
||||||
|
zassert_true(callback_called_mask_status_even == 0,
|
||||||
|
"Alarm callback called prematurely");
|
||||||
|
|
||||||
|
/* Wait for alarm to trigger */
|
||||||
|
k_sleep(K_SECONDS(RTC_TEST_ALARM_TEST_CALLED_DELAY));
|
||||||
|
|
||||||
|
/* Validate alarm callback called */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
callback_called_status =
|
||||||
|
(i % 2) ? atomic_test_bit(&callback_called_mask_odd, i)
|
||||||
|
: atomic_test_bit(&callback_called_mask_even, i);
|
||||||
|
|
||||||
|
zassert_true(callback_called_status == true,
|
||||||
|
"Alarm callback should have been called");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset RTC time */
|
||||||
|
ret = rtc_set_time(rtc, &time_set);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to set time");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable and clear alarms */
|
||||||
|
for (uint16_t i = 0; i < alarms_count; i++) {
|
||||||
|
ret = rtc_alarm_set_callback(rtc, i, NULL, NULL);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to disable alarm callback");
|
||||||
|
|
||||||
|
ret = rtc_alarm_set_time(rtc, i, 0, NULL);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to disable alarm");
|
||||||
|
|
||||||
|
ret = rtc_alarm_is_pending(rtc, i);
|
||||||
|
|
||||||
|
zassert_true(ret > -1, "Failed to clear alarm pending state");
|
||||||
|
}
|
||||||
|
}
|
87
tests/drivers/rtc/rtc_api/src/test_calibrate.c
Normal file
87
tests/drivers/rtc/rtc_api/src/test_calibrate.c
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Bjarki Arge Andreasen
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/rtc.h>
|
||||||
|
|
||||||
|
#define RTC_TEST_CAL_RANGE_LIMIT (200000)
|
||||||
|
#define RTC_TEST_CAL_RANGE_STEP (10000)
|
||||||
|
|
||||||
|
static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
|
||||||
|
|
||||||
|
static int test_set_get_calibration(int32_t calibrate_set)
|
||||||
|
{
|
||||||
|
int32_t calibrate_get;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = rtc_set_calibration(rtc, calibrate_set);
|
||||||
|
|
||||||
|
/* Check if calibration is within limits of hardware */
|
||||||
|
if (ret == -EINVAL) {
|
||||||
|
/* skip */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate calibration was set */
|
||||||
|
zassert_true(ret == 0, "Failed to set calibration");
|
||||||
|
|
||||||
|
ret = rtc_get_calibration(rtc, &calibrate_get);
|
||||||
|
|
||||||
|
/* Validate calibration was gotten */
|
||||||
|
zassert_true(ret == 0, "Failed to get calibration");
|
||||||
|
|
||||||
|
/* Print comparison between set and get values */
|
||||||
|
printk("Calibrate (set,get): %i, %i\n", calibrate_set, calibrate_get);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(rtc_api, set_get_calibration)
|
||||||
|
{
|
||||||
|
int32_t calibrate_get;
|
||||||
|
int ret;
|
||||||
|
int32_t range_limit;
|
||||||
|
int32_t range_step;
|
||||||
|
|
||||||
|
ret = rtc_set_calibration(rtc, 0);
|
||||||
|
|
||||||
|
/* Validate calibration was set */
|
||||||
|
zassert_true(ret == 0, "Failed to set calibration");
|
||||||
|
|
||||||
|
ret = rtc_get_calibration(rtc, &calibrate_get);
|
||||||
|
|
||||||
|
/* Validate calibration was gotten */
|
||||||
|
zassert_true(ret == 0, "Failed to get calibration");
|
||||||
|
|
||||||
|
/* Validate edge values (0 already tested) */
|
||||||
|
test_set_get_calibration(1);
|
||||||
|
test_set_get_calibration(-1);
|
||||||
|
|
||||||
|
range_limit = RTC_TEST_CAL_RANGE_LIMIT;
|
||||||
|
range_step = RTC_TEST_CAL_RANGE_STEP;
|
||||||
|
|
||||||
|
/* Validate over negative range */
|
||||||
|
for (int32_t set = range_step; set <= range_limit; set += range_step) {
|
||||||
|
ret = test_set_get_calibration(-set);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
/* Limit of hardware capabilties reached */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate over positive range */
|
||||||
|
for (int32_t set = range_step; set <= range_limit; set += range_step) {
|
||||||
|
ret = test_set_get_calibration(set);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
/* Limit of hardware capabilties reached */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
tests/drivers/rtc/rtc_api/src/test_time.c
Normal file
68
tests/drivers/rtc/rtc_api/src/test_time.c
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Bjarki Arge Andreasen
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/rtc.h>
|
||||||
|
#include <zephyr/sys/timeutil.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Wed Dec 31 2025 23:59:55 GMT+0000 */
|
||||||
|
#define RTC_TEST_GET_SET_TIME (1767225595UL)
|
||||||
|
#define RTC_TEST_GET_SET_TIME_TOL (1UL)
|
||||||
|
|
||||||
|
static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
|
||||||
|
|
||||||
|
ZTEST(rtc_api, test_set_get_time)
|
||||||
|
{
|
||||||
|
struct rtc_time datetime_set;
|
||||||
|
struct rtc_time datetime_get;
|
||||||
|
time_t timer_get;
|
||||||
|
time_t timer_set = RTC_TEST_GET_SET_TIME;
|
||||||
|
|
||||||
|
gmtime_r(&timer_set, (struct tm *)(&datetime_set));
|
||||||
|
|
||||||
|
memset(&datetime_get, 0xFF, sizeof(datetime_get));
|
||||||
|
|
||||||
|
zassert_true(rtc_set_time(rtc, &datetime_set) == 0, "Failed to set time");
|
||||||
|
|
||||||
|
zassert_true(rtc_get_time(rtc, &datetime_get) == 0,
|
||||||
|
"Failed to get time using rtc_time_get()");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_sec > -1) && (datetime_get.tm_sec < 60),
|
||||||
|
"Invalid tm_sec");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_min > -1) && (datetime_get.tm_min < 60),
|
||||||
|
"Invalid tm_min");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_hour > -1) && (datetime_get.tm_hour < 24),
|
||||||
|
"Invalid tm_hour");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_mday > 0) && (datetime_get.tm_mday < 32),
|
||||||
|
"Invalid tm_mday");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_year > 124) && (datetime_get.tm_year < 127),
|
||||||
|
"Invalid tm_year");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_wday > -2) && (datetime_get.tm_wday < 7),
|
||||||
|
"Invalid tm_wday");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_yday > -2) && (datetime_get.tm_yday < 366),
|
||||||
|
"Invalid tm_yday");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_isdst == -1), "Invalid tm_isdst");
|
||||||
|
|
||||||
|
zassert_true((datetime_get.tm_nsec > -1) && (datetime_get.tm_yday < 1000000000),
|
||||||
|
"Invalid tm_yday");
|
||||||
|
|
||||||
|
timer_get = timeutil_timegm((struct tm *)(&datetime_get));
|
||||||
|
|
||||||
|
zassert_true((timer_get >= RTC_TEST_GET_SET_TIME) &&
|
||||||
|
(timer_get <= (RTC_TEST_GET_SET_TIME + RTC_TEST_GET_SET_TIME_TOL)),
|
||||||
|
"Got unexpected time");
|
||||||
|
}
|
57
tests/drivers/rtc/rtc_api/src/test_time_incrementing.c
Normal file
57
tests/drivers/rtc/rtc_api/src/test_time_incrementing.c
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Bjarki Arge Andreasen
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/rtc.h>
|
||||||
|
#include <zephyr/sys/timeutil.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* Wed Dec 31 2025 23:59:55 GMT+0000 */
|
||||||
|
#define RTC_TEST_TIME_COUNTING_SET_TIME (1767225595UL)
|
||||||
|
#define RTC_TEST_TIME_COUNTING_LIMIT (RTC_TEST_TIME_COUNTING_SET_TIME + 10UL)
|
||||||
|
#define RTC_TEST_TIME_COUNTING_POLL_LIMIT (30U)
|
||||||
|
|
||||||
|
static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
|
||||||
|
|
||||||
|
ZTEST(rtc_api, test_time_counting)
|
||||||
|
{
|
||||||
|
struct rtc_time datetime_set;
|
||||||
|
struct rtc_time datetime_get;
|
||||||
|
time_t timer_get;
|
||||||
|
time_t timer_set = RTC_TEST_TIME_COUNTING_SET_TIME;
|
||||||
|
time_t timer_get_last = timer_set;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
gmtime_r(&timer_set, (struct tm *)(&datetime_set));
|
||||||
|
|
||||||
|
zassert_true(rtc_set_time(rtc, &datetime_set) == 0, "Failed to set time");
|
||||||
|
|
||||||
|
for (i = 0; i < RTC_TEST_TIME_COUNTING_POLL_LIMIT; i++) {
|
||||||
|
/* Get time */
|
||||||
|
zassert_true(rtc_get_time(rtc, &datetime_get) == 0, "Failed to get time");
|
||||||
|
|
||||||
|
timer_get = timeutil_timegm((struct tm *)(&datetime_get));
|
||||||
|
|
||||||
|
/* Validate if time incrementing */
|
||||||
|
zassert_true(timer_get_last <= timer_get, "Time is decrementing");
|
||||||
|
|
||||||
|
/* Check if limit reached */
|
||||||
|
if (timer_get == RTC_TEST_TIME_COUNTING_LIMIT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save last timer get */
|
||||||
|
timer_get_last = timer_get;
|
||||||
|
|
||||||
|
/* Limit polling rate */
|
||||||
|
k_msleep(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
zassert_true(i < RTC_TEST_TIME_COUNTING_POLL_LIMIT,
|
||||||
|
"Timeout occurred waiting for time to increment");
|
||||||
|
}
|
55
tests/drivers/rtc/rtc_api/src/test_update_callback.c
Normal file
55
tests/drivers/rtc/rtc_api/src/test_update_callback.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Bjarki Arge Andreasen
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/rtc.h>
|
||||||
|
#include <zephyr/sys/atomic.h>
|
||||||
|
|
||||||
|
static const struct device *rtc = DEVICE_DT_GET(DT_ALIAS(rtc));
|
||||||
|
static atomic_t callback_called_counter;
|
||||||
|
static atomic_t callback_test_user_data_address;
|
||||||
|
static uint32_t test_user_data = 0x1234;
|
||||||
|
|
||||||
|
static void test_rtc_update_callback_handler(const struct device *dev, void *user_data)
|
||||||
|
{
|
||||||
|
atomic_inc(&callback_called_counter);
|
||||||
|
|
||||||
|
atomic_set(&callback_test_user_data_address, (uint32_t)user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(rtc_api, test_update_callback)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t counter;
|
||||||
|
uint32_t address;
|
||||||
|
|
||||||
|
ret = rtc_update_set_callback(rtc, NULL, NULL);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to clear and disable update callback");
|
||||||
|
|
||||||
|
atomic_set(&callback_called_counter, 0);
|
||||||
|
|
||||||
|
k_msleep(5000);
|
||||||
|
|
||||||
|
counter = atomic_get(&callback_called_counter);
|
||||||
|
|
||||||
|
zassert_true(counter == 0, "Update callback should not have been called");
|
||||||
|
|
||||||
|
ret = rtc_update_set_callback(rtc, test_rtc_update_callback_handler, &test_user_data);
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to set and enable update callback");
|
||||||
|
|
||||||
|
k_msleep(10000);
|
||||||
|
|
||||||
|
counter = atomic_get(&callback_called_counter);
|
||||||
|
|
||||||
|
address = atomic_get(&callback_test_user_data_address);
|
||||||
|
|
||||||
|
zassert_true(counter < 12 && counter > 8, "Invalid update callback called counter");
|
||||||
|
|
||||||
|
zassert_true(address == ((uint32_t)(&test_user_data)), "Incorrect user data");
|
||||||
|
}
|
8
tests/drivers/rtc/rtc_api/testcase.yaml
Normal file
8
tests/drivers/rtc/rtc_api/testcase.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2022 Bjarki Arge Andreasen
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
tests:
|
||||||
|
drivers.rtc.rtc_api:
|
||||||
|
tags: drivers rtc api
|
||||||
|
filter: dt_alias_exists("rtc")
|
||||||
|
depends_on: rtc
|
Loading…
Add table
Add a link
Reference in a new issue