Skip to content

[RFC] Adding RTC API #23526

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 7 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
1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
/drivers/pinmux/stm32/ @rsalveti @idlethread
/drivers/pinmux/*hsdk* @iriszzw
/drivers/pwm/*litex* @mateusz-holenko @kgugala @pgielda
/drivers/rtc/ @jdascenzio
/drivers/sensor/ @MaureenHelm
/drivers/sensor/ams_iAQcore/ @alexanderwachter
/drivers/sensor/ens210/ @alexanderwachter
Expand Down
1 change: 1 addition & 0 deletions boards/arm/disco_l475_iot1/disco_l475_iot1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ supported:
- nvs
- vl53l0x
- watchdog
- rtc
ram: 96
flash: 1024
1 change: 1 addition & 0 deletions boards/arm/nucleo_l432kc/nucleo_l432kc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ supported:
- can
- counter
- spi
- rtc
1 change: 1 addition & 0 deletions boards/arm/nucleo_l452re/nucleo_l452re.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ supported:
- can
- counter
- spi
- rtc
1 change: 1 addition & 0 deletions boards/arm/nucleo_l476rg/nucleo_l476rg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ supported:
- i2c
- counter
- adc
- rtc
ram: 96
flash: 1024
1 change: 1 addition & 0 deletions boards/arm/nucleo_l496zg/nucleo_l496zg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ supported:
- pwm
- counter
- watchdog
- rtc
testing:
ignore_tags:
- net
Expand Down
1 change: 1 addition & 0 deletions boards/arm/nucleo_l4r5zi/nucleo_l4r5zi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ supported:
- usb device
- nvs
- counter
- rtc
ram: 640
flash: 2048
1 change: 1 addition & 0 deletions boards/arm/sensortile_box/sensortile_box.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ supported:
- usb device
- nvs
- counter
- rtc
ram: 640
flash: 2048
1 change: 1 addition & 0 deletions boards/arm/stm32l476g_disco/stm32l476g_disco.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ flash: 1024
supported:
- gpio
- counter
- rtc
1 change: 1 addition & 0 deletions boards/arm/stm32l496g_disco/stm32l496g_disco.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ supported:
- spi
- gpio
- counter
- rtc
2 changes: 2 additions & 0 deletions drivers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ source "drivers/sensor/Kconfig"

source "drivers/counter/Kconfig"

source "drivers/rtc/Kconfig"

source "drivers/dma/Kconfig"

source "drivers/usb/Kconfig"
Expand Down
7 changes: 7 additions & 0 deletions drivers/rtc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_library()
Copy link
Member

Choose a reason for hiding this comment

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

In commit drivers: rtc: add system call handlers, I can understand that it is easy to just copy the commit subject to the body but we should try to avoid this. It is really annoying later if one looks the commits and tries to understand what the commit is about and both the subject and body are same (not really applicable for this commit as it is easy to understand what the commit does but as a general note). For example here the commit body could say Add system call handlers so that the RTC get/set functions can be called from userspace. So the commit body should tell why we are doing the change, it is usually not necessary to document what the commit does as that can be usually seen from the code.


zephyr_library_sources_ifdef(CONFIG_RTC_STM32 rtc_stm32.c)

zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c)
17 changes: 17 additions & 0 deletions drivers/rtc/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright (c) 2020 Paratronic
# SPDX-License-Identifier: Apache-2.0

menuconfig RTC
bool "RTC Drivers"
help
Enable support for RTC.

if RTC

module = RTC
module-str = rtc
source "subsys/logging/Kconfig.template.log_config"

source "drivers/rtc/Kconfig.rtc_stm32"

endif # RTC
25 changes: 25 additions & 0 deletions drivers/rtc/Kconfig.rtc_stm32
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (c) 2020 Paratronic
# SPDX-License-Identifier: Apache-2.0

menuconfig RTC_STM32
bool "STM32 RTC Driver"
depends on SOC_FAMILY_STM32 && !COUNTER_RTC_STM32
select USE_STM32_LL_RTC
help
Build RTC driver for STM32 SoCs

choice RTC_STM32_CLOCK_SRC
bool "RTC clock source"
depends on RTC_STM32

config RTC_STM32_CLOCK_LSI
bool "LSI"
help
Use LSI as RTC clock

config RTC_STM32_CLOCK_LSE
bool "LSE"
help
Use LSE as RTC clock

endchoice #RTC_STM32_CLOCK_SRC
26 changes: 26 additions & 0 deletions drivers/rtc/rtc_handlers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2020 Paratronic
*
* SPDX-License-Identifier: Apache-2.0
*/

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

static inline int z_vrfy_rtc_get_time(struct device *dev,
struct timespec *tp)
{
Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RTC));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(tp, sizeof(*tp)));
return z_impl_rtc_get_time(dev, tp);
}
#include <syscalls/rtc_get_time_mrsh.c>

static inline int z_vrfy_rtc_set_time(struct device *dev,
const struct timespec *tp)
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here: Z_OOPS(Z_SYSCALL_MEMORY_READ(tp, sizeof(*tp)));

Z_OOPS(Z_SYSCALL_DRIVER_RTC(dev, set_time));
Z_OOPS(Z_SYSCALL_MEMORY_READ(tp, sizeof(*tp)));
return z_impl_rtc_set_time(dev, tp);
}
#include <syscalls/rtc_set_time_mrsh.c>
180 changes: 180 additions & 0 deletions drivers/rtc/rtc_stm32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* Copyright (c) 2020 Paratronic
* SPDX-License-Identifier: Apache-2.0
*
* Source file for the STM32 RTC driver
*
*/


