Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 103 additions & 11 deletions drivers/counter/counter_esp32_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@

#define DT_DRV_COMPAT espressif_esp32_rtc_timer

#include <soc/soc_caps.h>
#include <esp_rom_sys.h>

#if SOC_LP_TIMER_SUPPORTED
#include "hal/lp_timer_ll.h"
#else
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc.h"
#include <esp_rom_sys.h>
#include <hal/rtc_cntl_ll.h>
#endif

#include <zephyr/device.h>
#include <zephyr/drivers/counter.h>
Expand All @@ -26,6 +32,9 @@ static void counter_esp32_isr(void *arg);

struct counter_esp32_config {
struct counter_config_info counter_info;
#if SOC_LP_TIMER_SUPPORTED
lp_timer_dev_t *dev;
#endif
int irq_source;
int irq_priority;
int irq_flags;
Expand Down Expand Up @@ -84,9 +93,37 @@ static int counter_esp32_stop(const struct device *dev)

static int counter_esp32_get_value(const struct device *dev, uint32_t *ticks)
{
#if SOC_LP_TIMER_SUPPORTED
const struct counter_esp32_config *cfg = dev->config;

lp_timer_ll_counter_snapshot(cfg->dev);

*ticks = lp_timer_ll_get_counter_value_low(cfg->dev, 0);
#else
ARG_UNUSED(dev);

*ticks = (uint32_t) rtc_cntl_ll_get_rtc_time();
#endif

return 0;
}

static int counter_esp32_get_value_64(const struct device *dev, uint64_t *ticks)
{
#if SOC_LP_TIMER_SUPPORTED
const struct counter_esp32_config *cfg = dev->config;

lp_timer_ll_counter_snapshot(cfg->dev);

uint32_t lo = lp_timer_ll_get_counter_value_low(cfg->dev, 0);
uint32_t hi = lp_timer_ll_get_counter_value_high(cfg->dev, 0);

*ticks = ((uint64_t)hi << 32 | lo);
#else
ARG_UNUSED(dev);

*ticks = rtc_cntl_ll_get_rtc_time();
#endif

return 0;
}
Expand All @@ -95,9 +132,13 @@ static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id,
const struct counter_alarm_cfg *alarm_cfg)
{
ARG_UNUSED(chan_id);
#if SOC_LP_TIMER_SUPPORTED
const struct counter_esp32_config *cfg = dev->config;
lp_timer_dev_t *lp_timer = cfg->dev;
#endif
struct counter_esp32_data *data = dev->data;
uint32_t now;
uint32_t ticks = 0;
uint64_t now;
uint64_t ticks = 0;

#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32C2) || \
defined(CONFIG_SOC_SERIES_ESP32C3)
Expand All @@ -109,35 +150,63 @@ static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id,
data->alarm_cfg.callback = alarm_cfg->callback;
data->alarm_cfg.user_data = alarm_cfg->user_data;

counter_esp32_get_value(dev, &now);
counter_esp32_get_value_64(dev, &now);

ticks = (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) ? alarm_cfg->ticks
: now + alarm_cfg->ticks;
if (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) {
ticks = (now & ~0xFFFFFFFFULL) | alarm_cfg->ticks;
if (ticks < now) {
ticks += (1ULL << 32);
}
} else {
ticks = now + alarm_cfg->ticks;
}

data->ticks = (uint32_t)ticks;

#if SOC_LP_TIMER_SUPPORTED
lp_timer_ll_clear_alarm_intr_status(cfg->dev);
lp_timer_ll_set_alarm_target(cfg->dev, 0, ticks);
lp_timer_ll_set_target_enable(cfg->dev, 0, true);
lp_timer->int_en.alarm = 1;
#else
rtc_cntl_ll_set_wakeup_timer(ticks);

/* RTC main timer set alarm value */
CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, 0xffffffff);
CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, 0xFFFFFFFF);

/* RTC main timer set alarm enable */
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN);

/* RTC main timer interrupt enable */
SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_MAIN_TIMER_INT_ENA);
#endif

return 0;
}

static int counter_esp32_cancel_alarm(const struct device *dev, uint8_t chan_id)
{
ARG_UNUSED(dev);
ARG_UNUSED(chan_id);
struct counter_esp32_data *data = dev->data;

#if SOC_LP_TIMER_SUPPORTED
const struct counter_esp32_config *cfg = dev->config;
lp_timer_dev_t *lp_timer = cfg->dev;

lp_timer_ll_set_target_enable(cfg->dev, 0, false);
lp_timer->int_en.alarm = 0;
lp_timer_ll_clear_alarm_intr_status(cfg->dev);
#else
/* RTC main timer set alarm disable */
CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN);

