Skip to content
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

include/drivers: Add RTC support #52618

Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions doc/develop/api/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ between major releases are available in the :ref:`zephyr_release_notes`.
- Experimental
- 3.1

* - :ref:`rtc_api`
- Experimental
- 3.4

* - :ref:`rtio_api`
- Experimental
- 3.2
Expand Down
51 changes: 48 additions & 3 deletions doc/hardware/peripherals/rtc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,54 @@ Real-Time Clock (RTC)
Overview
********

This is a placeholder for API specific to real-time clocks. Currently
all RTC peripherals are implemented through :ref:`counter_api` with
device-specific API for counters with real-time support.
.. list-table:: **Glossary**
:widths: 30 80
:header-rows: 1

* - Word
- Definition
* - Real-time clock
- Low power device tracking time using broken-down time
* - Real-time counter
- Low power counter which can be used to track time
* - RTC
- Acronym for real-time clock

An RTC is a low power device which tracks time using broken-down time.
It should not be confused with low-power counters which sometimes share
the same name, acronym, or both.

RTCs are usually optimized for low energy consumption and are usually
kept running even when the system is in a low power state.

RTCs usually contain one or more alarms which can be configured to
trigger at a given time. These alarms are commonly used to wake up the
system from a low power state.

History of RTCs in Zephyr
*************************

RTCs have been supported before this API was created, using the
:ref:`counter_api` API. The unix timestamp was used to convert
between broken-down time and the unix timestamp within the RTC
drivers, which internally used the broken-down time representation.

The disadvantages of this approach where that hardware counters can
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The disadvantages of this approach where that hardware counters can
The disadvantages of this approach were that hardware counters could

not be set to a specific count, requiring all RTCs to use device
specific APIs to set the time, converting from unix time to
broken-down time, unnecessarily in some cases, and some common
features missing, like input clock calibration and the update
callback.

Configuration Options
*********************

Related configuration options:

* :kconfig:option:`CONFIG_RTC`
* :kconfig:option:`CONFIG_RTC_ALARM`
* :kconfig:option:`CONFIG_RTC_UPDATE`
* :kconfig:option:`CONFIG_RTC_CALIBRATION`

API Reference
*************
Expand Down
1 change: 1 addition & 0 deletions drivers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,4 @@ add_subdirectory_ifdef(CONFIG_VIRTUALIZATION virtualization)
add_subdirectory_ifdef(CONFIG_W1 w1)
add_subdirectory_ifdef(CONFIG_WATCHDOG watchdog)
add_subdirectory_ifdef(CONFIG_WIFI wifi)
add_subdirectory_ifdef(CONFIG_RTC rtc)
1 change: 1 addition & 0 deletions drivers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,6 @@ source "drivers/w1/Kconfig"
source "drivers/watchdog/Kconfig"
source "drivers/wifi/Kconfig"
source "drivers/xen/Kconfig"
source "drivers/rtc/Kconfig"

endmenu
7 changes: 7 additions & 0 deletions drivers/rtc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) 2022 Bjarki Arge Andreasen
# SPDX-License-Identifier: Apache-2.0

zephyr_library()

zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c)

26 changes: 26 additions & 0 deletions drivers/rtc/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) 2022 Bjarki Arge Andreasen
# SPDX-License-Identifier: Apache-2.0

menuconfig RTC
bool "RTC driver support"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would put "real time clock" in a help field here, just so that it is obvious to someone browsing Kconfig options without having to dive into the documentation


if RTC

config RTC_ALARM
bool "RTC driver alarm support"
help
This is an option which enables driver support for RTC alarms.

config RTC_UPDATE
bool "RTC driver update event callback support"
help
This is an option which enables driver support for the RTC
update event callback.

config RTC_CALIBRATION
bool "RTC driver clock calibration support"
help
This is an option which enables driver support for RTC clock
calibration.
Comment on lines +9 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these really necessary? At some point, configuration options get too fine-grained.


endif # RTC
79 changes: 79 additions & 0 deletions drivers/rtc/rtc_handlers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2022 Bjarki Arge Andreasen
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/drivers/rtc.h>
#include <zephyr/syscall_handler.h>

static inline int z_vrfy_rtc_set_time(const struct device *dev, const struct rtc_time *timeptr)
{
Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, set_time));
Z_OOPS(Z_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time)));
return z_impl_rtc_set_time(dev, timeptr);
}
#include <syscalls/rtc_set_time_mrsh.c>

static inline int z_vrfy_rtc_get_time(const struct device *dev, struct rtc_time *timeptr)
{
Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, get_time));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time)));
return z_impl_rtc_get_time(dev, timeptr);
}
#include <syscalls/rtc_get_time_mrsh.c>

#ifdef CONFIG_RTC_ALARM
static inline int z_vrfy_rtc_alarm_get_supported_fields(const struct device *dev, uint16_t id,
uint16_t *mask)
{
Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, alarm_get_supported_fields));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(mask, sizeof(uint16_t)));
return z_impl_rtc_alarm_get_supported_fields(dev, id, mask);
}
#include <syscalls/rtc_alarm_get_supported_fields_mrsh.c>

static inline int z_vrfy_rtc_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
const struct rtc_time *timeptr)
{
Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, alarm_set_time));
Z_OOPS(Z_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time)));
return z_impl_rtc_alarm_set_time(dev, id, mask, timeptr);
nordicjm marked this conversation as resolved.
Show resolved Hide resolved
}
#include <syscalls/rtc_alarm_set_time_mrsh.c>

static inline int z_vrfy_rtc_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
struct rtc_time *timeptr)
{
Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, alarm_get_time));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(mask, sizeof(uint16_t)));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time)));
return z_impl_rtc_alarm_get_time(dev, id, mask, timeptr);
}
#include <syscalls/rtc_alarm_get_time_mrsh.c>

static inline int z_vrfy_rtc_alarm_is_pending(const struct device *dev, uint16_t id)
{
Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, alarm_is_pending));
return z_impl_rtc_alarm_is_pending(dev, id);
}
#include <syscalls/rtc_alarm_is_pending_mrsh.c>
#endif /* CONFIG_RTC_ALARM */

#ifdef CONFIG_RTC_CALIBRATION
static inline int z_vrfy_rtc_set_calibration(const struct device *dev, int32_t calibration)
bjarki-andreasen marked this conversation as resolved.
Show resolved Hide resolved
{
Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, set_calibration));
return z_impl_rtc_set_calibration(dev, calibration);
}

#include <syscalls/rtc_set_calibration_mrsh.c>

static inline int z_vrfy_rtc_get_calibration(const struct device *dev, int32_t *calibration)
{
Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, get_calibration));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(calibration, sizeof(int32_t)));
return z_impl_rtc_get_calibration(dev, calibration);
}
#include <syscalls/rtc_get_calibration_mrsh.c>
#endif /* CONFIG_RTC_CALIBRATION */
Loading