This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit ebe4ab889462f0ea60d0915e8d2f8e9242287caa Author: Gustavo Henrique Nihei <gustavo.ni...@espressif.com> AuthorDate: Wed Apr 5 16:49:06 2023 -0300 risc-v/espressif: Add support for RTC subsystem Signed-off-by: Gustavo Henrique Nihei <gustavo.ni...@espressif.com> --- arch/risc-v/src/espressif/Kconfig | 4 +- arch/risc-v/src/espressif/Make.defs | 4 + arch/risc-v/src/espressif/esp_rtc.c | 876 +++++++++++++++++++++ arch/risc-v/src/espressif/esp_rtc.h | 51 ++ arch/risc-v/src/espressif/hal_esp32c6.mk | 1 + .../esp32c3-generic/configs/rtc/defconfig | 51 ++ .../esp32c3-generic/src/esp32c3_bringup.c | 14 + .../esp32c6-generic/configs/rtc/defconfig | 52 ++ .../esp32c6-generic/src/esp32c6_bringup.c | 14 + .../esp32h2-generic/configs/rtc/defconfig | 52 ++ .../esp32h2-generic/src/esp32h2_bringup.c | 14 + 11 files changed, 1131 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/espressif/Kconfig b/arch/risc-v/src/espressif/Kconfig index 252e812492..c431196fcd 100644 --- a/arch/risc-v/src/espressif/Kconfig +++ b/arch/risc-v/src/espressif/Kconfig @@ -217,8 +217,8 @@ config ESPRESSIF_UART1 select ARCH_HAVE_SERIAL_TERMIOS config ESPRESSIF_HR_TIMER - bool "High-Resolution Timer" - default n + bool + default y if RTC_DRIVER ---help--- A high-resolution hardware timer for supporting the management of kernel events. diff --git a/arch/risc-v/src/espressif/Make.defs b/arch/risc-v/src/espressif/Make.defs index ff077a16bf..74d0785583 100644 --- a/arch/risc-v/src/espressif/Make.defs +++ b/arch/risc-v/src/espressif/Make.defs @@ -60,6 +60,10 @@ ifeq ($(CONFIG_ONESHOT),y) CHIP_CSRCS += esp_oneshot.c endif +ifeq ($(CONFIG_RTC),y) +CHIP_CSRCS += esp_rtc.c +endif + ifeq ($(CONFIG_ESPRESSIF_HR_TIMER),y) CHIP_CSRCS += esp_hr_timer.c endif diff --git a/arch/risc-v/src/espressif/esp_rtc.c b/arch/risc-v/src/espressif/esp_rtc.c new file mode 100644 index 0000000000..57a2b06c5d --- /dev/null +++ b/arch/risc-v/src/espressif/esp_rtc.c @@ -0,0 +1,876 @@ +/**************************************************************************** + * arch/risc-v/src/espressif/esp_rtc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <assert.h> +#include <debug.h> +#include <errno.h> +#include <stdbool.h> +#include <string.h> +#include <sys/types.h> + +#include <nuttx/arch.h> +#include <nuttx/spinlock.h> +#include <nuttx/timers/rtc.h> + +#include "clock/clock.h" + +#include "esp_hr_timer.h" +#include "esp_rtc.h" +#include "riscv_internal.h" + +#include "esp_attr.h" +#include "soc/rtc.h" + +/* Chip-dependent headers from esp-hal-3rdparty */ + +#ifdef CONFIG_ESPRESSIF_ESP32C3 +#include "esp32c3/rtc.h" +#include "esp32c3/rom/rtc.h" +#elif defined(CONFIG_ESPRESSIF_ESP32C6) +#include "esp32c6/rtc.h" +#include "esp32c6/rom/rtc.h" +#elif defined(CONFIG_ESPRESSIF_ESP32H2) +#include "esp32h2/rtc.h" +#include "esp32h2/rom/rtc.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The magic data for the struct esp_rtc_backup_s that is in RTC slow + * memory. + */ + +#define MAGIC_RTC_SAVE (UINT64_C(0x11223344556677)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_RTC_DRIVER + +#ifdef CONFIG_RTC_ALARM +struct alm_cbinfo_s +{ + struct esp_hr_timer_s *alarm_hdl; /* Timer id point to here */ + rtc_alarm_callback_t ac_cb; /* Client callback function */ + volatile void *ac_arg; /* Argument to pass with the callback function */ + uint64_t deadline_us; + uint8_t index; +}; +#endif /* CONFIG_RTC_ALARM */ + +/* This is the private type for the RTC state. It must be cast compatible + * with struct rtc_lowerhalf_s. + */ + +struct esp_rtc_lowerhalf_s +{ + /* This is the contained reference to the read-only, lower-half + * operations vtable (which may lie in FLASH or ROM) + */ + + const struct rtc_ops_s *ops; +#ifdef CONFIG_RTC_ALARM + /* Alarm callback information */ + + struct alm_cbinfo_s alarmcb[CONFIG_RTC_NALARMS]; +#endif /* CONFIG_RTC_ALARM */ +}; + +#endif/* CONFIG_RTC_DRIVER */ + +struct esp_rtc_backup_s +{ + uint64_t magic; + int64_t offset; /* Offset time from RTC HW value */ + int64_t reserved0; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Prototypes for static methods in struct rtc_ops_s */ + +#ifdef CONFIG_RTC_DRIVER +static int esp_rtc_rdtime(struct rtc_lowerhalf_s *lower, + struct rtc_time *rtctime); +static int esp_rtc_settime(struct rtc_lowerhalf_s *lower, + const struct rtc_time *rtctime); +static bool esp_rtc_havesettime(struct rtc_lowerhalf_s *lower); + +#ifdef CONFIG_RTC_ALARM +static void IRAM_ATTR rtc_hr_timer_cb(void *arg); +static int esp_rtc_setalarm(struct rtc_lowerhalf_s *lower, + const struct lower_setalarm_s *alarminfo); +static int esp_rtc_setrelative(struct rtc_lowerhalf_s *lower, + const struct lower_setrelative_s *alarminfo); +static int esp_rtc_cancelalarm(struct rtc_lowerhalf_s *lower, + int alarmid); +static int esp_rtc_rdalarm(struct rtc_lowerhalf_s *lower, + struct lower_rdalarm_s *alarminfo); +#endif /* CONFIG_RTC_ALARM */ +#endif /* CONFIG_RTC_DRIVER */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_RTC_DRIVER +/* RTC driver operations */ + +static const struct rtc_ops_s g_rtc_ops = +{ + .rdtime = esp_rtc_rdtime, + .settime = esp_rtc_settime, + .havesettime = esp_rtc_havesettime, +#ifdef CONFIG_RTC_ALARM + .setalarm = esp_rtc_setalarm, + .setrelative = esp_rtc_setrelative, + .cancelalarm = esp_rtc_cancelalarm, + .rdalarm = esp_rtc_rdalarm, +#endif /* CONFIG_RTC_ALARM */ +}; + +/* RTC device state */ + +static struct esp_rtc_lowerhalf_s g_rtc_lowerhalf = +{ + .ops = &g_rtc_ops +}; + +/* Flag for tracking HR Timer enable status */ + +static bool g_hr_timer_enabled = false; + +#endif /* CONFIG_RTC_DRIVER */ + +/* Saved data for persistent RTC time */ + +static RTC_DATA_ATTR struct esp_rtc_backup_s g_rtc_saved_data; +static struct esp_rtc_backup_s *g_rtc_save; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile bool g_rtc_enabled = false; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_rtc_set_boot_time + * + * Description: + * Set time to RTC register to replace the original boot time. + * + * Input Parameters: + * time_us - set time in microseconds. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void IRAM_ATTR esp_rtc_set_boot_time(uint64_t time_us) +{ + putreg32((uint32_t)(time_us & UINT32_MAX), RTC_BOOT_TIME_LOW_REG); + putreg32((uint32_t)(time_us >> 32), RTC_BOOT_TIME_HIGH_REG); +} + +/**************************************************************************** + * Name: esp_rtc_get_boot_time + * + * Description: + * Get time of RTC register to indicate the original boot time. + * + * Input Parameters: + * None. + * + * Returned Value: + * Boot time in microseconds. + * + ****************************************************************************/ + +static uint64_t IRAM_ATTR esp_rtc_get_boot_time(void) +{ + return ((uint64_t)getreg32(RTC_BOOT_TIME_LOW_REG)) + + (((uint64_t)getreg32(RTC_BOOT_TIME_HIGH_REG)) << 32); +} + +/**************************************************************************** + * Name: rtc_hr_timer_cb + * + * Description: + * Callback to be called upon HR-Timer expiration. + * + * Input Parameters: + * arg - Information about the HR-Timer configuration. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#if defined(CONFIG_RTC_DRIVER) && defined(CONFIG_RTC_ALARM) +static void IRAM_ATTR rtc_hr_timer_cb(void *arg) +{ + struct alm_cbinfo_s *cbinfo = (struct alm_cbinfo_s *)arg; + rtc_alarm_callback_t cb; + void *cb_arg; + int alminfo_id; + + DEBUGASSERT(cbinfo != NULL); + + alminfo_id = cbinfo->index; + + if (cbinfo->ac_cb != NULL) + { + /* Alarm callback */ + + cb = cbinfo->ac_cb; + cb_arg = (void *)cbinfo->ac_arg; + cbinfo->ac_cb = NULL; + cbinfo->ac_arg = NULL; + cbinfo->deadline_us = 0; + cb(cb_arg, alminfo_id); + } +} +#endif /* CONFIG_RTC_DRIVER */ + +/**************************************************************************** + * Name: esp_rtc_rdtime + * + * Description: + * Return the current RTC time. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure. + * rcttime - The location in which to return the current RTC time. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_DRIVER + +#ifdef CONFIG_RTC_HIRES +static int esp_rtc_rdtime(struct rtc_lowerhalf_s *lower, + struct rtc_time *rtctime) +{ + struct timespec ts; + int ret; + + /* Get the higher resolution time */ + + ret = up_rtc_gettime(&ts); + if (ret < 0) + { + goto errout; + } + + /* Convert the one second epoch time to a struct tmThis operation + * depends on the fact that struct rtc_time and struct tm are cast + * compatible. + */ + + if (!gmtime_r(&ts.tv_sec, (struct tm *)rtctime)) + { + ret = -get_errno(); + goto errout; + } + + return OK; + +errout: + rtcerr("Failed to get RTC time: %d\n", ret); + return ret; +} + +#else /* !CONFIG_RTC_HIRES */ + +static int esp_rtc_rdtime(struct rtc_lowerhalf_s *lower, + struct rtc_time *rtctime) +{ + time_t timer; + + /* The resolution of time is only 1 second */ + + timer = up_rtc_time(); + + /* Convert the one second epoch time to a struct tm */ + + if (gmtime_r(&timer, (struct tm *)rtctime) == 0) + { + int errcode = get_errno(); + DEBUGASSERT(errcode > 0); + + rtcerr("gmtime_r failed: %d\n", errcode); + return -errcode; + } + + return OK; +} +#endif /* CONFIG_RTC_HIRES */ + +#endif /* CONFIG_RTC_DRIVER */ + +/**************************************************************************** + * Name: esp_rtc_settime + * + * Description: + * Implement the settime() method of the RTC driver interface. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure. + * rcttime - The new time to set. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_DRIVER +static int esp_rtc_settime(struct rtc_lowerhalf_s *lower, + const struct rtc_time *rtctime) +{ + struct timespec ts; + + /* Convert the struct rtc_time to a time_t. Here we assume that struct + * rtc_time is cast compatible with struct tm. + */ + + ts.tv_sec = mktime((struct tm *)rtctime); + ts.tv_nsec = 0; + + /* Now set the time (with a accuracy of seconds) */ + + return up_rtc_settime(&ts); +} +#endif /* CONFIG_RTC_DRIVER */ + +/**************************************************************************** + * Name: esp_rtc_havesettime + * + * Description: + * Implement the havesettime() method of the RTC driver interface. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure. + * + * Returned Value: + * True if RTC date-time have been previously set, false otherwise. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_DRIVER +static bool esp_rtc_havesettime(struct rtc_lowerhalf_s *lower) +{ + return esp_rtc_get_boot_time() != 0; +} +#endif /* CONFIG_RTC_DRIVER */ + +/**************************************************************************** + * Name: esp_rtc_setalarm + * + * Description: + * Set a new alarm. This function implements the setalarm() method of the + * RTC driver interface. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure. + * alarminfo - Provided information needed to set the alarm. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#if defined(CONFIG_RTC_DRIVER) && defined(CONFIG_RTC_ALARM) +static int esp_rtc_setalarm(struct rtc_lowerhalf_s *lower, + const struct lower_setalarm_s *alarminfo) +{ + struct esp_rtc_lowerhalf_s *priv = (struct esp_rtc_lowerhalf_s *)lower; + struct alm_cbinfo_s *cbinfo; + uint64_t timeout; + irqstate_t flags; + int id; + + DEBUGASSERT(priv != NULL); + DEBUGASSERT(alarminfo != NULL); + + timeout = mktime((struct tm *)&alarminfo->time); + + /* Set the alarm in RT-Timer */ + + id = alarminfo->id; + cbinfo = &priv->alarmcb[id]; + + if (cbinfo->ac_cb != NULL) + { + return -EBUSY; + } + + /* Create the RT-Timer alarm */ + + flags = spin_lock_irqsave(NULL); + + if (cbinfo->alarm_hdl == NULL) + { + struct esp_hr_timer_args_s hr_timer_args; + int ret; + + cbinfo->index = id; + hr_timer_args.arg = cbinfo; + hr_timer_args.callback = rtc_hr_timer_cb; + + ret = esp_hr_timer_create(&hr_timer_args, &cbinfo->alarm_hdl); + if (ret < 0) + { + rtcerr("Failed to create HR Timer=%d\n", ret); + spin_unlock_irqrestore(NULL, flags); + return ret; + } + } + + cbinfo->ac_cb = alarminfo->cb; + cbinfo->ac_arg = alarminfo->priv; + cbinfo->deadline_us = timeout * USEC_PER_SEC; + + rtcinfo("Starting alarm ID %d\n", id); + + esp_hr_timer_start(cbinfo->alarm_hdl, cbinfo->deadline_us, false); + + spin_unlock_irqrestore(NULL, flags); + + return OK; +} +#endif /* CONFIG_RTC_DRIVER && CONFIG_RTC_ALARM */ + +/**************************************************************************** + * Name: esp_rtc_setrelative + * + * Description: + * Set a new alarm relative to the current time. This function implements + * the setrelative() method of the RTC driver interface. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure. + * alarminfo - Provided information needed to set the alarm. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#if defined(CONFIG_RTC_DRIVER) && defined(CONFIG_RTC_ALARM) +static int esp_rtc_setrelative(struct rtc_lowerhalf_s *lower, + const struct lower_setrelative_s *alarminfo) +{ + struct lower_setalarm_s setalarm; + time_t seconds; + int ret = -EINVAL; + irqstate_t flags; + + DEBUGASSERT(lower != NULL && alarminfo != NULL); + + if (alarminfo->reltime > 0) + { + flags = spin_lock_irqsave(NULL); + + seconds = alarminfo->reltime; + gmtime_r(&seconds, (struct tm *)&setalarm.time); + + /* The set the alarm using this absolute time */ + + setalarm.id = alarminfo->id; + setalarm.cb = alarminfo->cb; + setalarm.priv = alarminfo->priv; + ret = esp_rtc_setalarm(lower, &setalarm); + + spin_unlock_irqrestore(NULL, flags); + } + + return ret; +} +#endif /* CONFIG_RTC_DRIVER && CONFIG_RTC_ALARM */ + +/**************************************************************************** + * Name: esp_rtc_cancelalarm + * + * Description: + * Cancel the current alarm. This function implements the cancelalarm() + * method of the RTC driver interface. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure. + * alarmid - ID of the alarm to be cancelled. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#if defined(CONFIG_RTC_DRIVER) && defined(CONFIG_RTC_ALARM) +static int esp_rtc_cancelalarm(struct rtc_lowerhalf_s *lower, int alarmid) +{ + struct esp_rtc_lowerhalf_s *priv; + struct alm_cbinfo_s *cbinfo; + irqstate_t flags; + + DEBUGASSERT(lower != NULL); + + priv = (struct esp_rtc_lowerhalf_s *)lower; + + /* Set the alarm in hardware and enable interrupts */ + + cbinfo = &priv->alarmcb[alarmid]; + + if (cbinfo->ac_cb == NULL) + { + return -ENODATA; + } + + flags = spin_lock_irqsave(NULL); + + /* Stop and delete the alarm */ + + rtcinfo("Cancelling alarm ID %d\n", alarmid); + + esp_hr_timer_stop(cbinfo->alarm_hdl); + esp_hr_timer_delete(cbinfo->alarm_hdl); + + cbinfo->ac_cb = NULL; + cbinfo->deadline_us = 0; + cbinfo->alarm_hdl = NULL; + + spin_unlock_irqrestore(NULL, flags); + + return OK; +} +#endif /* CONFIG_RTC_DRIVER && CONFIG_RTC_ALARM */ + +/**************************************************************************** + * Name: esp_rtc_rdalarm + * + * Description: + * Query the RTC alarm. + * + * Input Parameters: + * lower - A reference to RTC lower half driver state structure. + * alarminfo - Provided information needed to query the alarm. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#if defined(CONFIG_RTC_DRIVER) && defined(CONFIG_RTC_ALARM) +static int esp_rtc_rdalarm(struct rtc_lowerhalf_s *lower, + struct lower_rdalarm_s *alarminfo) +{ + struct esp_rtc_lowerhalf_s *priv; + struct timespec ts; + struct alm_cbinfo_s *cbinfo; + irqstate_t flags; + + DEBUGASSERT(lower != NULL); + DEBUGASSERT(alarminfo != NULL); + DEBUGASSERT(alarminfo->time != NULL); + + priv = (struct esp_rtc_lowerhalf_s *)lower; + + flags = spin_lock_irqsave(NULL); + + /* Get the alarm according to the alarm ID */ + + cbinfo = &priv->alarmcb[alarminfo->id]; + + ts.tv_sec = (esp_hr_timer_time_us() + g_rtc_save->offset + + cbinfo->deadline_us) / USEC_PER_SEC; + ts.tv_nsec = ((esp_hr_timer_time_us() + g_rtc_save->offset + + cbinfo->deadline_us) % USEC_PER_SEC) * NSEC_PER_USEC; + + localtime_r((const time_t *)&ts.tv_sec, + (struct tm *)alarminfo->time); + + spin_unlock_irqrestore(NULL, flags); + + return OK; +} +#endif /* CONFIG_RTC_DRIVER && CONFIG_RTC_ALARM */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_rtc_time + * + * Description: + * Get the current time in seconds. This is similar to the standard time() + * function. This interface is only required if the low-resolution + * RTC/counter hardware implementation is selected. It is only used by the + * RTOS during initialization to set up the system time when CONFIG_RTC is + * set but CONFIG_RTC_HIRES is not set. + * + * Input Parameters: + * None. + * + * Returned Value: + * Current time in seconds. + * + ****************************************************************************/ + +#ifndef CONFIG_RTC_HIRES +time_t up_rtc_time(void) +{ + uint64_t time_us; + irqstate_t flags; + + flags = spin_lock_irqsave(NULL); + +#ifdef CONFIG_RTC_DRIVER + /* NOTE: HR-Timer starts to work after the board is initialized, and the + * RTC controller starts works after up_rtc_initialize is initialized. + * Since the system clock starts to work before the board is initialized, + * if CONFIG_RTC is enabled, the system time must be matched by the time + * of the RTC controller (up_rtc_initialize has already been initialized, + * and HR-Timer cannot work). + */ + + /* Determine if HR-Timer is started */ + + if (g_hr_timer_enabled) + { + /* Get the time from HR-Timer, the time interval between RTC + * controller and HR-Timer is stored in g_rtc_save->offset. + */ + + time_us = esp_hr_timer_time_us() + g_rtc_save->offset + + esp_rtc_get_boot_time(); + } + else +#endif + { + /* Get the time from RTC controller */ + + time_us = esp_rtc_get_time_us() + esp_rtc_get_boot_time(); + } + + spin_unlock_irqrestore(NULL, flags); + + return (time_t)(time_us / USEC_PER_SEC); +} +#endif /* !CONFIG_RTC_HIRES */ + +/**************************************************************************** + * Name: up_rtc_gettime + * + * Description: + * Get the current time from the high resolution RTC time or HR-Timer. This + * interface is only supported by the high-resolution RTC/counter hardware + * implementation. It is used to replace the system timer. + * + * Input Parameters: + * tp - The location to return the RTC time or HR-Timer value. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_HIRES +int up_rtc_gettime(struct timespec *tp) +{ + irqstate_t flags; + uint64_t time_us; + + flags = spin_lock_irqsave(NULL); + +#ifdef CONFIG_RTC_DRIVER + if (g_hr_timer_enabled) + { + time_us = esp_hr_timer_time_us() + g_rtc_save->offset + + esp_rtc_get_boot_time(); + } + else +#endif + { + time_us = esp_rtc_get_time_us() + esp_rtc_get_boot_time(); + } + + tp->tv_sec = time_us / USEC_PER_SEC; + tp->tv_nsec = (time_us % USEC_PER_SEC) * NSEC_PER_USEC; + + spin_unlock_irqrestore(NULL, flags); + + return OK; +} +#endif /* CONFIG_RTC_HIRES */ + +/**************************************************************************** + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be + * able to set their time based on a standard timespec. + * + * Input Parameters: + * ts - Time to set. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +int up_rtc_settime(const struct timespec *ts) +{ + uint64_t now_us; + uint64_t rtc_offset_us; + irqstate_t flags; + + DEBUGASSERT(ts != NULL && ts->tv_nsec < NSEC_PER_SEC); + + flags = spin_lock_irqsave(NULL); + + now_us = ((uint64_t) ts->tv_sec) * USEC_PER_SEC + + ts->tv_nsec / NSEC_PER_USEC; + +#ifdef CONFIG_RTC_DRIVER + if (g_hr_timer_enabled) + { + /* Set based on HR-Timer offset value */ + + rtc_offset_us = now_us - esp_hr_timer_time_us(); + } + else +#endif + { + /* Set based on the offset value of the RTC controller */ + + rtc_offset_us = now_us - esp_rtc_get_time_us(); + } + + g_rtc_save->offset = 0; + + esp_rtc_set_boot_time(rtc_offset_us); + + spin_unlock_irqrestore(NULL, flags); + + return OK; +} + +/**************************************************************************** + * Name: up_rtc_initialize + * + * Description: + * Initialize the hardware RTC according to the selected configuration. + * This function is called once during the OS initialization sequence. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +int up_rtc_initialize(void) +{ + g_rtc_save = &g_rtc_saved_data; + + /* If saved data is invalid, clear offset information */ + + if (g_rtc_save->magic != MAGIC_RTC_SAVE) + { + g_rtc_save->magic = MAGIC_RTC_SAVE; + g_rtc_save->offset = 0; + esp_rtc_set_boot_time(0); + } + +#ifdef CONFIG_RTC_HIRES + /* Synchronize the base time to the RTC time */ + + up_rtc_gettime(&g_basetime); +#endif + + g_rtc_enabled = true; + + return OK; +} + +/**************************************************************************** + * Name: esp_rtc_driverinit + * + * Description: + * Initialize and register an RTC lower half driver. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_DRIVER +int esp_rtc_driverinit(void) +{ + struct rtc_lowerhalf_s *lower = (struct rtc_lowerhalf_s *)&g_rtc_lowerhalf; + + int ret = rtc_initialize(0, lower); + if (ret < 0) + { + return ret; + } + + /* HR-Timer enabled */ + + g_hr_timer_enabled = true; + + /* Get the time difference between HR Timer and RTC */ + + g_rtc_save->offset = esp_rtc_get_time_us() - esp_hr_timer_time_us(); + + return ret; +} +#endif /* CONFIG_RTC_DRIVER */ diff --git a/arch/risc-v/src/espressif/esp_rtc.h b/arch/risc-v/src/espressif/esp_rtc.h new file mode 100644 index 0000000000..0ddc9d2ac1 --- /dev/null +++ b/arch/risc-v/src/espressif/esp_rtc.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * arch/risc-v/src/espressif/esp_rtc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_ESPRESSIF_ESP_RTC_H +#define __ARCH_RISCV_SRC_ESPRESSIF_ESP_RTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_rtc_driverinit + * + * Description: + * Initialize and register an RTC lower half driver. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on any failure. + * + ****************************************************************************/ + +int esp_rtc_driverinit(void); + +#endif /* __ARCH_RISCV_SRC_ESPRESSIF_ESP_RTC_H */ diff --git a/arch/risc-v/src/espressif/hal_esp32c6.mk b/arch/risc-v/src/espressif/hal_esp32c6.mk index dbed87ff05..8f698e360d 100644 --- a/arch/risc-v/src/espressif/hal_esp32c6.mk +++ b/arch/risc-v/src/espressif/hal_esp32c6.mk @@ -95,6 +95,7 @@ CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_UNPACK)/components/hal/uart_hal.c CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_UNPACK)/components/hal/uart_hal_iram.c CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_UNPACK)/components/hal/$(CHIP_SERIES)/clk_tree_hal.c CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_UNPACK)/components/hal/$(CHIP_SERIES)/efuse_hal.c +CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_UNPACK)/components/hal/$(CHIP_SERIES)/lp_timer_hal.c CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_UNPACK)/components/hal/$(CHIP_SERIES)/modem_clock_hal.c CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_UNPACK)/components/log/log.c CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_UNPACK)/components/log/log_noos.c diff --git a/boards/risc-v/espressif/esp32c3-generic/configs/rtc/defconfig b/boards/risc-v/espressif/esp32c3-generic/configs/rtc/defconfig new file mode 100644 index 0000000000..dfed670b9d --- /dev/null +++ b/boards/risc-v/espressif/esp32c3-generic/configs/rtc/defconfig @@ -0,0 +1,51 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c3-generic" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32C3_GENERIC=y +CONFIG_ARCH_CHIP="espressif" +CONFIG_ARCH_CHIP_ESPRESSIF=y +CONFIG_ARCH_INTERRUPTSTACK=1536 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_EXAMPLES_ALARM=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_DATE=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_RTC=y +CONFIG_RTC_ALARM=y +CONFIG_RTC_DRIVER=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=5 +CONFIG_START_MONTH=4 +CONFIG_START_YEAR=2023 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/espressif/esp32c3-generic/src/esp32c3_bringup.c b/boards/risc-v/espressif/esp32c3-generic/src/esp32c3_bringup.c index d2aa66a025..1ed308b374 100644 --- a/boards/risc-v/espressif/esp32c3-generic/src/esp32c3_bringup.c +++ b/boards/risc-v/espressif/esp32c3-generic/src/esp32c3_bringup.c @@ -50,6 +50,10 @@ # include "esp_hr_timer.h" #endif +#ifdef CONFIG_RTC_DRIVER +# include "esp_rtc.h" +#endif + #include "esp32c3-generic.h" /**************************************************************************** @@ -145,6 +149,16 @@ int esp_bringup(void) } #endif +#ifdef CONFIG_RTC_DRIVER + /* Initialize the RTC driver */ + + ret = esp_rtc_driverinit(); + if (ret < 0) + { + _err("Failed to initialize the RTC driver: %d\n", ret); + } +#endif + /* If we got here then perhaps not all initialization was successful, but * at least enough succeeded to bring-up NSH with perhaps reduced * capabilities. diff --git a/boards/risc-v/espressif/esp32c6-generic/configs/rtc/defconfig b/boards/risc-v/espressif/esp32c6-generic/configs/rtc/defconfig new file mode 100644 index 0000000000..3d6988d808 --- /dev/null +++ b/boards/risc-v/espressif/esp32c6-generic/configs/rtc/defconfig @@ -0,0 +1,52 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c6-generic" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32C6_GENERIC=y +CONFIG_ARCH_CHIP="espressif" +CONFIG_ARCH_CHIP_ESPRESSIF=y +CONFIG_ARCH_INTERRUPTSTACK=1536 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_ESP32C6=y +CONFIG_EXAMPLES_ALARM=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_DATE=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_RTC=y +CONFIG_RTC_ALARM=y +CONFIG_RTC_DRIVER=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=5 +CONFIG_START_MONTH=4 +CONFIG_START_YEAR=2023 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/espressif/esp32c6-generic/src/esp32c6_bringup.c b/boards/risc-v/espressif/esp32c6-generic/src/esp32c6_bringup.c index d0c1e55b28..5873847eea 100644 --- a/boards/risc-v/espressif/esp32c6-generic/src/esp32c6_bringup.c +++ b/boards/risc-v/espressif/esp32c6-generic/src/esp32c6_bringup.c @@ -50,6 +50,10 @@ # include "esp_hr_timer.h" #endif +#ifdef CONFIG_RTC_DRIVER +# include "esp_rtc.h" +#endif + #include "esp32c6-generic.h" /**************************************************************************** @@ -145,6 +149,16 @@ int esp_bringup(void) } #endif +#ifdef CONFIG_RTC_DRIVER + /* Initialize the RTC driver */ + + ret = esp_rtc_driverinit(); + if (ret < 0) + { + _err("Failed to initialize the RTC driver: %d\n", ret); + } +#endif + /* If we got here then perhaps not all initialization was successful, but * at least enough succeeded to bring-up NSH with perhaps reduced * capabilities. diff --git a/boards/risc-v/espressif/esp32h2-generic/configs/rtc/defconfig b/boards/risc-v/espressif/esp32h2-generic/configs/rtc/defconfig new file mode 100644 index 0000000000..d168b1fbfa --- /dev/null +++ b/boards/risc-v/espressif/esp32h2-generic/configs/rtc/defconfig @@ -0,0 +1,52 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32h2-generic" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32H2_GENERIC=y +CONFIG_ARCH_CHIP="espressif" +CONFIG_ARCH_CHIP_ESPRESSIF=y +CONFIG_ARCH_INTERRUPTSTACK=1536 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_ESP32H2=y +CONFIG_EXAMPLES_ALARM=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_DATE=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_RTC=y +CONFIG_RTC_ALARM=y +CONFIG_RTC_DRIVER=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=5 +CONFIG_START_MONTH=4 +CONFIG_START_YEAR=2023 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/espressif/esp32h2-generic/src/esp32h2_bringup.c b/boards/risc-v/espressif/esp32h2-generic/src/esp32h2_bringup.c index acf1de7c17..8229ca6f7b 100644 --- a/boards/risc-v/espressif/esp32h2-generic/src/esp32h2_bringup.c +++ b/boards/risc-v/espressif/esp32h2-generic/src/esp32h2_bringup.c @@ -50,6 +50,10 @@ # include "esp_hr_timer.h" #endif +#ifdef CONFIG_RTC_DRIVER +# include "esp_rtc.h" +#endif + #include "esp32h2-generic.h" /**************************************************************************** @@ -145,6 +149,16 @@ int esp_bringup(void) } #endif +#ifdef CONFIG_RTC_DRIVER + /* Initialize the RTC driver */ + + ret = esp_rtc_driverinit(); + if (ret < 0) + { + _err("Failed to initialize the RTC driver: %d\n", ret); + } +#endif + /* If we got here then perhaps not all initialization was successful, but * at least enough succeeded to bring-up NSH with perhaps reduced * capabilities.