/* RTC main timer interrupt disable */
/* RTC main timer interrupt disable, and clear interrupt flag */
REG_WRITE(RTC_CNTL_INT_ENA_REG, 0);
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_MAIN_TIMER_INT_CLR);
#endif

data->alarm_cfg.callback = NULL;
data->alarm_cfg.user_data = NULL;

return 0;
}
Expand All @@ -156,11 +225,18 @@ static int counter_esp32_set_top_value(const struct device *dev,

static uint32_t counter_esp32_get_pending_int(const struct device *dev)
{
#if SOC_LP_TIMER_SUPPORTED
const struct counter_esp32_config *cfg = dev->config;
lp_timer_dev_t *lp_timer = cfg->dev;

return lp_timer->int_st.alarm;
#else
ARG_UNUSED(dev);

uint32_t rc = READ_PERI_REG(RTC_CNTL_INT_ST_REG) & RTC_CNTL_MAIN_TIMER_INT_ST;

return (rc >> RTC_CNTL_MAIN_TIMER_INT_ST_S);
#endif
}

/*
Expand Down Expand Up @@ -190,6 +266,9 @@ static const struct counter_esp32_config counter_config = {
.flags = COUNTER_CONFIG_INFO_COUNT_UP,
.channels = 1
},
#if SOC_LP_TIMER_SUPPORTED
.dev = (lp_timer_dev_t *)DT_INST_REG_ADDR(0),
#endif
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
.irq_source = DT_INST_IRQ_BY_IDX(0, 0, irq),
.irq_priority = DT_INST_IRQ_BY_IDX(0, 0, priority),
Expand All @@ -200,6 +279,7 @@ static DEVICE_API(counter, rtc_timer_esp32_api) = {
.start = counter_esp32_start,
.stop = counter_esp32_stop,
.get_value = counter_esp32_get_value,
.get_value_64 = counter_esp32_get_value_64,
.set_alarm = counter_esp32_set_alarm,
.cancel_alarm = counter_esp32_cancel_alarm,
.set_top_value = counter_esp32_set_top_value,
Expand All @@ -212,18 +292,30 @@ static void counter_esp32_isr(void *arg)
{
const struct device *dev = (const struct device *)arg;
struct counter_esp32_data *data = dev->data;
counter_alarm_callback_t cb = data->alarm_cfg.callback;
void *cb_data = data->alarm_cfg.user_data;
uint32_t now;

#if SOC_LP_TIMER_SUPPORTED
const struct counter_esp32_config *cfg = dev->config;
lp_timer_dev_t *lp_timer = cfg->dev;

if (!lp_timer->int_st.alarm) {
return;
}
#else
uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG);

if (!(status & RTC_CNTL_MAIN_TIMER_INT_ST_M)) {
return;
}
#endif

counter_esp32_cancel_alarm(dev, 0);
counter_esp32_get_value(dev, &now);

if (data->alarm_cfg.callback) {
data->alarm_cfg.callback(dev, 0, now, data->alarm_cfg.user_data);
if (cb && (now > data->ticks)) {
cb(dev, 0, now, cb_data);
}
}

Expand Down
2 changes: 1 addition & 1 deletion dts/riscv/espressif/esp32c2/esp32c2_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@

rtc_timer: rtc_timer@60008004 {
reg = <0x60008004 0xC>;
compatible = "espressif,esp32-rtc_timer";
compatible = "espressif,esp32-rtc-timer";
clocks = <&clock ESP32_MODULE_MAX>;
interrupts = <RTC_CORE_INTR_SOURCE IRQ_DEFAULT_PRIORITY 0>;
interrupt-parent = <&intc>;
Expand Down
4 changes: 2 additions & 2 deletions dts/riscv/espressif/esp32c3/esp32c3_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@

rtc_timer: rtc_timer@60008004 {
reg = <0x60008004 0xC>;
compatible = "espressif,esp32-rtc_timer";
compatible = "espressif,esp32-rtc-timer";
clocks = <&clock ESP32_MODULE_MAX>;
interrupts = <RTC_CORE_INTR_SOURCE IRQ_DEFAULT_PRIORITY 0>;
interrupt-parent = <&intc>;
status = "okay";
status = "disabled";
};

flash: flash-controller@60002000 {
Expand Down
2 changes: 1 addition & 1 deletion dts/riscv/espressif/esp32c6/esp32c6_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
};

rtc_timer: rtc_timer@600b0c00 {
compatible = "espressif,esp32-rtc_timer";
compatible = "espressif,esp32-rtc-timer";
reg = <0x600B0C00 DT_SIZE_K(1)>;
clocks = <&clock ESP32_MODULE_MAX>;
interrupts = <LP_RTC_TIMER_INTR_SOURCE IRQ_DEFAULT_PRIORITY 0>;
Expand Down
2 changes: 1 addition & 1 deletion dts/riscv/espressif/esp32h2/esp32h2_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
};

rtc_timer: rtc_timer@600b0c00 {
compatible = "espressif,esp32-rtc_timer";
compatible = "espressif,esp32-rtc-timer";
reg = <0x600B0C00 DT_SIZE_K(1)>;
clocks = <&clock ESP32_MODULE_MAX>;
interrupts = <LP_RTC_TIMER_INTR_SOURCE IRQ_DEFAULT_PRIORITY 0>;
Expand Down
2 changes: 1 addition & 1 deletion dts/xtensa/espressif/esp32/esp32_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
clocks = <&clock ESP32_MODULE_MAX>;
interrupts = <RTC_CORE_INTR_SOURCE IRQ_DEFAULT_PRIORITY 0>;
interrupt-parent = <&intc>;
status = "okay";
status = "disabled";
};

flash: flash-controller@3ff42000 {
Expand Down
4 changes: 2 additions & 2 deletions dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,11 @@

rtc_timer: rtc_timer@3f408004 {
reg = <0x3f408004 0xC>;
compatible = "espressif,esp32-rtc_timer";
compatible = "espressif,esp32-rtc-timer";
clocks = <&clock ESP32_MODULE_MAX>;
interrupts = <RTC_CORE_INTR_SOURCE IRQ_DEFAULT_PRIORITY 0>;
interrupt-parent = <&intc>;
status = "okay";
status = "disabled";
};

flash: flash-controller@3f402000 {
Expand Down
2 changes: 1 addition & 1 deletion dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@

rtc_timer: rtc_timer@60008004 {
reg = <0x60008004 0xC>;
compatible = "espressif,esp32-rtc_timer";
compatible = "espressif,esp32-rtc-timer";
clocks = <&clock ESP32_MODULE_MAX>;
interrupts = <RTC_CORE_INTR_SOURCE IRQ_DEFAULT_PRIORITY 0>;
interrupt-parent = <&intc>;
Expand Down
9 changes: 9 additions & 0 deletions tests/drivers/counter/counter_basic_api/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,13 @@ config TEST_DRIVER_COUNTER_MCUX_LPC_RTC_HIGHRES
help
tests the nxp_lpc_rtc_highres compatible driver

config TEST_DRIVER_COUNTER_TOLERANCE
int "Counter ticks tolerance (%)"
default 10
help
Error tolerance used in counter driver tests.
A number of ticks is estimated and counter is tested against systimer,
to verify accuracy. Tolerance is a percentage of deviation allowed for
the number of expected ticks.

source "Kconfig.zephyr"
10 changes: 10 additions & 0 deletions tests/drivers/counter/counter_basic_api/socs/esp32_procpu.overlay
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/

&timer0 {
status = "okay";
counter {
status = "okay";
};
};

&rtc_timer {
status = "okay";
};

&clock {
slow-clk-src = <ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256>;
};
6 changes: 6 additions & 0 deletions tests/drivers/counter/counter_basic_api/socs/esp32c2.overlay
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/

&timer0 {
status = "okay";
counter {
Expand Down
10 changes: 10 additions & 0 deletions tests/drivers/counter/counter_basic_api/socs/esp32c3.overlay
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/

&timer0 {
status = "okay";
counter {
status = "okay";
};
};

&rtc_timer {
status = "okay";
};

&clock {
slow-clk-src = <ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256>;
};
10 changes: 10 additions & 0 deletions tests/drivers/counter/counter_basic_api/socs/esp32c3_usb.overlay
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/

&timer0 {
status = "okay";
counter {
status = "okay";
};
};

&rtc_timer {
status = "okay";
};

&clock {
slow-clk-src = <ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256>;
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/*
* Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/

&timer0 {
status = "okay";
counter {
Expand All @@ -11,3 +17,7 @@
status = "okay";
};
};

&rtc_timer {
status = "okay";
};
Loading