#include <kernel.h>
#include <soc.h>
#include <drivers/clock_control/stm32_clock_control.h>
#include <drivers/rtc.h>
#include <sys/timeutil.h>

#define LOG_LEVEL CONFIG_RTC_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(rtc);

#if defined(CONFIG_RTC_STM32_CLOCK_LSI)
/* prescaler values for LSI @ 32 KHz */
#define RTC_PREDIV_ASYNC 31
#define RTC_PREDIV_SYNC 999
#else /* CONFIG_RTC_STM32_CLOCK_LSE */
/* prescaler values for LSE @ 32768 Hz */
#define RTC_PREDIV_ASYNC 127
#define RTC_PREDIV_SYNC 255
#endif

static int rtc_stm32_set_time(struct device *dev, const struct timespec *tp)
{
int err = -EIO;
struct tm tm;
LL_RTC_TimeTypeDef timeDef;
LL_RTC_DateTypeDef dateDef;
const char *serr = NULL;
int key;

ARG_UNUSED(dev);

key = irq_lock();

LL_PWR_EnableBkUpAccess();

gmtime_r(&tp->tv_sec, &tm);
timeDef.Hours = tm.tm_hour;
timeDef.Minutes = tm.tm_min;
timeDef.Seconds = tm.tm_sec;
if (LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BIN, &timeDef) != SUCCESS) {
serr = "failed to set time";
goto out;
}

dateDef.WeekDay = ((tm.tm_wday + 6) % 7) + 1;
dateDef.Month = tm.tm_mon + 1;
dateDef.Day = tm.tm_mday;
dateDef.Year = (tm.tm_year + 1900) - 2000;
if (LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BIN, &dateDef) != SUCCESS) {
serr = "failed to set date";
goto out;
}

err = 0;
out:
LL_PWR_DisableBkUpAccess();

irq_unlock(key);

if (serr) {
LOG_ERR("%s", serr);
}

return err;
}

static int rtc_stm32_get_time(struct device *dev, struct timespec *tp)
{
struct tm tm;
u32_t time;
u32_t subSeconds;
u32_t date;
int key;

ARG_UNUSED(dev);

key = irq_lock();
subSeconds = LL_RTC_TIME_GetSubSecond(RTC);
time = LL_RTC_TIME_Get(RTC);
date = LL_RTC_DATE_Get(RTC);
irq_unlock(key);

tm.tm_sec = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_SECOND(time));
tm.tm_min = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MINUTE(time));
tm.tm_hour = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_HOUR(time));

tm.tm_mday = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_DAY(date));
tm.tm_mon = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MONTH(date)) - 1;
tm.tm_year = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_YEAR(date)) + 100;
tp->tv_sec = timeutil_timegm(&tm);
tp->tv_nsec = ((u64_t)(RTC_PREDIV_SYNC - subSeconds) * NSEC_PER_SEC) /
(RTC_PREDIV_SYNC + 1);

return 0;
}

static int rtc_stm32_init(struct device *dev)
{
int err = -EIO;
struct device *clk;
struct stm32_pclken pclken;
LL_RTC_InitTypeDef init;

clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
__ASSERT_NO_MSG(clk);

pclken.enr = DT_INST_0_ST_STM32_RTC_CLOCK_BITS;
pclken.bus = DT_INST_0_ST_STM32_RTC_CLOCK_BUS;
clock_control_on(clk, (clock_control_subsys_t *) &pclken);

LL_PWR_EnableBkUpAccess();

#if defined(CONFIG_RTC_STM32_CLOCK_LSI)
LL_RCC_LSI_Enable();

/* Wait until LSI is ready */
while (LL_RCC_LSI_IsReady() != 1) {
}

LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);

#else /* CONFIG_RTC_STM32_CLOCK_LSE */
LL_RCC_LSE_Enable();

/* Wait until LSE is ready */
while (LL_RCC_LSE_IsReady() != 1) {
}

LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);

#endif

LL_RCC_EnableRTC();

init.HourFormat = RTC_HOURFORMAT_24;
init.AsynchPrescaler = RTC_PREDIV_ASYNC;
init.SynchPrescaler = RTC_PREDIV_SYNC;
if (LL_RTC_Init(RTC, &init) != SUCCESS) {
LOG_ERR("failed to init");
goto out;
}
/* check if calendar has been initialized */
if (!LL_RTC_IsActiveFlag_INITS(RTC)) {
LOG_INF("Datetime initialization");
struct timespec tp;
/* Init date time to 1 January 2001 00:00:00 */
tp.tv_sec = 978307200;
tp.tv_nsec = 0;
err = rtc_stm32_set_time(dev, &tp);
if (err < 0) {
goto out;
}
}

err = 0;
out:
LL_PWR_DisableBkUpAccess();
if (err == 0) {
LOG_DBG("RTC initialised correctly");
}
return err;
}

static const struct rtc_driver_api rtc_stm32_driver_api = {
.get_time = rtc_stm32_get_time,
.set_time = rtc_stm32_set_time,
};

DEVICE_AND_API_INIT(rtc_stm32, DT_RTC_0_NAME, &rtc_stm32_init,
NULL, NULL, PRE_KERNEL_1,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &rtc_stm32_driver_api);
Loading