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.


Reply via email to