diff --git a/libraries/RTC/RTC.cpp b/libraries/RTC/RTC.cpp new file mode 100644 index 000000000..4308a4366 --- /dev/null +++ b/libraries/RTC/RTC.cpp @@ -0,0 +1,799 @@ +#include "RTC.h" +#include +#include +#include +#include +#include + +Rtc::~Rtc() { +} + +bool Rtc::setYear(int year) { + if (year < 1970 || year > 2100) { + return false; + } + int currentYear, month, day, hour, minute, second; + int retVal = getTime(currentYear, month, day, hour, minute, second); + if (retVal == 0) { + retVal = setTime(year, month, day, hour, minute, second); + if (retVal == 0u) { + return true; + } + } + + return false; +} + +bool Rtc::setMonthOfYear(int month) { + if (month < 1 || month > 12) { + return false; + } + int year, currentMonth, day, hour, minute, second; + int retVal = getTime(year, currentMonth, day, hour, minute, second); + if (retVal == 0) { + retVal = setTime(year, month, day, hour, minute, second); + if (retVal == 0u) { + return true; + } + } + return false; +} + +bool Rtc::setDayOfMonth(int day) { + if (day < 1 || day > 31) { + return false; + } + int year, month, currentDay, hour, minute, second; + int retVal = getTime(year, month, currentDay, hour, minute, second); + if (retVal == 0) { + retVal = setTime(year, month, day, hour, minute, second); + if (retVal == 0u) { + return true; + } + } + return false; +} + +bool Rtc::setHour(int hour) { + if (hour < 0 || hour > 23) { + return false; + } + int year, month, day, currentHour, minute, second; + int retVal = getTime(year, month, day, currentHour, minute, second); + if (retVal == 0) { + retVal = setTime(year, month, day, hour, minute, second); + if (retVal == 0u) { + return true; + } + } + return false; +} + +bool Rtc::setMinute(int minute) { + if (minute < 0 || minute > 59) { + return false; + } + int year, month, day, hour, currentMinute, second; + int retVal = getTime(year, month, day, hour, currentMinute, second); + if (retVal == 0) { + retVal = setTime(year, month, day, hour, minute, second); + if (retVal == 0u) { + return true; + } + } + return false; +} + +bool Rtc::setSecond(int second) { + if (second < 0 || second > 59) { + return false; + } + int year, month, day, hour, minute, currentSecond; + int retVal = getTime(year, month, day, hour, minute, currentSecond); + if (retVal == 0) { + retVal = setTime(year, month, day, hour, minute, second); + if (retVal == 0u) { + return true; + } + } + return false; +} + +int Rtc::getYear() { + int year, month, day, hour, minute, second; + int retVal = getTime(year, month, day, hour, minute, second); + if (retVal == 0) { + return year; + } + return -1; +} + +int Rtc::getMonth() { + int year, month, day, hour, minute, second; + int retVal = getTime(year, month, day, hour, minute, second); + if (retVal == 0) { + return month; + } + return -1; +} + +int Rtc::getDayOfMonth() { + int year, month, day, hour, minute, second; + int retVal = getTime(year, month, day, hour, minute, second); + if (retVal == 0) { + return day; + } + return -1; +} + +int Rtc::getHour() { + int year, month, day, hour, minute, second; + int retVal = getTime(year, month, day, hour, minute, second); + if (retVal == 0) { + return hour; + } + return -1; +} + +int Rtc::getMinutes() { + int year, month, day, hour, minute, second; + int retVal = getTime(year, month, day, hour, minute, second); + if (retVal == 0) { + return minute; + } + return -1; +} + +int Rtc::getSeconds() { + int year, month, day, hour, minute, second; + int retVal = getTime(year, month, day, hour, minute, second); + if (retVal == 0) { + return second; + } + return -1; +} + +#ifdef CONFIG_RTC_STM32 + +#if DT_NODE_EXISTS(DT_NODELABEL(rtc)) +#define RTC_NODE DT_NODELABEL(rtc) +#else +#define RTC_NODE DT_INVALID_NODE +#warning "RTC node not found in devicetree" +#endif + +/** + * @brief Rtc library constructor + * + * Constructor used with the STM32 microcontroller based boards (OPTA, PORTENTA H7, GIGA R1) + * + */ +Rtc::Rtc() { + rtc_dev = DEVICE_DT_GET_OR_NULL(RTC_NODE); + if (!rtc_dev) { + printk("RTC device not found in device tree\n"); + } +} + +/** + * @brief Rtc library classic begin() function + * + * Takes care of the underlying STM32 RTC HAL driver initalization + * + * @return bool operation result + */ +bool Rtc::begin() { + if (!device_is_ready(rtc_dev)) { + printk("RTC:: not ready\n"); + return false; + } + + // Register the alarm callback (even if not active yet) + rtc_alarm_set_callback(rtc_dev, alarmId, Rtc::alarmCallbackWrapper, this); + + return true; +} + +/** + * @brief Rtc library setter function + * + * Used to set the time and data with a single function call + * + * @param int year to be set + * @param int month to be set + * @param int day to be set + * @param int hour to be set + * @param int minute to be set + * @param int second to be set + * @return int operation result + */ +int Rtc::setTime(int year, int month, int day, int hour, int minute, int second) { + struct rtc_time time = { + .tm_sec = second, + .tm_min = minute, + .tm_hour = hour, + .tm_mday = day, + .tm_mon = month - 1, + .tm_year = year - 1900, + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = -1, /**< Daylight saving time flag (Unknown = -1) */ + .tm_nsec = 0 /* Nanoseconds (Unknown = 0) */ + }; + + return rtc_set_time(rtc_dev, &time); +} + +/** + * @brief Rtc library getter + * + * Used to get the time and date with a single function call + * + * @param int reference to currently set year + * @param int reference to currently set month + * @param int reference to currently set day of month + * @param int reference to currently set hour + * @param int reference to currently set minute + * @param int reference to currently set second + */ +int Rtc::getTime(int &year, int &month, int &day, int &hour, int &minute, int &second) { + struct rtc_time time; + int ret = rtc_get_time(rtc_dev, &time); + if (ret < 0) { + return ret; + } + + year = time.tm_year + 1900; + month = time.tm_mon + 1; + day = time.tm_mday; + hour = time.tm_hour; + minute = time.tm_min; + second = time.tm_sec; + + return 0; +} + +/** + * @brief Rtc library setter + * + * Used to set the alarm time through a single function call + * + * @param int year to be set + * @param int month to be set + * @param int day to be set + * @param int hour to be set + * @param int minute to be set + * @param int second to be set + * @return int operation result + */ +int Rtc::setAlarm(int year, int month, int day, int hour, int minute, int second, + RtcAlarmCallback cb, void *user_data) { + struct rtc_time alarm_time = { + .tm_sec = second, + .tm_min = minute, + .tm_hour = hour, + .tm_mday = day, + .tm_mon = month - 1, + .tm_year = year - 1900, + .tm_wday = -1, /* unknown */ + .tm_yday = -1, /* unknown */ + .tm_isdst = -1, /* unknown */ + .tm_nsec = 0 /* unknown */ + }; + + uint16_t supported_mask = 0; + int ret = rtc_alarm_get_supported_fields(rtc_dev, alarmId, &supported_mask); + if (ret < 0) { + return ret; + } + + // Build the actual mask based on what we intend to set + uint16_t mask = 0; + if (supported_mask & RTC_ALARM_TIME_MASK_SECOND) { + mask |= RTC_ALARM_TIME_MASK_SECOND; + } + if (supported_mask & RTC_ALARM_TIME_MASK_MINUTE) { + mask |= RTC_ALARM_TIME_MASK_MINUTE; + } + if (supported_mask & RTC_ALARM_TIME_MASK_HOUR) { + mask |= RTC_ALARM_TIME_MASK_HOUR; + } + if (supported_mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + } + if (supported_mask & RTC_ALARM_TIME_MASK_MONTH) { + mask |= RTC_ALARM_TIME_MASK_MONTH; + } + if (supported_mask & RTC_ALARM_TIME_MASK_YEAR) { + mask |= RTC_ALARM_TIME_MASK_YEAR; + } + + // Save user callback + userAlarmCallback = cb; + userAlarmCallbackData = user_data; + + return rtc_alarm_set_time(rtc_dev, alarmId, mask, &alarm_time); +} + +/** + * @brief Rtc library getter + * + * Used to get the time and date of the currently set alarm + * + * @param int reference to currently set year + * @param int reference to currently set month + * @param int reference to currently set day of month + * @param int reference to currently set hour + * @param int reference to currently set minute + * @param int reference to currently set second + * @return int operation result + */ +int Rtc::getAlarm(int &year, int &month, int &day, int &hour, int &minute, int &second) { + struct rtc_time alarm_time; + uint16_t mask = 0; + + int ret = rtc_alarm_get_time(rtc_dev, alarmId, &mask, &alarm_time); + if (ret < 0) { + return ret; + } + + year = alarm_time.tm_year + 1900; + month = alarm_time.tm_mon + 1; + day = alarm_time.tm_mday; + hour = alarm_time.tm_hour; + minute = alarm_time.tm_min; + second = alarm_time.tm_sec; + + return 0; +} + +/** + * @brief Rtc utility function + * + * Used to cancel a previously set alarm + * + * @return int operation result + */ +int Rtc::cancelAlarm() { + // Clear alarm by setting mask to 0 + struct rtc_time dummy = {}; + return rtc_alarm_set_time(rtc_dev, alarmId, 0, &dummy); +} + +/** + * @brief Rtc utility function + * + * Used to check if an alarm is currently set + * + * @return bool operation result, true for alarm pending, false otherwise + */ +bool Rtc::isAlarmPending() { + int ret = rtc_alarm_is_pending(rtc_dev, alarmId); + return ret > 0; +} + +/** + * @brief Rtc callback function + * + * This alarm callback wrapper is needed to make the connection between C-style low level driver + * function callbacks which need to be static and the objects derived from the RTC class; You do not + * need to call this directly in the app + * + * @param const struct device *dev is the hardware device (not used at this level) + * @param uint16_t id is an event/alarm identifier + * @param void *user_data is a void pointer the user can set when registering the callback + */ +void Rtc::alarmCallbackWrapper([[maybe_unused]] const struct device *dev, + [[maybe_unused]] uint16_t id, void *user_data) { + Rtc *self = static_cast(user_data); + if (self && self->userAlarmCallback) { + self->userAlarmCallback(self->userAlarmCallbackData); + } +} + +/** + * @brief Rtc utility function + * + * This function allows for updating the user callback and the message passed to it + * + * @param RtcUpdateCallback cb is the new callback which will be called in the app when the event + * fires later on + * @param void *user_data is a void pointer the user can set when registering the callback + */ +int Rtc::setUpdateCallback(RtcUpdateCallback cb, void *user_data) { + userUpdateCallback = cb; + userUpdateCallbackData = user_data; + + return rtc_update_set_callback(rtc_dev, Rtc::updateCallbackWrapper, this); +} + +/** + * @brief Rtc utility function + * + * This function is a wrapper which allows for connecting the low level driver and the registered + * callback with the instance of the object we use in the application sketch + * + * @param const struct device *dev is the hardware device (not used at this level) + * @param void *user_data is a void pointer the user can set when registering the callback + */ +void Rtc::updateCallbackWrapper([[maybe_unused]] const struct device *dev, void *user_data) { + Rtc *self = static_cast(user_data); + if (self && self->userUpdateCallback) { + self->userUpdateCallback(self->userUpdateCallbackData); + } +} + +/** + * @brief Sets the Rtc calibration value. + * + * This function writes a calibration value to the Rtc hardware to adjust + * timing accuracy. A positive or negative calibration factor may be applied, + * depending on whether the clock is running fast or slow. + * + * @param calibration The calibration adjustment value in parts per million (ppm). + * @return 0 if successful, or a negative error code on failure. + */ +int Rtc::setCalibration(int32_t calibration) { + return rtc_set_calibration(rtc_dev, calibration); +} + +/** + * @brief Retrieves the current Rtc calibration value. + * + * This function reads the current calibration adjustment applied to the Rtc. + * + * @param calibration Reference to an integer where the current calibration + * value (in parts per million) will be stored. + * @return 0 if successful, or a negative error code on failure. + */ +int Rtc::getCalibration(int32_t &calibration) { + return rtc_get_calibration(rtc_dev, &calibration); +} + +#else // For non-STM32 platforms (nordic), we must use the generic counter API to implement RTC + // functionality + +#if DT_NODE_EXISTS(DT_NODELABEL(rtc2)) +#define COUNTER_NODE DT_NODELABEL(rtc2) +#else +#warning "RTC node not found in devicetree" +#define COUNTER_NODE DT_INVALID_NODE +#endif +LOG_MODULE_REGISTER(Rtc); + +// Utility functions - local scope only +namespace { +static const int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static bool is_leap(int year) { + return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); +} +} // namespace + +/** + * @brief Static alarm handler for the RTC driver. + * + * This function acts as a static wrapper between the hardware interrupt and + * the user-defined callback. It retrieves the relevant `RTC` instance + * from the provided `user_data` and invokes the user’s callback function. + * + * @param dev Pointer to the RTC device structure (hardware driver). + * @param chan_id The alarm channel identifier. + * @param ticks The current tick count at the time of the alarm. + * @param user_data Pointer to user-defined data (the RTC instance). + */ +void Rtc::alarmHandler(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data) { + Rtc *rtc = static_cast(user_data); + if (rtc->user_callback) { + rtc->user_callback(dev, chan_id, ticks, rtc->user_data); + } else { + printk("Alarm triggered but no callback registered! Channel: %d, Ticks: %u\n", chan_id, + ticks); + } +} + +/** + * @brief Constructs an Rtc object. + * + * Initializes internal variables, sets default offsets, and retrieves + * the hardware RTC counter device. + */ +Rtc::Rtc() { + counter_dev = DEVICE_DT_GET_OR_NULL(COUNTER_NODE); + timeOffset = 0; + user_callback = nullptr; + user_data = nullptr; +} + +/** + * @brief Initializes the RTC hardware interface. + * + * This function checks if the RTC device is ready and starts the counter. + * + * @return true if the device is ready and successfully started, false otherwise. + */ +bool Rtc::begin() { + if (!counter_dev) { + printk("RTC counter device not found in device tree\n"); + return false; + } + if (!device_is_ready(counter_dev)) { + printk("RTC counter device not ready\n"); + return false; + } + + counter_start(counter_dev); + return true; +} + +/** + * @brief Sets the current RTC time. + * + * This function converts a date and time into epoch format and adjusts the + * internal time offset based on the current tick counter. + * + * @param year The current year (e.g., 2025). + * @param month The current month (1–12). + * @param day The day of the month (1–31). + * @param hour The hour (0–23). + * @param minute The minute (0–59). + * @param second The second (0–59). + * @return 0 if successful, or a negative error code if frequency or ticks are invalid. + */ +int Rtc::setTime(int year, int month, int day, int hour, int minute, int second) { + time_t target = datetimeToEpoch(year, month, day, hour, minute, second); + + uint32_t ticks; + counter_get_value(counter_dev, &ticks); + + uint32_t freq = counter_get_frequency(counter_dev); + if (freq == 0) { + printk("Counter frequency is zero\n"); + return -1; + } + + timeOffset = target - (ticks / freq); + return 0; +} + +/** + * @brief Retrieves the current RTC time. + * + * This function reads the current counter value, applies the time offset, + * and converts the epoch time to a human-readable date and time. + * + * @param year Reference to store the current year. + * @param month Reference to store the current month. + * @param day Reference to store the current day. + * @param hour Reference to store the current hour. + * @param minute Reference to store the current minute. + * @param second Reference to store the current second. + * @return 0 if successful. + */ +int Rtc::getTime(int &year, int &month, int &day, int &hour, int &minute, int &second) { + uint32_t ticks; + counter_get_value(counter_dev, &ticks); + + uint32_t freq = counter_get_frequency(counter_dev); + time_t now = timeOffset + (ticks / freq); + + epochToDatetime(now, year, month, day, hour, minute, second); + return 0; +} + +/** + * @brief Sets an RTC alarm. + * + * This function schedules an alarm for a specific date and time. When the + * target time is reached, the registered user callback is invoked. + * + * @param year Target alarm year. + * @param month Target alarm month. + * @param day Target alarm day. + * @param hour Target alarm hour. + * @param minute Target alarm minute. + * @param second Target alarm second. + * @param callback Function pointer to the user-defined callback. + * @param cb_user_data Pointer to user data passed to the callback when triggered. + * @return 0 if successful, or a negative error code if the target time is invalid. + */ +int Rtc::setAlarm(int year, int month, int day, int hour, int minute, int second, + void (*callback)(const struct device *dev, uint8_t chan_id, uint32_t ticks, + void *user_data), + void *cb_user_data) { + time_t target_epoch = datetimeToEpoch(year, month, day, hour, minute, second); + uint32_t freq = counter_get_frequency(counter_dev); + uint32_t current_ticks; + + if (counter_get_value(counter_dev, ¤t_ticks) != 0) { + printk("Failed to get current counter value\n"); + return -1; + } + + time_t current_epoch = timeOffset + (current_ticks / freq); + time_t delta_seconds = target_epoch - current_epoch; + + if (delta_seconds <= 0) { + return -1; + } + + uint32_t alarm_ticks = current_ticks + delta_seconds * freq; + + // Save user callback + user_callback = callback; + user_data = cb_user_data; + + alarm_cfg.flags = 0; // Absolute alarm + alarm_cfg.ticks = alarm_ticks; + alarm_cfg.callback = Rtc::alarmHandler; + alarm_cfg.user_data = this; + + int ret = counter_set_channel_alarm(counter_dev, 0, &alarm_cfg); + if (ret != 0) { + printk("Failed to set alarm: %d\n", ret); + user_callback = nullptr; + user_data = nullptr; + return ret; + } + + return 0; +} + +/** + * @brief Cancels the currently scheduled alarm. + * + * This function stops any active alarm and clears the registered callback + * and user data. + * @return 0 on success, negative error code otherwise. + */ +int Rtc::cancelAlarm() { + int ret = counter_cancel_channel_alarm(counter_dev, 0); + if (ret != 0) { + printk("Failed to cancel alarm: %d\n", ret); + } + user_callback = nullptr; + user_data = nullptr; + return ret; +} + +/** + * @brief Retrieves the currently configured alarm time. + * This function is not supported and will return -1 to indicate this. + * + * @return -1 to indicate not supported. + */ +int Rtc::getAlarm([[maybe_unused]] int &year, [[maybe_unused]] int &month, + [[maybe_unused]] int &day, [[maybe_unused]] int &hour, + [[maybe_unused]] int &minute, [[maybe_unused]] int &second) { + return -1; +} + +/** + * @brief Checks whether an alarm is currently pending. + * This function is not supported and will return false to indicate this. + * + * @return false to indicate not supported. + */ +bool Rtc::isAlarmPending() { + return false; +} + +/** + * @brief Registers an update callback function. + * This function is not supported and will return -1 to indicate this. + * + * @return -1 to indicate not supported. + */ +int Rtc::setUpdateCallback([[maybe_unused]] RtcUpdateCallback cb, + [[maybe_unused]] void *user_data) { + return -1; +} + +/** + * @brief Sets the Rtc calibration value. + * This function is not supported and will return -1 to indicate this. + * + * @return -1 to indicate not supported. + */ +int Rtc::setCalibration([[maybe_unused]] int32_t calibration) { + return -1; +} + +/** + * @brief Retrieves the current Rtc calibration value. + * This function is not supported and will return -1 to indicate this. + * + * @return -1 to indicate not supported. + */ +int Rtc::getCalibration([[maybe_unused]] int32_t &calibration) { + return -1; +} + +/** + * @brief Converts a date and time to Unix epoch seconds. + * + * This utility function calculates the number of seconds since + * January 1, 1970 (the Unix epoch) for the provided date and time. + * + * @param year Year value (e.g., 2025). + * @param month Month value (1–12). + * @param day Day value (1–31). + * @param hour Hour value (0–23). + * @param minute Minute value (0–59). + * @param second Second value (0–59). + * @return Corresponding epoch time in seconds. + */ +time_t Rtc::datetimeToEpoch(int year, int month, int day, int hour, int minute, int second) { + int y = year; + int m = month; + time_t days = 0; + + for (int i = 1970; i < y; i++) { + days += is_leap(i) ? 366 : 365; + } + + for (int i = 1; i < m; i++) { + days += days_in_month[i - 1]; + if (i == 2 && is_leap(y)) { + days += 1; + } + } + + days += (day - 1); + + return (((days * 24 + hour) * 60 + minute) * 60 + second); +} + +/** + * @brief Converts Unix epoch seconds to a date and time. + * + * This utility function breaks down a given epoch timestamp into a + * human-readable calendar date and time. + * + * @param t Epoch time in seconds. + * @param year Reference to store the year. + * @param month Reference to store the month. + * @param day Reference to store the day. + * @param hour Reference to store the hour. + * @param minute Reference to store the minute. + * @param second Reference to store the second. + */ +void Rtc::epochToDatetime(time_t t, int &year, int &month, int &day, int &hour, int &minute, + int &second) { + time_t seconds_in_day = t % 86400; + time_t days = t / 86400; + + hour = seconds_in_day / 3600; + minute = (seconds_in_day % 3600) / 60; + second = seconds_in_day % 60; + + year = 1970; + while (true) { + int days_in_year = is_leap(year) ? 366 : 365; + if (days >= days_in_year) { + days -= days_in_year; + year++; + } else { + break; + } + } + + int m = 0; + while (true) { + int dim = days_in_month[m]; + if (m == 1 && is_leap(year)) { + dim++; + } + + if (days >= dim) { + days -= dim; + m++; + } else { + break; + } + } + + month = m + 1; + day = days + 1; +} +#endif /* CONFIG_RTC_STM32*/ diff --git a/libraries/RTC/RTC.h b/libraries/RTC/RTC.h new file mode 100644 index 000000000..4d106bbab --- /dev/null +++ b/libraries/RTC/RTC.h @@ -0,0 +1,408 @@ +/** + * @file RTC.h + * @brief RTC library header for Zephyr-based Arduino boards. + * + * This class provides a unified interface for accessing and configuring + * real-time clock (RTC) peripherals across multiple Arduino platforms, + * such as the Portenta H7, GIGA R1, Opta, Nano 33 BLE, and Nicla Sense ME. + * + * It allows for reading and writing time, managing alarms, applying calibration, + * and registering update callbacks. + * + * Supported APIs adapt automatically to the underlying hardware. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +/** + * @typedef RtcAlarmCallback + * @brief Function pointer type for RTC alarm callbacks. + * + * @param user_data User-defined data passed to the callback when the alarm triggers. + */ +typedef void (*RtcAlarmCallback)(void *user_data); + +/** + * @typedef RtcUpdateCallback + * @brief Function pointer type for RTC update event callbacks. + * + * @param user_data User-defined data passed to the callback when the RTC updates. + */ +typedef void (*RtcUpdateCallback)(void *user_data); + +/** + * @class Rtc + * @brief Cross-platform RTC abstraction for Arduino boards running Zephyr. + * + * The Rtc class provides an object-oriented interface for interacting with + * the hardware real-time clock. It supports time management, alarm scheduling, + * calibration, and update event callbacks. + * + * Depending on the board, it interfaces with either the Zephyr RTC driver + * or the Zephyr counter driver for boards without a dedicated RTC peripheral. + * + */ +class Rtc { +public: + /** + * @brief Constructs a new Rtc object. + * + * Initializes internal pointers and prepares the instance + * for communication with the underlying RTC or counter driver. + */ + Rtc(); + + /** + * @brief Initializes the RTC hardware. + * + * Must be called before using other methods. + * + * @return true if the RTC device was successfully initialized, false otherwise. + */ + bool begin(); + + /** + * @brief Destroys the Rtc object. + */ + ~Rtc(); + + /** + * @brief Sets the current day of the month in the RTC. + * + * Updates only the day field of the current date and keeps other + * components (year, month, time) intact. + * + * @param day Day value to be set (1–31). + * @return true if the operation succeeds, false otherwise. + */ + bool setDayOfMonth(int day); + + /** + * @brief Sets the current month in the RTC. + * + * Updates only the month field while keeping all other time components + * unchanged. + * + * @param month Month value to be set (1–12). + * @return true if the operation succeeds, false otherwise. + */ + bool setMonthOfYear(int month); + + /** + * @brief Sets the current year in the RTC. + * + * Retrieves the current RTC time, updates only the year field, and writes the + * new time back to the RTC while preserving other date and time components. + * + * @param year Year value to be set (e.g., 2025). + * @return true if the operation succeeds, false otherwise. + */ + bool setYear(int year); + + /** + * @brief Sets the current hour in the RTC. + * + * Updates the hour component of the RTC without modifying date, minutes, or seconds. + * + * @param hour Hour value to be set (0–23). + * @return true if the operation succeeds, false otherwise. + */ + bool setHour(int hour); + + /** + * @brief Sets the current minute in the RTC. + * + * Updates the minute field of the current time, keeping all other + * components unchanged. + * + * @param minute Minute value to be set (0–59). + * @return true if the operation succeeds, false otherwise. + */ + bool setMinute(int minute); + + /** + * @brief Sets the current second in the RTC. + * + * Updates only the seconds field while preserving other components. + * + * @param second Second value to be set (0–59). + * @return true if the operation succeeds, false otherwise. + */ + bool setSecond(int second); + + /** + * @brief Retrieves the current day of the month from the RTC. + * + * Reads the RTC date and returns the day field. + * + * @return The current day of the month (1–31). + */ + int getDayOfMonth(); + + /** + * @brief Retrieves the current month from the RTC. + * + * Reads the current date and returns the month component. + * + * @return The current month as an integer (1–12). + */ + int getMonth(); + + /** + * @brief Retrieves the current year from the RTC. + * + * Reads the current date and time and returns the year component. + * + * @return The current year as an integer (e.g. 2025). + */ + int getYear(); + + /** + * @brief Retrieves the current hour from the RTC. + * + * Reads the RTC time and returns the hour component. + * + * @return The current hour (0–23). + */ + int getHour(); + + /** + * @brief Retrieves the current minute from the RTC. + * + * Reads the RTC time and returns the minute component. + * + * @return The current minute (0–59). + */ + int getMinutes(); + + /** + * @brief Retrieves the current second from the RTC. + * + * Reads the RTC time and returns the second component. + * + * @return The current second (0–59). + */ + int getSeconds(); + + /** + * @brief Sets the complete date and time. + * + * @param year Year (e.g., 2025) + * @param month Month (1–12) + * @param day Day of the month (1–31) + * @param hour Hour (0–23) + * @param minute Minute (0–59) + * @param second Second (0–59) + * @return 0 on success, negative error code otherwise. + */ + int setTime(int year, int month, int day, int hour, int minute, int second); + + /** + * @brief Retrieves the current date and time. + * + * @param year Reference to store the current year. + * @param month Reference to store the current month. + * @param day Reference to store the current day. + * @param hour Reference to store the current hour. + * @param minute Reference to store the current minute. + * @param second Reference to store the current second. + * @return 0 on success, negative error code otherwise. + */ + int getTime(int &year, int &month, int &day, int &hour, int &minute, int &second); + +#ifdef CONFIG_RTC_STM32 + /** + * @brief Schedules an alarm for a specific time. + * + * @param year Target year. + * @param month Target month. + * @param day Target day of the month. + * @param hour Target hour. + * @param minute Target minute. + * @param second Target second. + * @param cb Optional user callback triggered when the alarm fires. + * @param user_data Optional user-defined data passed to the callback. + * @return 0 on success, negative error code otherwise. + */ + int setAlarm(int year, int month, int day, int hour, int minute, int second, + RtcAlarmCallback cb = nullptr, void *user_data = nullptr); + + /** + * @brief Cancels the currently active alarm. + * @return 0 on success, negative error code otherwise. + */ + int cancelAlarm(); + +#else + /** + * @brief Sets an RTC alarm for boards using the Zephyr counter driver. + * + * @param year Target year. + * @param month Target month. + * @param day Target day. + * @param hour Target hour. + * @param minute Target minute. + * @param second Target second. + * @param callback Function pointer for the alarm event. + * @param cb_user_data Pointer to user data passed to the callback. + * @return 0 on success, negative error code otherwise. + */ + int setAlarm(int year, int month, int day, int hour, int minute, int second, + void (*callback)(const struct device *dev, uint8_t chan_id, uint32_t ticks, + void *user_data), + void *cb_user_data); + + /** + * @brief Cancels an active alarm. + * + * @return 0 on success, negative error code otherwise. + */ + int cancelAlarm(); + + /** + * @brief Retrieves the currently configured alarm time. + * + * @return -1 to indicate not supported. + */ + int getAlarm([[maybe_unused]] int &year, [[maybe_unused]] int &month, [[maybe_unused]] int &day, + [[maybe_unused]] int &hour, [[maybe_unused]] int &minute, + [[maybe_unused]] int &second); + + /** + * @brief Checks whether an alarm is currently pending. + * This function is not supported and will return -1 to indicate this. + * + * @return false to indicate not supported. + */ + bool isAlarmPending(); + + /** + * @brief Registers an update callback function. + * This function is not supported and will return -1 to indicate this. + * + * @return -1 to indicate not supported. + */ + int setUpdateCallback([[maybe_unused]] RtcUpdateCallback cb, [[maybe_unused]] void *user_data); + + /** + * @brief Sets the Rtc calibration value. + * This function is not supported and will return -1 to indicate this. + * + * @return -1 to indicate not supported. + */ + int setCalibration([[maybe_unused]] int32_t calibration); + + /** + * @brief Retrieves the current Rtc calibration value. + * This function is not supported and will return -1 to indicate this. + * + * @return -1 to indicate not supported. + */ + int getCalibration([[maybe_unused]] int32_t &calibration); +#endif + +#ifdef CONFIG_RTC_STM32 + /** + * @brief Retrieves the currently configured alarm time. + * + * @param year Reference to store the alarm year. + * @param month Reference to store the alarm month. + * @param day Reference to store the alarm day. + * @param hour Reference to store the alarm hour. + * @param minute Reference to store the alarm minute. + * @param second Reference to store the alarm second. + * @return 0 on success, negative error code otherwise. + */ + int getAlarm(int &year, int &month, int &day, int &hour, int &minute, int &second); + + /** + * @brief Checks whether an alarm is currently pending. + * + * @return true if an alarm is pending, false otherwise. + */ + bool isAlarmPending(); + + /** + * @brief Registers an update callback function. + * + * The callback is invoked when the RTC generates an update event. + * + * @param cb Function pointer for the update callback. + * @param user_data Optional user data passed to the callback. + * @return 0 on success, negative error code otherwise. + */ + int setUpdateCallback(RtcUpdateCallback cb, void *user_data); + + /** + * @brief Applies a calibration correction to the RTC. + * + * @param calibration Calibration offset in parts per million (ppm). + * @return 0 on success, negative error code otherwise. + */ + int setCalibration(int32_t calibration); + + /** + * @brief Reads the current RTC calibration setting. + * + * @param calibration Reference to store the current calibration value in ppm. + * @return 0 on success, negative error code otherwise. + */ + int getCalibration(int32_t &calibration); +#endif + +private: +#ifdef CONFIG_RTC_STM32 + /** @brief Pointer to the Zephyr RTC device. */ + const struct device *rtc_dev; + + /** @brief Internal static wrapper for alarm callbacks. */ + static void alarmCallbackWrapper([[maybe_unused]] const struct device *dev, + [[maybe_unused]] uint16_t id, void *user_data); + + /** @brief Internal static wrapper for update callbacks. */ + static void updateCallbackWrapper([[maybe_unused]] const struct device *dev, void *user_data); + + RtcAlarmCallback userAlarmCallback = nullptr; /**< User-registered alarm callback. */ + void *userAlarmCallbackData = nullptr; /**< User data for alarm callback. */ + + RtcUpdateCallback userUpdateCallback = nullptr; /**< User-registered update callback. */ + void *userUpdateCallbackData = nullptr; /**< User data for update callback. */ + + uint16_t alarmId = 0; /**< Default alarm identifier. */ + +#else + /** @brief Pointer to the Zephyr counter device used as RTC backend. */ + const struct device *counter_dev; + + /** @brief Time offset between the system counter and epoch time. */ + time_t timeOffset; + + /** @brief Counter driver alarm configuration. */ + struct counter_alarm_cfg alarm_cfg; + + /** @brief User-registered callback for counter-based alarms. */ + void (*user_callback)(const struct device *dev, uint8_t chan_id, uint32_t ticks, + void *user_data); + + /** @brief User data associated with the alarm callback. */ + void *user_data; + + /** @brief Static handler for counter alarm interrupts. */ + static void alarmHandler(const struct device *dev, uint8_t chan_id, uint32_t ticks, + void *user_data); + + /** @brief Converts a date and time to a Unix epoch timestamp. */ + time_t datetimeToEpoch(int year, int month, int day, int hour, int minute, int second); + + /** @brief Converts a Unix epoch timestamp to a date and time. */ + void epochToDatetime(time_t t, int &year, int &month, int &day, int &hour, int &minute, + int &second); +#endif +}; diff --git a/libraries/RTC/examples/AlarmRTC/AlarmRTC.ino b/libraries/RTC/examples/AlarmRTC/AlarmRTC.ino new file mode 100644 index 000000000..51e6957c3 --- /dev/null +++ b/libraries/RTC/examples/AlarmRTC/AlarmRTC.ino @@ -0,0 +1,76 @@ +/* +* This sketch sets an alarm 10 seconds in the future and handles it via a callback. +*/ + +#include "RTC.h" +#include + +Rtc rtc; + +char printBuffer[30]; // declare a buffer of large enough size for the message we want to display +int year, month, day, hour, minute, second; + +#if defined(ARDUINO_NICLA_SENSE_ME) || defined(ARDUINO_NANO33BLE) +void onAlarm(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data) { + char printBuffer[40]; + // Assuming user_data is a string or message you want to print + sprintf(printBuffer, "Alarm went off! Message: %s\n", (char *)user_data); + Serial.println(printBuffer); +} +#else +void onAlarm(void *user_data) { + char printBuffer[40]; + sprintf(printBuffer, "Alarm went off! Message: %s\n", (char *)user_data); + Serial.println(printBuffer); +} +#endif + +void setup() { + int ret = 0xDEADBEEFu; // Starting with a custom value for the return which will definitely lead to failure if not changed to zero (i.e. success) by the functions below + char printBuffer[60]; + Serial.begin(115200); + delay(1000); + + if (!rtc.begin()) { + Serial.println("RTC not ready\n"); + return; + } + + int year, month, day, hour, minute, second; + ret = rtc.getTime(year, month, day, hour, minute, second); + if(ret != 0) + { + rtc.setTime(2025, 10, 21, 12, 0, 0); + } + + sprintf(printBuffer, "Current Time: %04d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second); + Serial.println(printBuffer); + + // Set alarm 10 seconds into the future + second += 5; + // Correct for minute rollover if necessary + if (second >= 60) { + second -= 60; + minute += 1; + } + + // The method also allows for registering a function callback which will be called when the alarm sets off and a display message which will be shown in the console + ret = rtc.setAlarm(year, month, day, hour, minute, second, onAlarm, (void *)"Wake up!!!"); + if (ret == 0) { + sprintf(printBuffer, "Alarm set for: %02d:%02d:%02d\n", hour, minute, second); + Serial.println(printBuffer); + } else { + sprintf(printBuffer, "Failed to set alarm (%d)\n", ret); + Serial.println(printBuffer); + } +} + +void loop() { + char printBuffer[30]; // declare a buffer of large enough size for the message we want to display + int y, m, d, h, min, s; + rtc.getTime(y, m, d, h, min, s); + // Because the print() and println() functions do not support formatted output directly, we can use this trick to prepare a buffer with the string we want to show + sprintf(printBuffer, "Time is: %04d-%02d-%02d %02d:%02d:%02d", y, m, d, h, min, s); + Serial.println(printBuffer); + delay(1000); +} \ No newline at end of file diff --git a/libraries/RTC/examples/CalibrationRTC/CalibrationRTC.ino b/libraries/RTC/examples/CalibrationRTC/CalibrationRTC.ino new file mode 100644 index 000000000..5425ac7d7 --- /dev/null +++ b/libraries/RTC/examples/CalibrationRTC/CalibrationRTC.ino @@ -0,0 +1,37 @@ +#include "RTC.h" +#include + +Rtc rtc; + +void setup() { + char printBuffer[64]; + delay(1000); + Serial.begin(115200); + if (!rtc.begin()) { + printf("RTC not ready\n"); + return; + } + + int calib = 0; + if (rtc.getCalibration(calib) == 0) { + snprintf(printBuffer, sizeof(printBuffer), "Current calibration: %d\n", calib); + Serial.println(printBuffer); + } else { + Serial.println("Failed to get calibration"); + } + + // Apply a small positive calibration (e.g., +1) + // This value is hardware-dependent, in a real application you should check the microcontroller's datasheet for the correct amount. + int32_t new_calib = calib + 1; + + if (rtc.setCalibration(new_calib) == 0) { + snprintf(printBuffer, sizeof(printBuffer), "Calibration updated to: %d\n", new_calib); + Serial.println(printBuffer); + } else { + Serial.println("Failed to set calibration"); + } +} + +void loop() { + delay(5000); +} diff --git a/libraries/RTC/examples/SimpleRTC/SimpleRTC.ino b/libraries/RTC/examples/SimpleRTC/SimpleRTC.ino new file mode 100644 index 000000000..e0e3f921d --- /dev/null +++ b/libraries/RTC/examples/SimpleRTC/SimpleRTC.ino @@ -0,0 +1,23 @@ +#include "RTC.h" + +Rtc rtc; + +int year, month, day, hour, minute, second; +int previousSecond = 0; +char printBuffer[30]; // Allocate large enough buffer to hold the 28 characters of the output format "Time is: 2025-09-25 11:49:26" + +void setup() { + Serial.begin(115200); + if (!rtc.begin()) { + Serial.println("RTC not ready\n"); + return; + } + rtc.setTime(2025, 10, 21, 12, 0, 0); +} + +void loop() { + rtc.getTime(year, month, day, hour, minute, second); // Read back time from hardware + sprintf(printBuffer, "Time is: %04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second); + Serial.println(printBuffer); + delay(1000); +} \ No newline at end of file diff --git a/loader/prj.conf b/loader/prj.conf index dc40e9533..6ce5233b5 100644 --- a/loader/prj.conf +++ b/loader/prj.conf @@ -41,3 +41,5 @@ CONFIG_CBPRINTF_FP_SUPPORT=y CONFIG_MAIN_THREAD_PRIORITY=14 CONFIG_EVENTS=y + +CONFIG_RTC_STM32=y diff --git a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.conf b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.conf index e291cfe53..151457a61 100644 --- a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.conf +++ b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.conf @@ -31,6 +31,12 @@ CONFIG_DAC=y CONFIG_PWM=y CONFIG_I2C_TARGET=y +CONFIG_CLOCK_CONTROL=y +CONFIG_RTC=y +CONFIG_RTC_ALARM=y +CONFIG_RTC_UPDATE=y +CONFIG_RTC_CALIBRATION=y + CONFIG_ICACHE=y CONFIG_DCACHE=y CONFIG_CACHE_MANAGEMENT=y diff --git a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay index 109a4ed32..fa571c8ba 100644 --- a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay +++ b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay @@ -27,6 +27,13 @@ status = "okay"; }; +&rtc { + status = "okay"; + + clocks = <&rcc STM32_CLOCK(APB4, 16U)>, + <&rcc STM32_SRC_LSE RTC_SEL(0)>; +}; + &i2c4 { status = "okay"; gc2145: gc2145@3c { diff --git a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.conf b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.conf index ea265a899..97c30d5ca 100644 --- a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.conf +++ b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.conf @@ -29,6 +29,7 @@ CONFIG_LOG_DEFAULT_LEVEL=2 CONFIG_ADC=y CONFIG_PWM=y +CONFIG_COUNTER=y CONFIG_LLEXT_STORAGE_WRITABLE=n CONFIG_HEAP_MEM_POOL_SIZE=16384 diff --git a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay index beb714835..cccb45f5a 100644 --- a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay +++ b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay @@ -284,3 +284,8 @@ clock-frequency = ; }; +&rtc2 { + status = "okay"; + clock-frequency = <32768>; + prescaler = <1>; // Optional: sets the RTC tick to ~30.5 µs +}; diff --git a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_sense.overlay b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_sense.overlay new file mode 100644 index 000000000..898644154 --- /dev/null +++ b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_sense.overlay @@ -0,0 +1,203 @@ +/ { + zephyr,user { + digital-pin-gpios = <&arduino_nano_header 0 0>, + <&arduino_nano_header 1 0>, + <&arduino_nano_header 2 0>, + <&arduino_nano_header 3 0>, + <&arduino_nano_header 4 0>, + <&arduino_nano_header 5 0>, + <&arduino_nano_header 6 0>, + <&arduino_nano_header 7 0>, + <&arduino_nano_header 8 0>, + <&arduino_nano_header 9 0>, + <&arduino_nano_header 10 0>, + <&arduino_nano_header 11 0>, + <&arduino_nano_header 12 0>, + <&arduino_nano_header 13 0>, + <&arduino_nano_header 14 0>, /* D14 / A0 */ + <&arduino_nano_header 15 0>, + <&arduino_nano_header 16 0>, + <&arduino_nano_header 17 0>, + <&arduino_nano_header 18 0>, /* D18 / A4 / I2C-SDA */ + <&arduino_nano_header 19 0>, /* D19 / A5 / I2C-SCL */ + <&arduino_nano_header 20 0>, + <&arduino_nano_header 21 0>; + + pwm-pin-gpios = <&arduino_nano_header 3 0>, + <&arduino_nano_header 5 0>, + <&arduino_nano_header 6 0>, + <&arduino_nano_header 13 0>, + <&arduino_nano_header 9 0>, + <&arduino_nano_header 10 0>, + <&arduino_nano_header 11 0>; + + adc-pin-gpios = <&arduino_nano_header 14 0>, + <&arduino_nano_header 15 0>, + <&arduino_nano_header 16 0>, + <&arduino_nano_header 17 0>, + <&arduino_nano_header 18 0>, + <&arduino_nano_header 19 0>, + <&arduino_nano_header 20 0>, + <&arduino_nano_header 21 0>; + + builtin-led-gpios = <&arduino_nano_header 13 0>; + + pwms = <&pwm1 1 255 PWM_POLARITY_NORMAL>, + <&pwm1 2 255 PWM_POLARITY_NORMAL>, + <&pwm1 3 255 PWM_POLARITY_NORMAL>, + <&pwm2 0 255 PWM_POLARITY_NORMAL>, + <&pwm2 1 255 PWM_POLARITY_NORMAL>, + <&pwm2 2 255 PWM_POLARITY_NORMAL>, + <&pwm2 3 255 PWM_POLARITY_NORMAL>; + + io-channels = <&adc 2>, + <&adc 3>, + <&adc 6>, + <&adc 5>, + <&adc 7>, + <&adc 0>, + <&adc 4>, + <&adc 1>; + + serials = <&uart0>; + i2cs = <&arduino_nano_i2c>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P0.02 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P0.03 */ + zephyr,resolution = <10>; + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P0.04 */ + zephyr,resolution = <10>; + }; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P0.05 */ + zephyr,resolution = <10>; + }; + + channel@4 { + reg = <4>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P0.28 */ + zephyr,resolution = <10>; + }; + + channel@5 { + reg = <5>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P0.29 */ + zephyr,resolution = <10>; + }; + + channel@6 { + reg = <6>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P0.30 */ + zephyr,resolution = <10>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P0.31 */ + zephyr,resolution = <10>; + }; +}; + +&pinctrl { + pwm1_default: pwm1_default { + group1 { + psels = , /* keep original config */ + , + , + ; + nordic,invert; + }; + }; + + pwm1_sleep: pwm1_sleep { + group1 { + psels = , /* keep original config */ + , + , + ; + low-power-enable; + }; + }; + + pwm2_default: pwm2_default { + group1 { + psels = , /* keep original config */ + , + , + ; + nordic,invert; + }; + }; + + pwm2_sleep: pwm2_sleep { + group1 { + psels = , /* keep original config */ + , + , + ; + low-power-enable; + }; + }; +}; + +&pwm1 { + status = "okay"; + pinctrl-0 = <&pwm1_default>; + pinctrl-1 = <&pwm1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&pwm2 { + status = "okay"; + pinctrl-0 = <&pwm2_default>; + pinctrl-1 = <&pwm2_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&rtc2 { + status = "okay"; + prescaler = <1>; // Optional: sets the RTC tick to ~30.5 µs +}; diff --git a/variants/arduino_nano_matter_mgm240sd22vna/skip_these_examples.txt b/variants/arduino_nano_matter_mgm240sd22vna/skip_these_examples.txt index c5875aa35..a455b8507 100644 --- a/variants/arduino_nano_matter_mgm240sd22vna/skip_these_examples.txt +++ b/variants/arduino_nano_matter_mgm240sd22vna/skip_these_examples.txt @@ -17,3 +17,4 @@ libraries/Ethernet libraries/Storage libraries/WiFi libraries/Zephyr_SDRAM +libraries/RTC diff --git a/variants/arduino_nicla_sense_me_nrf52832/arduino_nicla_sense_me_nrf52832.conf b/variants/arduino_nicla_sense_me_nrf52832/arduino_nicla_sense_me_nrf52832.conf index 666eaec57..78cecfc3b 100644 --- a/variants/arduino_nicla_sense_me_nrf52832/arduino_nicla_sense_me_nrf52832.conf +++ b/variants/arduino_nicla_sense_me_nrf52832/arduino_nicla_sense_me_nrf52832.conf @@ -20,9 +20,12 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 CONFIG_ADC=y #CONFIG_PWM=y +CONFIG_COUNTER=y CONFIG_LLEXT_STORAGE_WRITABLE=n CONFIG_HEAP_MEM_POOL_SIZE=8192 CONFIG_LLEXT_HEAP_SIZE=15 CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=-1 + +CONFIG_BT_RX_STACK_SIZE=1024 +CONFIG_BT_HCI_TX_STACK_SIZE=1024 diff --git a/variants/arduino_nicla_sense_me_nrf52832/arduino_nicla_sense_me_nrf52832.overlay b/variants/arduino_nicla_sense_me_nrf52832/arduino_nicla_sense_me_nrf52832.overlay index 6686c5075..699ad10d4 100644 --- a/variants/arduino_nicla_sense_me_nrf52832/arduino_nicla_sense_me_nrf52832.overlay +++ b/variants/arduino_nicla_sense_me_nrf52832/arduino_nicla_sense_me_nrf52832.overlay @@ -17,6 +17,12 @@ }; }; +&rtc2 { + status = "okay"; + clock-frequency = <32768>; + prescaler = <1>; // Optional: sets the RTC tick to ~30.5 µs +}; + / { zephyr,user { digital-pin-gpios = <&gpio0 10 0>, // 0: GPIO3 diff --git a/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.conf b/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.conf index 0f28cc3de..26a48ecf8 100644 --- a/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.conf +++ b/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.conf @@ -29,6 +29,12 @@ CONFIG_ADC=y CONFIG_DAC=n CONFIG_PWM=n +CONFIG_CLOCK_CONTROL=y +CONFIG_RTC=y +CONFIG_RTC_ALARM=y +CONFIG_RTC_UPDATE=y +CONFIG_RTC_CALIBRATION=y + CONFIG_ICACHE=y CONFIG_DCACHE=y CONFIG_CACHE_MANAGEMENT=y diff --git a/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.overlay b/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.overlay index 2b8cef4cf..17f8b59fb 100644 --- a/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.overlay +++ b/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.overlay @@ -21,6 +21,13 @@ status = "okay"; }; +&rtc { + status = "okay"; + + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; +}; + &i2c1 { status = "okay"; pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb7>; diff --git a/variants/arduino_portenta_c33_r7fa6m5bh3cfc/skip_these_examples.txt b/variants/arduino_portenta_c33_r7fa6m5bh3cfc/skip_these_examples.txt index 65c3dae24..f4d9a1f95 100644 --- a/variants/arduino_portenta_c33_r7fa6m5bh3cfc/skip_these_examples.txt +++ b/variants/arduino_portenta_c33_r7fa6m5bh3cfc/skip_these_examples.txt @@ -9,3 +9,4 @@ # relative to the root of the repository. libraries/Camera +libraries/RTC diff --git a/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.conf b/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.conf index f657c10ed..a68f4dda1 100644 --- a/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.conf +++ b/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.conf @@ -51,6 +51,13 @@ CONFIG_WIFI=y CONFIG_AIROC_WIFI_CUSTOM=y CONFIG_STM32_MEMMAP=y +CONFIG_CLOCK_CONTROL=y +CONFIG_RTC=y +CONFIG_RTC_ALARM=y +CONFIG_RTC_UPDATE=y +CONFIG_RTC_CALIBRATION=y + +CONFIG_NET_CORE_LOG_LEVEL_DBG=y CONFIG_NETWORKING=y CONFIG_NET_IPV6=n diff --git a/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay b/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay index 75782c44f..0aa844139 100644 --- a/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay +++ b/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay @@ -14,6 +14,13 @@ status = "okay"; }; +&rtc { + status = "okay"; + + clocks = <&rcc STM32_CLOCK(APB4, 16U)>, + <&rcc STM32_SRC_LSI RTC_SEL(2)>; +}; + &i2c3 { status = "okay"; diff --git a/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.conf b/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.conf index 9beb77ffb..b205b134f 100644 --- a/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.conf +++ b/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.conf @@ -24,6 +24,10 @@ CONFIG_ARM_MPU=n CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_RTC=y +CONFIG_RTC_ALARM=y +CONFIG_RTC_UPDATE=y +CONFIG_RTC_CALIBRATION=y CONFIG_COUNTER=y CONFIG_DEBUG_THREAD_INFO=y diff --git a/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay b/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay index 98d9552b9..dc745ed7a 100644 --- a/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay +++ b/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay @@ -184,6 +184,12 @@ }; }; +&rtc { + status = "okay"; + clocks = <&rcc STM32_CLOCK(APB3, 21)>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; +}; + / { zephyr,user { digital-pin-gpios = <&gpiob 7 GPIO_ACTIVE_HIGH>, /* D0 - PB7 */