diff --git a/doc/hardware/peripherals/rtc.rst b/doc/hardware/peripherals/rtc.rst index 6098f5e4a8a..0b053f548e4 100644 --- a/doc/hardware/peripherals/rtc.rst +++ b/doc/hardware/peripherals/rtc.rst @@ -59,3 +59,8 @@ API Reference ************* .. doxygengroup:: rtc_interface + +RTC device driver test suite +**************************** + +See :ref:`rtc_api_test` diff --git a/drivers/rtc/CMakeLists.txt b/drivers/rtc/CMakeLists.txt index 7addf32d314..cca66cf41fc 100644 --- a/drivers/rtc/CMakeLists.txt +++ b/drivers/rtc/CMakeLists.txt @@ -4,4 +4,5 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c) +zephyr_library_sources_ifdef(CONFIG_RTC_EMUL rtc_emul.c) diff --git a/dts/bindings/rtc/rtc-device.yaml b/dts/bindings/rtc/rtc-device.yaml new file mode 100644 index 00000000000..07f12aacaab --- /dev/null +++ b/dts/bindings/rtc/rtc-device.yaml @@ -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 diff --git a/tests/drivers/rtc/rtc_api/CMakeLists.txt b/tests/drivers/rtc/rtc_api/CMakeLists.txt new file mode 100644 index 00000000000..bef2a923f1d --- /dev/null +++ b/tests/drivers/rtc/rtc_api/CMakeLists.txt @@ -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) diff --git a/tests/drivers/rtc/rtc_api/doc/rtc_test.rst b/tests/drivers/rtc/rtc_api/doc/rtc_test.rst new file mode 100644 index 00000000000..7846670f131 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/doc/rtc_test.rst @@ -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``. diff --git a/tests/drivers/rtc/rtc_api/prj.conf b/tests/drivers/rtc/rtc_api/prj.conf new file mode 100644 index 00000000000..2d8e4c373a8 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/prj.conf @@ -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 diff --git a/tests/drivers/rtc/rtc_api/src/main.c b/tests/drivers/rtc/rtc_api/src/main.c new file mode 100644 index 00000000000..1c5ce94429e --- /dev/null +++ b/tests/drivers/rtc/rtc_api/src/main.c @@ -0,0 +1,9 @@ +/* + * Copyright 2022 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +ZTEST_SUITE(rtc_api, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/rtc/rtc_api/src/test_alarm.c b/tests/drivers/rtc/rtc_api/src/test_alarm.c new file mode 100644 index 00000000000..dc224c9e465 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/src/test_alarm.c @@ -0,0 +1,143 @@ +/* + * Copyright 2022 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +/* 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"); + } +} diff --git a/tests/drivers/rtc/rtc_api/src/test_alarm_callback.c b/tests/drivers/rtc/rtc_api/src/test_alarm_callback.c new file mode 100644 index 00000000000..9dfa73eaace --- /dev/null +++ b/tests/drivers/rtc/rtc_api/src/test_alarm_callback.c @@ -0,0 +1,169 @@ +/* + * Copyright 2022 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +/* 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"); + } +} diff --git a/tests/drivers/rtc/rtc_api/src/test_calibrate.c b/tests/drivers/rtc/rtc_api/src/test_calibrate.c new file mode 100644 index 00000000000..939f9c144a6 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/src/test_calibrate.c @@ -0,0 +1,87 @@ +/* + * Copyright 2022 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#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; + } + } +} diff --git a/tests/drivers/rtc/rtc_api/src/test_time.c b/tests/drivers/rtc/rtc_api/src/test_time.c new file mode 100644 index 00000000000..832502d954b --- /dev/null +++ b/tests/drivers/rtc/rtc_api/src/test_time.c @@ -0,0 +1,68 @@ +/* + * Copyright 2022 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include + +/* 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"); +} diff --git a/tests/drivers/rtc/rtc_api/src/test_time_incrementing.c b/tests/drivers/rtc/rtc_api/src/test_time_incrementing.c new file mode 100644 index 00000000000..b1680f2eca7 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/src/test_time_incrementing.c @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include + +/* 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"); +} diff --git a/tests/drivers/rtc/rtc_api/src/test_update_callback.c b/tests/drivers/rtc/rtc_api/src/test_update_callback.c new file mode 100644 index 00000000000..d20ddb9eaea --- /dev/null +++ b/tests/drivers/rtc/rtc_api/src/test_update_callback.c @@ -0,0 +1,55 @@ +/* + * Copyright 2022 Bjarki Arge Andreasen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +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"); +} diff --git a/tests/drivers/rtc/rtc_api/testcase.yaml b/tests/drivers/rtc/rtc_api/testcase.yaml new file mode 100644 index 00000000000..fc86b05b374 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/testcase.yaml @@ -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