drivers: rtc: Create utility function for time validation
RTC drivers should validate the `struct rtc_time`'s contents against the provided `mask`. Promote this common code to a new rtc_utils file and modify existing drivers to use this functionality. Extend the test coverage to include verifying this behaviour. This is groundwork ahead of adding support for the RP2040's (as used in the Raspberry Pi Pico) RTC and alarm. Signed-off-by: Andrew Featherstone <andrew.featherstone@gmail.com>
This commit is contained in:
parent
c975910f84
commit
4c880f4b0a
11 changed files with 200 additions and 74 deletions
|
@ -5,6 +5,8 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/rtc.h)
|
|||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(rtc_utils.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_RTC_AM1805 rtc_am1805.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_RTC_DS1307 rtc_ds1307.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c)
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/rtc.h>
|
||||
|
||||
#include "rtc_utils.h"
|
||||
|
||||
struct rtc_emul_data;
|
||||
|
||||
struct rtc_emul_work_delayable {
|
||||
|
@ -67,43 +69,6 @@ static bool rtc_emul_is_leap_year(struct rtc_time *datetime)
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RTC_ALARM
|
||||
static bool rtc_emul_validate_alarm_time(const struct rtc_time *timeptr, uint32_t mask)
|
||||
{
|
||||
if ((mask & RTC_ALARM_TIME_MASK_SECOND) &&
|
||||
(timeptr->tm_sec < 0 || timeptr->tm_sec > 59)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MINUTE) &&
|
||||
(timeptr->tm_min < 0 || timeptr->tm_min > 59)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_HOUR) &&
|
||||
(timeptr->tm_hour < 0 || timeptr->tm_hour > 23)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MONTH) &&
|
||||
(timeptr->tm_mon < 0 || timeptr->tm_mon > 11)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MONTHDAY) &&
|
||||
(timeptr->tm_mday < 1 || timeptr->tm_mday > 31)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_YEAR) &&
|
||||
(timeptr->tm_year < 0 || timeptr->tm_year > 199)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_RTC_ALARM */
|
||||
|
||||
static int rtc_emul_get_days_in_month(struct rtc_time *datetime)
|
||||
{
|
||||
const uint8_t *dim = (rtc_emul_is_leap_year(datetime) == true) ?
|
||||
|
@ -346,7 +311,7 @@ static int rtc_emul_alarm_set_time(const struct device *dev, uint16_t id, uint16
|
|||
}
|
||||
|
||||
if (mask > 0) {
|
||||
if (rtc_emul_validate_alarm_time(timeptr, mask) == false) {
|
||||
if (rtc_utils_validate_rtc_time(timeptr, mask) == false) {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
#define RTC_SAM_CALIBRATE_PPB_QUANTA (1500)
|
||||
#define RTC_SAM_CALIBRATE_PPB_LOW_SCALE (30500)
|
||||
|
||||
#define RTC_SAM_TIME_MASK \
|
||||
(RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | \
|
||||
RTC_ALARM_TIME_MASK_MONTH | RTC_ALARM_TIME_MASK_MONTHDAY | RTC_ALARM_TIME_MASK_YEAR | \
|
||||
RTC_ALARM_TIME_MASK_WEEKDAY)
|
||||
|
||||
typedef void (*rtc_sam_irq_init_fn_ptr)(void);
|
||||
|
||||
struct rtc_sam_config {
|
||||
|
@ -58,41 +63,6 @@ static void rtc_sam_enable_wp(void)
|
|||
REG_RTC_WPMR = RTC_SAM_WPMR_ENABLE;
|
||||
}
|
||||
|
||||
static bool rtc_sam_validate_tm(const struct rtc_time *timeptr, uint32_t mask)
|
||||
{
|
||||
if ((mask & RTC_ALARM_TIME_MASK_SECOND) &&
|
||||
(timeptr->tm_sec < 0 || timeptr->tm_sec > 59)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MINUTE) &&
|
||||
(timeptr->tm_min < 0 || timeptr->tm_min > 59)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_HOUR) &&
|
||||
(timeptr->tm_hour < 0 || timeptr->tm_hour > 23)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MONTH) &&
|
||||
(timeptr->tm_mon < 0 || timeptr->tm_mon > 11)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MONTHDAY) &&
|
||||
(timeptr->tm_mday < 1 || timeptr->tm_mday > 31)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_YEAR) &&
|
||||
(timeptr->tm_year < 0 || timeptr->tm_year > 199)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t rtc_sam_timr_from_tm(const struct rtc_time *timeptr)
|
||||
{
|
||||
uint32_t timr;
|
||||
|
@ -126,7 +96,7 @@ static int rtc_sam_set_time(const struct device *dev, const struct rtc_time *tim
|
|||
const struct rtc_sam_config *config = dev->config;
|
||||
Rtc *regs = config->regs;
|
||||
|
||||
if (rtc_sam_validate_tm(timeptr, UINT32_MAX) == false) {
|
||||
if (rtc_utils_validate_rtc_time(timeptr, RTC_SAM_TIME_MASK) == false) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
58
drivers/rtc/rtc_utils.c
Normal file
58
drivers/rtc/rtc_utils.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Bjarki Arge Andreasen
|
||||
* Copyright (c) 2024 Andrew Featherstone
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/drivers/rtc.h>
|
||||
|
||||
#include "rtc_utils.h"
|
||||
|
||||
bool rtc_utils_validate_rtc_time(const struct rtc_time *timeptr, uint16_t mask)
|
||||
{
|
||||
if ((mask & RTC_ALARM_TIME_MASK_SECOND) && (timeptr->tm_sec < 0 || timeptr->tm_sec > 59)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MINUTE) && (timeptr->tm_min < 0 || timeptr->tm_min > 59)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_HOUR) && (timeptr->tm_hour < 0 || timeptr->tm_hour > 23)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MONTH) && (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_MONTHDAY) &&
|
||||
(timeptr->tm_mday < 1 || timeptr->tm_mday > 31)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_YEAR) && (timeptr->tm_year < 0 || timeptr->tm_year > 199)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_WEEKDAY) &&
|
||||
(timeptr->tm_wday < 0 || timeptr->tm_wday > 6)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_YEARDAY) &&
|
||||
(timeptr->tm_yday < 0 || timeptr->tm_yday > 365)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((mask & RTC_ALARM_TIME_MASK_NSEC) &&
|
||||
(timeptr->tm_nsec < 0 || timeptr->tm_nsec > 999999999)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
28
drivers/rtc/rtc_utils.h
Normal file
28
drivers/rtc/rtc_utils.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Bjarki Arge Andreasen
|
||||
* Copyright (c) 2024 Andrew Featherstone
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_RTC_RTC_UTILS_H_
|
||||
#define ZEPHYR_DRIVERS_RTC_RTC_UTILS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/drivers/rtc.h>
|
||||
|
||||
/**
|
||||
* @brief Validate a datetime with a mask
|
||||
*
|
||||
* Ensure that any fields selected by mask contain a valid value.
|
||||
*
|
||||
* @param timeptr The time to set
|
||||
* @param mask Mask of fields to validate
|
||||
*
|
||||
* @return true if the required fields are valid.
|
||||
*/
|
||||
bool rtc_utils_validate_rtc_time(const struct rtc_time *timeptr, uint16_t mask);
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_RTC_RTC_UTILS_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue