You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/06/19 03:01:42 UTC
[incubator-nuttx] branch master updated: xtensa/esp32: Support
ESP32 RTC driver
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new c3792f0 xtensa/esp32: Support ESP32 RTC driver
c3792f0 is described below
commit c3792f0aaeb067ccf64f793e94b3cb68fd175290
Author: chenwen <ch...@espressif.com>
AuthorDate: Thu Jun 17 19:14:33 2021 +0800
xtensa/esp32: Support ESP32 RTC driver
---
arch/xtensa/src/esp32/Kconfig | 1 +
arch/xtensa/src/esp32/Make.defs | 4 +
arch/xtensa/src/esp32/esp32_rtc.c | 593 ++++++++++++++++++++-
arch/xtensa/src/esp32/esp32_rtc.h | 225 ++++++++
arch/xtensa/src/esp32/esp32_rtc_lowerhalf.c | 565 ++++++++++++++++++++
arch/xtensa/src/esp32/esp32_rtc_lowerhalf.h | 56 ++
.../esp32/esp32-devkitc/configs/rtc/defconfig | 53 ++
.../xtensa/esp32/esp32-devkitc/src/esp32_bringup.c | 15 +
.../esp32/esp32-ethernet-kit/configs/rtc/defconfig | 52 ++
.../esp32/esp32-ethernet-kit/src/esp32_bringup.c | 15 +
.../esp32/esp32-wrover-kit/configs/rtc/defconfig | 53 ++
.../esp32/esp32-wrover-kit/src/esp32_bringup.c | 15 +
12 files changed, 1644 insertions(+), 3 deletions(-)
diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig
index bdfa9a7..14dfb0f 100644
--- a/arch/xtensa/src/esp32/Kconfig
+++ b/arch/xtensa/src/esp32/Kconfig
@@ -214,6 +214,7 @@ endchoice # On-board Crystal Frequency
config ESP32_RT_TIMER
bool "Real-time Timer"
default n
+ select ESP32_TIMER0
config ESP32_PARTITION
bool "ESP32 Partition"
diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs
index 964468a..113edd9 100644
--- a/arch/xtensa/src/esp32/Make.defs
+++ b/arch/xtensa/src/esp32/Make.defs
@@ -193,6 +193,10 @@ ifeq ($(CONFIG_ESP32_AES_ACCELERATOR),y)
CHIP_CSRCS += esp32_aes.c
endif
+ifeq ($(CONFIG_RTC_DRIVER),y)
+CHIP_CSRCS += esp32_rtc_lowerhalf.c
+endif
+
ifeq ($(CONFIG_ESP32_WIRELESS),y)
WIRELESS_DRV_UNPACK = esp-wireless-drivers-3rdparty
WIRELESS_DRV_ID = 2b53111
diff --git a/arch/xtensa/src/esp32/esp32_rtc.c b/arch/xtensa/src/esp32/esp32_rtc.c
index 0c4be46..47cd168 100644
--- a/arch/xtensa/src/esp32/esp32_rtc.c
+++ b/arch/xtensa/src/esp32/esp32_rtc.c
@@ -24,13 +24,19 @@
#include <stdint.h>
#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/spinlock.h>
#include "esp32_rtc.h"
#include "esp32_clockconfig.h"
+#include "esp32_rt_timer.h"
+
#include "hardware/esp32_rtccntl.h"
#include "hardware/esp32_dport.h"
#include "hardware/esp32_i2s.h"
-#include "esp32_rtc.h"
+
#include "xtensa.h"
#include "xtensa_attr.h"
@@ -124,6 +130,25 @@
.fe_pd = (val), \
}
+#ifdef CONFIG_RTC_DRIVER
+/* The magic data for the struct esp32_rtc_backup_s that is in RTC slow
+ * memory.
+ */
+
+# define MAGIC_RTC_SAVE (UINT64_C(0x11223344556677))
+#endif
+
+/* RTC Memory & Store Register usage */
+
+#define RTC_SLOW_CLK_CAL_REG RTC_CNTL_STORE1_REG /* RTC_SLOW_CLK calibration value */
+#define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG /* Boot time, low word */
+#define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG /* Boot time, high word */
+#define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG /* External XTAL frequency */
+#define RTC_APB_FREQ_REG RTC_CNTL_STORE5_REG /* APB bus frequency */
+#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG /* FAST_RTC_MEMORY_ENTRY */
+#define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG
+#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG /* FAST_RTC_MEMORY_CRC */
+
/****************************************************************************
* Private Types
****************************************************************************/
@@ -176,6 +201,28 @@ struct esp32_rtc_sleep_pd_config_s
uint32_t fe_pd : 1; /* Set to 1 to power down WiFi in sleep */
};
+#ifdef CONFIG_RTC_DRIVER
+
+#ifdef CONFIG_RTC_ALARM
+struct alm_cbinfo_s
+{
+ struct rt_timer_s *alarm_hdl; /* Timer id point to here */
+ volatile alm_callback_t ac_cb; /* Client callback function */
+ volatile FAR void *ac_arg; /* Argument to pass with the callback function */
+ uint64_t deadline_us;
+ uint8_t index;
+};
+#endif
+
+struct esp32_rtc_backup_s
+{
+ uint64_t magic;
+ int64_t offset; /* Offset time from RTC HW value */
+ int64_t reserved0;
+};
+
+#endif
+
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -191,6 +238,10 @@ static void IRAM_ATTR esp32_rtc_clk_slow_freq_set(
enum esp32_rtc_slow_freq_e slow_freq);
static void esp32_select_rtc_slow_clk(enum esp32_slow_clk_sel_e slow_clk);
+#ifdef CONFIG_RTC_DRIVER
+static void IRAM_ATTR esp32_rt_cb_handler(FAR void *arg);
+#endif
+
/****************************************************************************
* Private Data
****************************************************************************/
@@ -205,6 +256,31 @@ static struct esp32_rtc_priv_s esp32_rtc_priv =
.rtc_dboost_fpd = 1
};
+#ifdef CONFIG_RTC_DRIVER
+
+/* Callback to use when the alarm expires */
+
+#ifdef CONFIG_RTC_ALARM
+static struct alm_cbinfo_s g_alarmcb[RTC_ALARM_LAST];
+#endif
+
+static RTC_DATA_ATTR struct esp32_rtc_backup_s rtc_saved_data;
+
+/* Saved data for persistent RTC time */
+
+static struct esp32_rtc_backup_s *g_rtc_save;
+static bool g_rt_timer_enabled = false;
+
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_DRIVER
+volatile bool g_rtc_enabled = false;
+#endif
+
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -475,6 +551,49 @@ static void esp32_select_rtc_slow_clk(enum esp32_slow_clk_sel_e slow_clk)
putreg32((uint32_t)cal_val, RTC_SLOW_CLK_CAL_REG);
}
+#ifdef CONFIG_RTC_DRIVER
+
+/****************************************************************************
+ * Name: esp32_rt_cb_handler
+ *
+ * Description:
+ * RT-Timer service routine
+ *
+ * Input Parameters:
+ * arg - Information about the RT-Timer configuration.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32_rt_cb_handler(FAR void *arg)
+{
+ FAR struct alm_cbinfo_s *cbinfo = (struct alm_cbinfo_s *)arg;
+ alm_callback_t cb;
+ FAR void *cb_arg;
+ int alminfo_id;
+
+ DEBUGASSERT(cbinfo != NULL);
+ alminfo_id = cbinfo->index;
+ DEBUGASSERT((RTC_ALARM0 <= alminfo_id) &&
+ (alminfo_id < RTC_ALARM_LAST));
+
+ if (cbinfo->ac_cb != NULL)
+ {
+ /* Alarm callback */
+
+ cb = cbinfo->ac_cb;
+ cb_arg = (FAR 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 */
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -826,7 +945,7 @@ void IRAM_ATTR esp32_rtc_bbpll_configure(
*
****************************************************************************/
-void esp32_rtc_clk_set()
+void esp32_rtc_clk_set(void)
{
enum esp32_rtc_fast_freq_e fast_freq = RTC_FAST_FREQ_8M;
enum esp32_slow_clk_sel_e slow_clk = RTC_SLOW_FREQ_RTC;
@@ -848,7 +967,7 @@ void esp32_rtc_clk_set()
*
****************************************************************************/
-void IRAM_ATTR esp32_rtc_init()
+void IRAM_ATTR esp32_rtc_init(void)
{
struct esp32_rtc_priv_s *priv = &esp32_rtc_priv;
@@ -1473,3 +1592,471 @@ int IRAM_ATTR esp32_rtc_sleep_start(uint32_t wakeup_opt,
RTC_CNTL_DBG_ATTEN_DEFAULT);
return reject;
}
+
+/****************************************************************************
+ * Name: esp32_rtc_get_time_us
+ *
+ * Description:
+ * Get current value of RTC counter in microseconds
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Current value of RTC counter in microseconds
+ *
+ ****************************************************************************/
+
+uint64_t esp32_rtc_get_time_us(void)
+{
+ const uint32_t cal = getreg32(RTC_SLOW_CLK_CAL_REG);
+ const uint64_t rtc_this_ticks = esp32_rtc_time_get();
+
+ /* RTC counter result is up to 2^48, calibration factor is up to 2^24,
+ * for a 32kHz clock. We need to calculate (assuming no overflow):
+ * (ticks * cal) >> RTC_CLK_CAL_FRACT. An overflow in the (ticks * cal)
+ * multiplication would cause time to wrap around after approximately
+ * 13 days, which is probably not enough for some applications.
+ * Therefore multiplication is split into two terms, for the lower 32-bit
+ * and the upper 16-bit parts of "ticks", i.e.:
+ * ((ticks_low + 2^32 * ticks_high) * cal) >> RTC_CLK_CAL_FRACT
+ */
+
+ const uint64_t ticks_low = rtc_this_ticks & UINT32_MAX;
+ const uint64_t ticks_high = rtc_this_ticks >> 32;
+ const uint64_t delta_time_us = ((ticks_low * cal) >> RTC_CLK_CAL_FRACT) +
+ ((ticks_high * cal) << (32 - RTC_CLK_CAL_FRACT));
+
+ return delta_time_us;
+}
+
+/****************************************************************************
+ * Name: esp32_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
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32_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: esp32_rtc_get_boot_time
+ *
+ * Description:
+ * Get time of RTC register to indicate the original boot time.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * time_us - get time in microseconds.
+ *
+ ****************************************************************************/
+
+uint64_t IRAM_ATTR esp32_rtc_get_boot_time(void)
+{
+ return ((uint64_t)getreg32(RTC_BOOT_TIME_LOW_REG))
+ + (((uint64_t)getreg32(RTC_BOOT_TIME_HIGH_REG)) << 32);
+}
+
+#ifdef CONFIG_RTC_DRIVER
+
+/****************************************************************************
+ * 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:
+ * The 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);
+
+ /* NOTE: RT-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 RT-Timer cannot work).
+ */
+
+ /* Determine if RT-Timer is started */
+
+ if (g_rt_timer_enabled == true)
+ {
+ /* Get the time from RT-Timer, the time interval between RTC
+ * controller and RT-Timer is stored in g_rtc_save->offset.
+ */
+
+ time_us = rt_timer_time_us() + g_rtc_save->offset +
+ esp32_rtc_get_boot_time();
+ }
+ else
+ {
+ /* Get the time from RTC controller. */
+
+ time_us = esp32_rtc_get_time_us() +
+ esp32_rtc_get_boot_time();
+ }
+
+ spin_unlock_irqrestore(NULL, flags);
+
+ return (time_t)(time_us / USEC_PER_SEC);
+}
+#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 - the time to use
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_settime(FAR const struct timespec *ts)
+{
+ irqstate_t flags;
+ uint64_t now_us;
+ uint64_t rtc_offset_us;
+
+ 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;
+ if (g_rt_timer_enabled == true)
+ {
+ /* Set based on RT-Timer offset value. */
+
+ rtc_offset_us = now_us - rt_timer_time_us();
+ }
+ else
+ {
+ /* Set based on the offset value of the RT controller. */
+
+ rtc_offset_us = now_us - esp32_rtc_get_time_us();
+ }
+
+ g_rtc_save->offset = 0;
+ esp32_rtc_set_boot_time(rtc_offset_us);
+
+ spin_unlock_irqrestore(NULL, flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_rtc_initialize
+ *
+ * Description:
+ * Initialize the hardware RTC per the selected configuration.
+ * This function is called once during the OS initialization sequence
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_initialize(void)
+{
+#ifndef CONFIG_PM
+ /* Initialize RTC controller parameters */
+
+ esp32_rtc_init();
+ esp32_rtc_clk_set();
+#endif
+
+ g_rtc_save = &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;
+ esp32_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: up_rtc_gettime
+ *
+ * Description:
+ * Get the current time from the high resolution RTC time or RT-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 RT-Timer value.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_HIRES
+int up_rtc_gettime(FAR struct timespec *tp)
+{
+ irqstate_t flags;
+ uint64_t time_us;
+
+ flags = spin_lock_irqsave(NULL);
+
+ if (g_rt_timer_enabled == true)
+ {
+ time_us = rt_timer_time_us() + g_rtc_save->offset +
+ esp32_rtc_get_boot_time();
+ }
+ else
+ {
+ time_us = = esp32_rtc_get_time_us() +
+ esp32_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 */
+
+#ifdef CONFIG_RTC_ALARM
+
+/****************************************************************************
+ * Name: up_rtc_setalarm
+ *
+ * Description:
+ * Set up an alarm.
+ *
+ * Input Parameters:
+ * alminfo - Information about the alarm configuration.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_setalarm(FAR struct alm_setalarm_s *alminfo)
+{
+ struct rt_timer_args_s rt_timer_args;
+ FAR struct alm_cbinfo_s *cbinfo;
+ irqstate_t flags;
+ int ret = -EBUSY;
+ int id;
+
+ DEBUGASSERT(alminfo != NULL);
+ DEBUGASSERT((RTC_ALARM0 <= alminfo->as_id) &&
+ (alminfo->as_id < RTC_ALARM_LAST));
+
+ /* Set the alarm in RT-Timer */
+
+ id = alminfo->as_id;
+ cbinfo = &g_alarmcb[id];
+
+ if (cbinfo->ac_cb == NULL)
+ {
+ /* Create the RT-Timer alarm */
+
+ flags = spin_lock_irqsave(NULL);
+
+ if (cbinfo->alarm_hdl == NULL)
+ {
+ cbinfo->index = id;
+ rt_timer_args.arg = cbinfo;
+ rt_timer_args.callback = esp32_rt_cb_handler;
+ ret = rt_timer_create(&rt_timer_args, &cbinfo->alarm_hdl);
+ if (ret < 0)
+ {
+ rtcerr("ERROR: Failed to create rt_timer error=%d\n", ret);
+ spin_unlock_irqrestore(NULL, flags);
+ return ret;
+ }
+ }
+
+ cbinfo->ac_cb = alminfo->as_cb;
+ cbinfo->ac_arg = alminfo->as_arg;
+ cbinfo->deadline_us = alminfo->as_time.tv_sec * USEC_PER_SEC +
+ alminfo->as_time.tv_nsec / NSEC_PER_USEC;
+
+ if (cbinfo->alarm_hdl == NULL)
+ {
+ rtcerr("ERROR: failed to create alarm timer\n");
+ }
+ else
+ {
+ rtcinfo("Start RTC alarm.\n");
+ rt_timer_start(cbinfo->alarm_hdl, cbinfo->deadline_us, false);
+ ret = OK;
+ }
+
+ spin_unlock_irqrestore(NULL, flags);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: up_rtc_cancelalarm
+ *
+ * Description:
+ * Cancel an alarm.
+ *
+ * Input Parameters:
+ * alarmid - Identifies the alarm to be cancelled
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_cancelalarm(enum alm_id_e alarmid)
+{
+ FAR struct alm_cbinfo_s *cbinfo;
+ irqstate_t flags;
+ int ret = -ENODATA;
+
+ DEBUGASSERT((RTC_ALARM0 <= alarmid) &&
+ (alarmid < RTC_ALARM_LAST));
+
+ /* Set the alarm in hardware and enable interrupts */
+
+ cbinfo = &g_alarmcb[alarmid];
+
+ if (cbinfo->ac_cb != NULL)
+ {
+ flags = spin_lock_irqsave(NULL);
+
+ /* Stop and delete the alarm */
+
+ rtcinfo("Cancel RTC alarm.\n");
+ rt_timer_stop(cbinfo->alarm_hdl);
+ rt_timer_delete(cbinfo->alarm_hdl);
+ cbinfo->ac_cb = NULL;
+ cbinfo->deadline_us = 0;
+ cbinfo->alarm_hdl = NULL;
+
+ spin_unlock_irqrestore(NULL, flags);
+
+ ret = OK;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: up_rtc_rdalarm
+ *
+ * Description:
+ * Query an alarm configured in hardware.
+ *
+ * Input Parameters:
+ * tp - Location to return the timer match register.
+ * alarmid - Identifies the alarm to get.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_rdalarm(FAR struct timespec *tp, uint32_t alarmid)
+{
+ irqstate_t flags;
+ FAR struct alm_cbinfo_s *cbinfo;
+ DEBUGASSERT(tp != NULL);
+ DEBUGASSERT((RTC_ALARM0 <= alarmid) &&
+ (alarmid < RTC_ALARM_LAST));
+
+ flags = spin_lock_irqsave(NULL);
+
+ /* Get the alarm according to the alarmid */
+
+ cbinfo = &g_alarmcb[alarmid];
+
+ tp->tv_sec = (rt_timer_time_us() + g_rtc_save->offset +
+ cbinfo->deadline_us) / USEC_PER_SEC;
+ tp->tv_nsec = ((rt_timer_time_us() + g_rtc_save->offset +
+ cbinfo->deadline_us) % USEC_PER_SEC) * NSEC_PER_USEC;
+
+ spin_unlock_irqrestore(NULL, flags);
+
+ return OK;
+}
+
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Name: up_rtc_timer_init
+ *
+ * Description:
+ * Init RTC timer.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_timer_init(void)
+{
+ /* RT-Timer enabled */
+
+ g_rt_timer_enabled = true;
+
+ /* Get the time difference between rt_timer and RTC timer */
+
+ g_rtc_save->offset = esp32_rtc_get_time_us() - rt_timer_time_us();
+
+ return OK;
+}
+
+#endif /* CONFIG_RTC_DRIVER */
\ No newline at end of file
diff --git a/arch/xtensa/src/esp32/esp32_rtc.h b/arch/xtensa/src/esp32/esp32_rtc.h
index 025c878..3ce469b 100644
--- a/arch/xtensa/src/esp32/esp32_rtc.h
+++ b/arch/xtensa/src/esp32/esp32_rtc.h
@@ -30,6 +30,9 @@
****************************************************************************/
#include <nuttx/config.h>
+#include <nuttx/timers/rtc.h>
+#include <sys/types.h>
+#include <time.h>
#include "hardware/esp32_soc.h"
#ifndef __ASSEMBLY__
@@ -127,6 +130,31 @@ enum esp32_rtc_cal_sel_e
RTC_CAL_32K_XTAL = 2 /* External 32 kHz XTAL */
};
+#ifdef CONFIG_RTC_ALARM
+
+/* The form of an alarm callback */
+
+typedef CODE void (*alm_callback_t)(FAR void *arg, unsigned int alarmid);
+
+enum alm_id_e
+{
+ RTC_ALARM0 = 0, /* RTC ALARM 0 */
+ RTC_ALARM1 = 1, /* RTC ALARM 1 */
+ RTC_ALARM_LAST,
+};
+
+/* Structure used to pass parameters to set an alarm */
+
+struct alm_setalarm_s
+{
+ int as_id; /* enum alm_id_e */
+ struct timespec as_time; /* Alarm expiration time */
+ alm_callback_t as_cb; /* Callback (if non-NULL) */
+ FAR void *as_arg; /* Argument for callback */
+};
+
+#endif /* CONFIG_RTC_ALARM */
+
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
@@ -447,6 +475,203 @@ void esp32_rtc_sleep_init(uint32_t flags);
int esp32_rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt);
+/****************************************************************************
+ * Name: esp32_rtc_get_time_us
+ *
+ * Description:
+ * Get current value of RTC counter in microseconds
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Current value of RTC counter in microseconds
+ *
+ ****************************************************************************/
+
+uint64_t esp32_rtc_get_time_us(void);
+
+/****************************************************************************
+ * Name: esp32_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
+ *
+ ****************************************************************************/
+
+void esp32_rtc_set_boot_time(uint64_t time_us);
+
+/****************************************************************************
+ * Name: esp32_rtc_get_boot_time
+ *
+ * Description:
+ * Get time of RTC register to indicate the original boot time.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * time_us - get time in microseconds.
+ *
+ ****************************************************************************/
+
+uint64_t esp32_rtc_get_boot_time(void);
+
+#ifdef CONFIG_RTC_DRIVER
+
+/****************************************************************************
+ * 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 selected. It is only used by the
+ * RTOS during initialization to set up the system time when CONFIG_RTC is
+ * set but neither CONFIG_RTC_HIRES nor CONFIG_RTC_DATETIME are set.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * The current time in seconds
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_RTC_HIRES
+time_t up_rtc_time(void);
+#endif
+
+/****************************************************************************
+ * 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:
+ * tp - the time to use
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_settime(FAR const struct timespec *ts);
+
+/****************************************************************************
+ * Name: up_rtc_initialize
+ *
+ * Description:
+ * Initialize the hardware RTC per the selected configuration.
+ * This function is called once during the OS initialization sequence
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_initialize(void);
+
+/****************************************************************************
+ * Name: up_rtc_gettime
+ *
+ * Description:
+ * Get the current time from the high resolution RTC clock/counter. 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 high resolution time value.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_HIRES
+int up_rtc_gettime(FAR struct timespec *tp);
+#endif
+
+#ifdef CONFIG_RTC_ALARM
+
+/****************************************************************************
+ * Name: up_rtc_setalarm
+ *
+ * Description:
+ * Set up an alarm.
+ *
+ * Input Parameters:
+ * alminfo - Information about the alarm configuration.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_setalarm(FAR struct alm_setalarm_s *alminfo);
+
+/****************************************************************************
+ * Name: up_rtc_cancelalarm
+ *
+ * Description:
+ * Cancel an alaram.
+ *
+ * Input Parameters:
+ * alarmid - Identifies the alarm to be cancelled
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_cancelalarm(enum alm_id_e alarmid);
+
+/****************************************************************************
+ * Name: up_rtc_rdalarm
+ *
+ * Description:
+ * Query an alarm configured in hardware.
+ *
+ * Input Parameters:
+ * tp - Location to return the timer match register.
+ * alarmid - Identifies the alarm to be cancelled
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_rdalarm(FAR struct timespec *tp, uint32_t alarmid);
+
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Name: up_rtc_timer_init
+ *
+ * Description:
+ * Init RTC timer.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int up_rtc_timer_init(void);
+
+#endif /* CONFIG_RTC_DRIVER */
+
#ifdef __cplusplus
}
#endif
diff --git a/arch/xtensa/src/esp32/esp32_rtc_lowerhalf.c b/arch/xtensa/src/esp32/esp32_rtc_lowerhalf.c
new file mode 100644
index 0000000..e2ca2ed
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_rtc_lowerhalf.c
@@ -0,0 +1,565 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_rtc_lowerhalf.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 <nuttx/spinlock.h>
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/timers/rtc.h>
+
+#include "esp32_rtc.h"
+#include "hardware/esp32_tim.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+struct esp32_cbinfo_s
+{
+ volatile rtc_alarm_callback_t cb; /* Callback when the alarm expires */
+ volatile FAR void *priv; /* Private argurment to accompany callback */
+};
+#endif
+
+/* This is the private type for the RTC state. It must be cast compatible
+ * with struct rtc_lowerhalf_s.
+ */
+
+struct esp32_lowerhalf_s
+{
+ /* This is the contained reference to the read-only, lower-half
+ * operations vtable (which may lie in FLASH or ROM)
+ */
+
+ FAR const struct rtc_ops_s *ops;
+#ifdef CONFIG_RTC_ALARM
+ /* Alarm callback information */
+
+ struct esp32_cbinfo_s cbinfo[RTC_ALARM_LAST];
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Prototypes for static methods in struct rtc_ops_s */
+
+static int rtc_lh_rdtime(FAR struct rtc_lowerhalf_s *lower,
+ FAR struct rtc_time *rtctime);
+static int rtc_lh_settime(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct rtc_time *rtctime);
+static bool rtc_lh_havesettime(FAR struct rtc_lowerhalf_s *lower);
+
+#ifdef CONFIG_RTC_ALARM
+static void rtc_lh_alarm_callback(FAR void *arg, unsigned int alarmid);
+static int rtc_lh_setalarm(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setalarm_s *alarminfo);
+static int rtc_lh_setrelative(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setrelative_s *alarminfo);
+static int rtc_lh_cancelalarm(FAR struct rtc_lowerhalf_s *lower,
+ int alarmid);
+static int rtc_lh_rdalarm(FAR struct rtc_lowerhalf_s *lower,
+ FAR struct lower_rdalarm_s *alarminfo);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* ESP32 RTC driver operations */
+
+static const struct rtc_ops_s g_rtc_ops =
+{
+ .rdtime = rtc_lh_rdtime,
+ .settime = rtc_lh_settime,
+ .havesettime = rtc_lh_havesettime,
+#ifdef CONFIG_RTC_ALARM
+ .setalarm = rtc_lh_setalarm,
+ .setrelative = rtc_lh_setrelative,
+ .cancelalarm = rtc_lh_cancelalarm,
+ .rdalarm = rtc_lh_rdalarm,
+#endif
+#ifdef CONFIG_RTC_PERIODIC
+ .setperiodic = NULL,
+ .cancelperiodic = NULL,
+#endif
+#ifdef CONFIG_RTC_IOCTL
+ .ioctl = NULL,
+#endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ .destroy = NULL,
+#endif
+};
+
+/* ESP32 RTC device state */
+
+static struct esp32_lowerhalf_s g_rtc_lowerhalf =
+{
+ .ops = &g_rtc_ops,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rtc_lh_alarm_callback
+ *
+ * Description:
+ * This is the function that is called from the RTC driver when the alarm
+ * goes off. It just invokes the upper half drivers callback.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static void rtc_lh_alarm_callback(FAR void *arg, unsigned int alarmid)
+{
+ FAR struct esp32_lowerhalf_s *lower;
+ FAR struct esp32_cbinfo_s *cbinfo;
+ rtc_alarm_callback_t cb;
+ FAR void *priv;
+
+ DEBUGASSERT((RTC_ALARM0 <= alarmid) && (alarmid < RTC_ALARM_LAST));
+
+ lower = (struct esp32_lowerhalf_s *)arg;
+ cbinfo = &lower->cbinfo[alarmid];
+
+ /* Sample and clear the callback information to minimize the window in
+ * time in which race conditions can occur.
+ */
+
+ cb = (rtc_alarm_callback_t)cbinfo->cb;
+ priv = (FAR void *)cbinfo->priv;
+
+ cbinfo->cb = NULL;
+ cbinfo->priv = NULL;
+
+ /* Perform the callback */
+
+ if (cb != NULL)
+ {
+ cb(priv, alarmid);
+ }
+}
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Name: rtc_lh_rdtime
+ *
+ * Description:
+ * Returns 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.
+ *
+ ****************************************************************************/
+
+static int rtc_lh_rdtime(FAR struct rtc_lowerhalf_s *lower,
+ FAR struct rtc_time *rtctime)
+{
+#if defined(CONFIG_RTC_HIRES)
+ FAR 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 tm. This operation
+ * depends on the fact that struct rtc_time and struct tm are cast
+ * compatible.
+ */
+
+ if (!gmtime_r(&ts.tv_sec, (FAR struct tm *)rtctime))
+ {
+ ret = -get_errno();
+ goto errout;
+ }
+
+ return OK;
+
+errout:
+ rtcerr("ERROR: failed to get RTC time: %d\n", ret);
+ return ret;
+
+#else
+ 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, (FAR struct tm *)rtctime) == 0)
+ {
+ int errcode = get_errno();
+ DEBUGASSERT(errcode > 0);
+
+ rtcerr("ERROR: gmtime_r failed: %d\n", errcode);
+ return -errcode;
+ }
+
+ return OK;
+#endif
+}
+
+/****************************************************************************
+ * Name: rtc_lh_settime
+ *
+ * Description:
+ * Implements 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.
+ *
+ ****************************************************************************/
+
+static int rtc_lh_settime(FAR struct rtc_lowerhalf_s *lower,
+ FAR 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((FAR struct tm *)rtctime);
+ ts.tv_nsec = 0;
+
+ /* Now set the time (with a accuracy of seconds) */
+
+ return up_rtc_settime(&ts);
+}
+
+/****************************************************************************
+ * Name: rtc_lh_havesettime
+ *
+ * Description:
+ * Implements the havesettime() method of the RTC driver interface
+ *
+ * Input Parameters:
+ * lower - A reference to RTC lower half driver state structure
+ *
+ * Returned Value:
+ * Returns true if RTC date-time have been previously set.
+ *
+ ****************************************************************************/
+
+static bool rtc_lh_havesettime(FAR struct rtc_lowerhalf_s *lower)
+{
+ if (esp32_rtc_get_boot_time() == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ * Name: rtc_lh_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.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static int rtc_lh_setalarm(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setalarm_s *alarminfo)
+{
+ FAR struct esp32_lowerhalf_s *priv;
+ FAR struct esp32_cbinfo_s *cbinfo;
+ struct alm_setalarm_s lowerinfo;
+ int ret;
+
+ DEBUGASSERT(lower != NULL && alarminfo != NULL);
+ DEBUGASSERT((RTC_ALARM0 <= alarminfo->id) &&
+ (alarminfo->id < RTC_ALARM_LAST));
+
+ priv = (FAR struct esp32_lowerhalf_s *)lower;
+
+ /* Remember the callback information */
+
+ cbinfo = &priv->cbinfo[alarminfo->id];
+ cbinfo->cb = alarminfo->cb;
+ cbinfo->priv = alarminfo->priv;
+
+ /* Set the alarm */
+
+ lowerinfo.as_id = alarminfo->id;
+ lowerinfo.as_cb = rtc_lh_alarm_callback;
+ lowerinfo.as_arg = priv;
+
+ /* Convert the RTC time to a timespec (1 second accuracy) */
+
+ lowerinfo.as_time.tv_sec = mktime((FAR struct tm *)&alarminfo->time);
+ lowerinfo.as_time.tv_nsec = 0;
+
+ /* And set the alarm */
+
+ ret = up_rtc_setalarm(&lowerinfo);
+ if (ret < 0)
+ {
+ cbinfo->cb = NULL;
+ cbinfo->priv = NULL;
+ }
+
+ return ret;
+}
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Name: rtc_lh_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.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static int rtc_lh_setrelative(FAR struct rtc_lowerhalf_s *lower,
+ FAR 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);
+ DEBUGASSERT((RTC_ALARM0 <= alarminfo->id) &&
+ (alarminfo->id < RTC_ALARM_LAST));
+
+ if (alarminfo->reltime > 0)
+ {
+ flags = spin_lock_irqsave(NULL);
+
+ seconds = alarminfo->reltime;
+ gmtime_r(&seconds, (FAR 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 = rtc_lh_setalarm(lower, &setalarm);
+
+ spin_unlock_irqrestore(NULL, flags);
+ }
+
+ return ret;
+}
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Name: rtc_lh_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 - the alarm id
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned
+ * on any failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static int rtc_lh_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid)
+{
+ FAR struct esp32_lowerhalf_s *priv;
+ FAR struct esp32_cbinfo_s *cbinfo;
+
+ DEBUGASSERT(lower != NULL);
+ DEBUGASSERT((RTC_ALARM0 <= alarmid) && (alarmid < RTC_ALARM_LAST));
+
+ priv = (FAR struct esp32_lowerhalf_s *)lower;
+
+ /* Nullify callback information to reduce window for race conditions */
+
+ cbinfo = &priv->cbinfo[alarmid];
+ cbinfo->cb = NULL;
+ cbinfo->priv = NULL;
+
+ /* Then cancel the alarm */
+
+ return up_rtc_cancelalarm((enum alm_id_e)alarmid);
+}
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Name: rtc_lh_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.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static int rtc_lh_rdalarm(FAR struct rtc_lowerhalf_s *lower,
+ FAR struct lower_rdalarm_s *alarminfo)
+{
+ struct timespec ts;
+ int ret;
+ irqstate_t flags;
+
+ DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->time != NULL);
+ DEBUGASSERT((RTC_ALARM0 <= alarminfo->id) &&
+ (alarminfo->id < RTC_ALARM_LAST));
+
+ flags = spin_lock_irqsave(NULL);
+
+ ret = up_rtc_rdalarm(&ts, alarminfo->id);
+ localtime_r((FAR const time_t *)&ts.tv_sec,
+ (FAR struct tm *)alarminfo->time);
+
+ spin_unlock_irqrestore(NULL, flags);
+
+ return ret;
+}
+#endif /* CONFIG_RTC_ALARM */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_rtc_lowerhalf
+ *
+ * Description:
+ * Instantiate the RTC lower half driver for the ESP32.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * On success, a non-NULL RTC lower interface is returned. NULL is
+ * returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct rtc_lowerhalf_s *esp32_rtc_lowerhalf(void)
+{
+ return (FAR struct rtc_lowerhalf_s *)&g_rtc_lowerhalf;
+}
+
+/****************************************************************************
+ * Name: esp32_rtc_driverinit
+ *
+ * Description:
+ * Bind the configuration timer to a timer lower half instance and register
+ * the timer drivers at 'devpath'
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; A negated errno value is returned
+ * to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+int esp32_rtc_driverinit(void)
+{
+ int ret;
+ FAR struct rtc_lowerhalf_s *lower;
+
+ /* Instantiate the ESP32 lower-half RTC driver */
+
+ lower = esp32_rtc_lowerhalf();
+ if (lower == NULL)
+ {
+ return ret;
+ }
+ else
+ {
+ /* Bind the lower half driver and register the combined RTC driver
+ * as /dev/rtc0
+ */
+
+ ret = rtc_initialize(0, lower);
+ }
+
+ /* Init RTC timer */
+
+ up_rtc_timer_init();
+
+ return ret;
+}
diff --git a/arch/xtensa/src/esp32/esp32_rtc_lowerhalf.h b/arch/xtensa/src/esp32/esp32_rtc_lowerhalf.h
new file mode 100644
index 0000000..a5ef77e
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_rtc_lowerhalf.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_rtc_lowerhalf.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_XTENSA_SRC_ESP32_ESP32_RTC_LOWERHALF_H
+#define __ARCH_XTENSA_SRC_ESP32_ESP32_RTC_LOWERHALF_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_RTC_DRIVER
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_rtc_driverinit
+ *
+ * Description:
+ * Bind the configuration timer to a timer lower half instance and register
+ * the timer drivers at 'devpath'
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; A negated errno value is returned
+ * to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+int esp32_rtc_driverinit(void);
+
+#endif /* CONFIG_RTC_DRIVER */
+
+#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_RTC_LOWERHALF_H */
diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/rtc/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/rtc/defconfig
new file mode 100644
index 0000000..da35167
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-devkitc/configs/rtc/defconfig
@@ -0,0 +1,53 @@
+#
+# 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_ARCH_LEDS is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_CMDPARMS is not set
+CONFIG_ARCH="xtensa"
+CONFIG_ARCH_BOARD="esp32-devkitc"
+CONFIG_ARCH_BOARD_ESP32_DEVKITC=y
+CONFIG_ARCH_CHIP="esp32"
+CONFIG_ARCH_CHIP_ESP32=y
+CONFIG_ARCH_CHIP_ESP32WROVER=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_XTENSA=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BUILTIN=y
+CONFIG_ESP32_RT_TIMER=y
+CONFIG_ESP32_UART0=y
+CONFIG_EXAMPLES_ALARM=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INTELHEX_BINARY=y
+CONFIG_MAX_TASKS=16
+CONFIG_MM_REGIONS=3
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=114688
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_RTC=y
+CONFIG_RTC_ALARM=y
+CONFIG_RTC_DRIVER=y
+CONFIG_RTC_NALARMS=2
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c
index 75a61da..ca844a6 100644
--- a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c
@@ -90,6 +90,10 @@
# include <nuttx/input/buttons.h>
#endif
+#ifdef CONFIG_RTC_DRIVER
+# include "esp32_rtc_lowerhalf.h"
+#endif
+
#include "esp32-devkitc.h"
/****************************************************************************
@@ -375,6 +379,17 @@ int esp32_bringup(void)
}
#endif
+#ifdef CONFIG_RTC_DRIVER
+ /* Instantiate the ESP32 RTC driver */
+
+ ret = esp32_rtc_driverinit();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR,
+ "ERROR: Failed to Instantiate 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/xtensa/esp32/esp32-ethernet-kit/configs/rtc/defconfig b/boards/xtensa/esp32/esp32-ethernet-kit/configs/rtc/defconfig
new file mode 100644
index 0000000..ec05862
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-ethernet-kit/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_NSH_CMDPARMS is not set
+CONFIG_ARCH="xtensa"
+CONFIG_ARCH_BOARD="esp32-ethernet-kit"
+CONFIG_ARCH_BOARD_ESP32_ETHERNETKIT=y
+CONFIG_ARCH_CHIP="esp32"
+CONFIG_ARCH_CHIP_ESP32=y
+CONFIG_ARCH_CHIP_ESP32WROVER=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_XTENSA=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BUILTIN=y
+CONFIG_ESP32_RT_TIMER=y
+CONFIG_ESP32_UART0=y
+CONFIG_EXAMPLES_ALARM=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INTELHEX_BINARY=y
+CONFIG_MAX_TASKS=16
+CONFIG_MM_REGIONS=3
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=114688
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_RTC=y
+CONFIG_RTC_ALARM=y
+CONFIG_RTC_DRIVER=y
+CONFIG_RTC_NALARMS=2
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c
index 20b3309..e1875b5 100644
--- a/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/esp32-ethernet-kit/src/esp32_bringup.c
@@ -70,6 +70,10 @@
# include <nuttx/input/buttons.h>
#endif
+#ifdef CONFIG_RTC_DRIVER
+# include "esp32_rtc_lowerhalf.h"
+#endif
+
#include "esp32-ethernet-kit.h"
/****************************************************************************
@@ -271,6 +275,17 @@ int esp32_bringup(void)
}
#endif
+#ifdef CONFIG_RTC_DRIVER
+ /* Instantiate the ESP32 RTC driver */
+
+ ret = esp32_rtc_driverinit();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR,
+ "ERROR: Failed to Instantiate 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/xtensa/esp32/esp32-wrover-kit/configs/rtc/defconfig b/boards/xtensa/esp32/esp32-wrover-kit/configs/rtc/defconfig
new file mode 100644
index 0000000..4d87cf8
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-wrover-kit/configs/rtc/defconfig
@@ -0,0 +1,53 @@
+#
+# 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_ARCH_LEDS is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_CMDPARMS is not set
+CONFIG_ARCH="xtensa"
+CONFIG_ARCH_BOARD="esp32-wrover-kit"
+CONFIG_ARCH_BOARD_ESP32_WROVERKIT=y
+CONFIG_ARCH_CHIP="esp32"
+CONFIG_ARCH_CHIP_ESP32=y
+CONFIG_ARCH_CHIP_ESP32WROVER=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_XTENSA=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BUILTIN=y
+CONFIG_ESP32_RT_TIMER=y
+CONFIG_ESP32_UART0=y
+CONFIG_EXAMPLES_ALARM=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INTELHEX_BINARY=y
+CONFIG_MAX_TASKS=16
+CONFIG_MM_REGIONS=3
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=114688
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_RTC=y
+CONFIG_RTC_ALARM=y
+CONFIG_RTC_DRIVER=y
+CONFIG_RTC_NALARMS=2
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c
index 5012d2e..a9ee883 100644
--- a/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/esp32-wrover-kit/src/esp32_bringup.c
@@ -90,6 +90,10 @@
# include <nuttx/lcd/lcd_dev.h>
#endif
+#ifdef CONFIG_RTC_DRIVER
+# include "esp32_rtc_lowerhalf.h"
+#endif
+
#include "esp32-wrover-kit.h"
/****************************************************************************
@@ -358,6 +362,17 @@ int esp32_bringup(void)
}
#endif
+#ifdef CONFIG_RTC_DRIVER
+ /* Instantiate the ESP32 RTC driver */
+
+ ret = esp32_rtc_driverinit();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR,
+ "ERROR: Failed to Instantiate 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.