risc-v/esp32c3: Support ESP32-C3 auto-sleep
This commit is contained in:
parent
e44ec9e48e
commit
9a99d813fa
@ -657,6 +657,34 @@ config ESP32C3_WIFI_STA_DISCONNECT_PM
|
||||
Select this option to enable power management for station when disconnected.
|
||||
Chip will do modem-sleep when RF module is not in use anymore.
|
||||
|
||||
config EXAMPLE_WIFI_LISTEN_INTERVAL
|
||||
int "Wi-Fi listen interval"
|
||||
default 3
|
||||
---help---
|
||||
Interval for station to listen to beacon from AP. The unit of listen interval is one beacon interval.
|
||||
For example, if beacon interval is 100 ms and listen interval is 3, the interval for station to listen
|
||||
to beacon is 300 ms.
|
||||
|
||||
choice EXAMPLE_POWER_SAVE_MODE
|
||||
prompt "Power save mode"
|
||||
default EXAMPLE_POWER_SAVE_NONE
|
||||
---help---
|
||||
Power save mode for the ESP32-C3 to use. Modem sleep mode includes minimum and maximum power save modes.
|
||||
In minimum power save mode, station wakes up every DTIM to receive beacon. Broadcast data will not be
|
||||
lost because it is transmitted after DTIM. However, it can not save much more power if DTIM is short
|
||||
for DTIM is determined by AP.
|
||||
In maximum power save mode, station wakes up every listen interval to receive beacon. Broadcast data
|
||||
may be lost because station may be in sleep state at DTIM time. If listen interval is longer, more power
|
||||
is saved but broadcast data is more easy to lose.
|
||||
|
||||
config EXAMPLE_POWER_SAVE_NONE
|
||||
bool "none"
|
||||
config EXAMPLE_POWER_SAVE_MIN_MODEM
|
||||
bool "minimum modem"
|
||||
config EXAMPLE_POWER_SAVE_MAX_MODEM
|
||||
bool "maximum modem"
|
||||
endchoice
|
||||
|
||||
endmenu # ESP32C3_WIRELESS
|
||||
|
||||
menu "SPI Flash configuration"
|
||||
@ -716,4 +744,20 @@ config ESP32C3_DMA_M2M_TEST_BUFSIZE
|
||||
|
||||
endmenu # GDMA Configuration
|
||||
|
||||
config ESP32C3_AUTO_SLEEP
|
||||
bool "Auto-sleep"
|
||||
default n
|
||||
select PM
|
||||
select ESP32C3_RT_TIMER
|
||||
select ESP32C3_TIMER0
|
||||
select ESP32C3_TICKLESS
|
||||
---help---
|
||||
Enable ESP32-C3 Auto-sleep
|
||||
|
||||
config ESP32C3_TICKLESS
|
||||
bool "Enable ESP32-C3 tickless OS"
|
||||
default n
|
||||
select ARCH_HAVE_TICKLESS
|
||||
select SCHED_TICKLESS
|
||||
|
||||
endif # ARCH_CHIP_ESP32C3
|
||||
|
@ -46,11 +46,17 @@ endif
|
||||
# Specify our C code within this directory to be included
|
||||
|
||||
CHIP_CSRCS = esp32c3_allocateheap.c esp32c3_start.c esp32c3_idle.c
|
||||
CHIP_CSRCS += esp32c3_irq.c esp32c3_timerisr.c
|
||||
CHIP_CSRCS += esp32c3_irq.c
|
||||
CHIP_CSRCS += esp32c3_clockconfig.c esp32c3_gpio.c
|
||||
CHIP_CSRCS += esp32c3_lowputc.c
|
||||
CHIP_CSRCS += esp32c3_systemreset.c esp32c3_resetcause.c
|
||||
|
||||
ifeq ($(CONFIG_SCHED_TICKLESS),y)
|
||||
CHIP_CSRCS += esp32c3_tickless.c
|
||||
else
|
||||
CHIP_CSRCS += esp32c3_timerisr.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ESP32C3_UART),y)
|
||||
CHIP_CSRCS += esp32c3_serial.c
|
||||
endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
@ -30,6 +31,14 @@
|
||||
#include "esp32c3.h"
|
||||
#include "esp32c3_pm.h"
|
||||
|
||||
#ifdef CONFIG_ESP32C3_RT_TIMER
|
||||
#include "esp32c3_rt_timer.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
#include "esp32c3_tickless.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@ -58,6 +67,14 @@
|
||||
#endif
|
||||
|
||||
#define PM_IDLE_DOMAIN 0 /* Revisit */
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define EXPECTED_IDLE_TIME_US (800)
|
||||
#define EARLY_WAKEUP_US (200)
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@ -75,9 +92,57 @@
|
||||
#ifdef CONFIG_PM
|
||||
static void up_idlepm(void)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_AUTO_SLEEP
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
if (esp32c3_pm_lockstatus() == 0 &&
|
||||
(esp32c3_should_skip_light_sleep() == false))
|
||||
{
|
||||
uint64_t os_start_us;
|
||||
uint64_t os_end_us;
|
||||
uint64_t os_step_us;
|
||||
uint64_t hw_start_us;
|
||||
uint64_t hw_end_us;
|
||||
uint64_t hw_step_us;
|
||||
uint64_t rtc_diff_us;
|
||||
struct timespec ts;
|
||||
uint64_t os_idle_us = up_get_idletime();
|
||||
uint64_t hw_idle_us = rt_timer_get_alarm();
|
||||
uint64_t sleep_us = MIN(os_idle_us, hw_idle_us);
|
||||
if (sleep_us > EXPECTED_IDLE_TIME_US)
|
||||
{
|
||||
esp32c3_sleep_enable_rtc_timer_wakeup(sleep_us - EARLY_WAKEUP_US);
|
||||
up_timer_gettime(&ts);
|
||||
os_start_us = (ts.tv_sec * USEC_PER_SEC +
|
||||
ts.tv_nsec / NSEC_PER_USEC);
|
||||
hw_start_us = rt_timer_time_us();
|
||||
|
||||
esp32c3_light_sleep_start(&rtc_diff_us);
|
||||
|
||||
hw_end_us = rt_timer_time_us();
|
||||
up_timer_gettime(&ts);
|
||||
os_end_us = (ts.tv_sec * USEC_PER_SEC +
|
||||
ts.tv_nsec / NSEC_PER_USEC);
|
||||
hw_step_us = rtc_diff_us - (hw_end_us - hw_start_us);
|
||||
os_step_us = rtc_diff_us - (os_end_us - os_start_us);
|
||||
DEBUGASSERT(hw_step_us > 0);
|
||||
DEBUGASSERT(os_step_us > 0);
|
||||
|
||||
/* Adjust current RT timer by a certain value. */
|
||||
|
||||
rt_timer_calibration(hw_step_us);
|
||||
|
||||
/* Adjust system time by a certain value. */
|
||||
|
||||
up_step_idletime((uint32_t)os_step_us);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
#else /* CONFIG_ESP32C3_AUTO_SLEEP */
|
||||
static enum pm_state_e oldstate = PM_NORMAL;
|
||||
enum pm_state_e newstate;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Decide, which power saving level can be obtained */
|
||||
@ -159,6 +224,7 @@ static void up_idlepm(void)
|
||||
pm_changestate(PM_IDLE_DOMAIN, PM_NORMAL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
# define up_idlepm()
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
@ -43,12 +44,21 @@
|
||||
#include "hardware/esp32c3_soc.h"
|
||||
#include "hardware/esp32c3_uart.h"
|
||||
#include "hardware/esp32c3_gpio.h"
|
||||
#include "hardware/apb_ctrl_reg.h"
|
||||
|
||||
#include "esp32c3_attr.h"
|
||||
#include "esp32c3_rtc.h"
|
||||
#include "esp32c3_clockconfig.h"
|
||||
#include "esp32c3_pm.h"
|
||||
|
||||
#ifdef CONFIG_ESP32C3_RT_TIMER
|
||||
#include "esp32c3_rt_timer.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
#include "esp32c3_tickless.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@ -99,6 +109,9 @@
|
||||
#define RTC_USB_TRIG_EN BIT(14)
|
||||
#define RTC_BROWNOUT_DET_TRIG_EN BIT(16)
|
||||
|
||||
#define PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO (1)
|
||||
#define PERIPH_SKIP_SLEEP_NO (1)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -207,28 +220,31 @@ struct esp32c3_rtc_vddsdio_config_s
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint32_t esp32c3_periph_ll_get_rst_en_mask
|
||||
static inline uint32_t IRAM_ATTR esp32c3_periph_ll_get_rst_en_mask
|
||||
(enum esp32c3_periph_module_e periph, bool enable);
|
||||
static uint32_t IRAM_ATTR esp32c3_periph_ll_get_rst_en_reg(
|
||||
enum esp32c3_periph_module_e periph);
|
||||
static uint32_t IRAM_ATTR esp32c3_periph_ll_get_clk_en_reg(
|
||||
enum esp32c3_periph_module_e periph);
|
||||
static inline uint32_t esp32c3_periph_ll_get_clk_en_mask(
|
||||
static inline uint32_t IRAM_ATTR esp32c3_periph_ll_get_clk_en_mask(
|
||||
enum esp32c3_periph_module_e periph);
|
||||
static inline bool IRAM_ATTR esp32c3_periph_ll_periph_enabled(
|
||||
enum esp32c3_periph_module_e periph);
|
||||
static inline void esp32c3_uart_tx_wait_idle(uint8_t uart_no);
|
||||
static inline void IRAM_ATTR esp32c3_uart_tx_wait_idle(uint8_t uart_no);
|
||||
static void IRAM_ATTR esp32c3_flush_uarts(void);
|
||||
static void IRAM_ATTR esp32c3_suspend_uarts(void);
|
||||
static void IRAM_ATTR esp32c3_resume_uarts(void);
|
||||
static void esp32c3_timer_wakeup_prepare(void);
|
||||
static uint32_t esp32c3_get_power_down_flags(void);
|
||||
static void IRAM_ATTR esp32c3_timer_wakeup_prepare(void);
|
||||
static uint32_t IRAM_ATTR esp32c3_get_power_down_flags(void);
|
||||
static void IRAM_ATTR esp32c3_set_vddsdio_config(
|
||||
struct esp32c3_rtc_vddsdio_config_s config);
|
||||
static int IRAM_ATTR esp32c3_get_vddsdio_config(
|
||||
struct esp32c3_rtc_vddsdio_config_s *config);
|
||||
static int IRAM_ATTR esp32c3_light_sleep_inner(uint32_t pd_flags,
|
||||
uint32_t time_us, struct esp32c3_rtc_vddsdio_config_s config);
|
||||
static void esp32c3_periph_module_enable(
|
||||
enum esp32c3_periph_module_e periph);
|
||||
static void IRAM_ATTR esp32c3_perip_clk_init(void);
|
||||
static int IRAM_ATTR esp32c3_sleep_start(uint32_t pd_flags);
|
||||
|
||||
/****************************************************************************
|
||||
@ -247,6 +263,22 @@ static struct esp32c3_sleep_config_s s_config =
|
||||
.wakeup_triggers = 0
|
||||
};
|
||||
|
||||
static _Atomic uint32_t pm_wakelock = 0;
|
||||
|
||||
/* Inform peripherals of light sleep wakeup overhead time */
|
||||
|
||||
inform_out_sleep_overhead_cb_t
|
||||
g_periph_inform_out_sleep_overhead_cb[PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO];
|
||||
|
||||
/* Indicates if light sleep shoule be skipped by peripherals. */
|
||||
|
||||
skip_light_sleep_cb_t g_periph_skip_sleep_cb[PERIPH_SKIP_SLEEP_NO];
|
||||
|
||||
static uint8_t ref_counts[PERIPH_MODULE_MAX] =
|
||||
{
|
||||
0
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -276,7 +308,7 @@ extern void esp_rom_delay_us(uint32_t us);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint32_t esp32c3_periph_ll_get_rst_en_mask
|
||||
static inline uint32_t IRAM_ATTR esp32c3_periph_ll_get_rst_en_mask
|
||||
(enum esp32c3_periph_module_e periph, bool enable)
|
||||
{
|
||||
switch (periph)
|
||||
@ -480,7 +512,7 @@ static uint32_t IRAM_ATTR esp32c3_periph_ll_get_clk_en_reg(
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint32_t esp32c3_periph_ll_get_clk_en_mask(
|
||||
static inline uint32_t IRAM_ATTR esp32c3_periph_ll_get_clk_en_mask(
|
||||
enum esp32c3_periph_module_e periph)
|
||||
{
|
||||
switch (periph)
|
||||
@ -725,7 +757,7 @@ static void IRAM_ATTR esp32c3_resume_uarts(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t esp32c3_get_power_down_flags(void)
|
||||
static uint32_t IRAM_ATTR esp32c3_get_power_down_flags(void)
|
||||
{
|
||||
uint32_t pd_flags = 0;
|
||||
|
||||
@ -1018,15 +1050,328 @@ static int IRAM_ATTR esp32c3_light_sleep_inner(uint32_t pd_flags,
|
||||
return err;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_periph_module_enable
|
||||
*
|
||||
* Description:
|
||||
* Enable peripheral module
|
||||
*
|
||||
* Input Parameters:
|
||||
* periph - Periph module (one of enum esp32c3_periph_module_e values)
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void esp32c3_periph_module_enable(enum esp32c3_periph_module_e periph)
|
||||
{
|
||||
irqstate_t flags = enter_critical_section();
|
||||
|
||||
assert(periph < PERIPH_MODULE_MAX);
|
||||
if (ref_counts[periph] == 0)
|
||||
{
|
||||
modifyreg32(esp32c3_periph_ll_get_clk_en_reg(periph), 0,
|
||||
esp32c3_periph_ll_get_clk_en_mask(periph));
|
||||
modifyreg32(esp32c3_periph_ll_get_rst_en_reg(periph),
|
||||
esp32c3_periph_ll_get_rst_en_mask(periph, true), 0);
|
||||
}
|
||||
|
||||
ref_counts[periph]++;
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_perip_clk_init
|
||||
*
|
||||
* Description:
|
||||
* This function disables clock of useless peripherals when cpu starts.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void IRAM_ATTR esp32c3_perip_clk_init(void)
|
||||
{
|
||||
uint32_t common_perip_clk1 = 0;
|
||||
|
||||
/* Reset the communication peripherals like I2C, SPI,
|
||||
* UART, I2S and bring them to known state.
|
||||
*/
|
||||
|
||||
uint32_t common_perip_clk = SYSTEM_WDG_CLK_EN |
|
||||
SYSTEM_I2S0_CLK_EN |
|
||||
SYSTEM_UART1_CLK_EN |
|
||||
SYSTEM_UART2_CLK_EN |
|
||||
SYSTEM_SPI2_CLK_EN |
|
||||
SYSTEM_I2C_EXT0_CLK_EN |
|
||||
SYSTEM_UHCI0_CLK_EN |
|
||||
SYSTEM_RMT_CLK_EN |
|
||||
SYSTEM_LEDC_CLK_EN |
|
||||
SYSTEM_UHCI1_CLK_EN |
|
||||
SYSTEM_TIMERGROUP1_CLK_EN |
|
||||
SYSTEM_SPI3_CLK_EN |
|
||||
SYSTEM_SPI4_CLK_EN |
|
||||
SYSTEM_I2C_EXT1_CLK_EN |
|
||||
SYSTEM_TWAI_CLK_EN |
|
||||
SYSTEM_I2S1_CLK_EN |
|
||||
SYSTEM_SPI2_DMA_CLK_EN |
|
||||
SYSTEM_SPI3_DMA_CLK_EN;
|
||||
|
||||
uint32_t hwcrypto_perip_clk = SYSTEM_CRYPTO_AES_CLK_EN |
|
||||
SYSTEM_CRYPTO_SHA_CLK_EN |
|
||||
SYSTEM_CRYPTO_RSA_CLK_EN;
|
||||
uint32_t wifi_bt_sdio_clk = SYSTEM_WIFI_CLK_WIFI_EN |
|
||||
SYSTEM_WIFI_CLK_BT_EN_M |
|
||||
SYSTEM_WIFI_CLK_UNUSED_BIT5 |
|
||||
SYSTEM_WIFI_CLK_UNUSED_BIT12;
|
||||
|
||||
/* Disable some peripheral clocks. */
|
||||
|
||||
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk, 0);
|
||||
modifyreg32(SYSTEM_PERIP_RST_EN0_REG, 0, common_perip_clk);
|
||||
|
||||
modifyreg32(SYSTEM_PERIP_CLK_EN1_REG, common_perip_clk1, 0);
|
||||
modifyreg32(SYSTEM_PERIP_RST_EN1_REG, 0, common_perip_clk1);
|
||||
|
||||
/* Disable hardware crypto clocks. */
|
||||
|
||||
modifyreg32(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk, 0);
|
||||
modifyreg32(SYSTEM_PERIP_RST_EN1_REG, 0, hwcrypto_perip_clk);
|
||||
|
||||
/* Disable WiFi/BT/SDIO clocks. */
|
||||
|
||||
modifyreg32(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk, 0);
|
||||
modifyreg32(SYSTEM_WIFI_CLK_EN_REG, 0, SYSTEM_WIFI_CLK_EN);
|
||||
|
||||
/* Set WiFi light sleep clock source to RTC slow clock */
|
||||
|
||||
REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0);
|
||||
modifyreg32(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M,
|
||||
SYSTEM_LPCLK_SEL_RTC_SLOW);
|
||||
|
||||
/* Enable RNG clock. */
|
||||
|
||||
esp32c3_periph_module_enable(PERIPH_RNG_MODULE);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_periph_should_skip_sleep
|
||||
*
|
||||
* Description:
|
||||
* Indicates if light sleep shoule be skipped by peripherals
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* True is returned on success. Otherwise false.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline bool IRAM_ATTR esp32c3_periph_should_skip_sleep(void)
|
||||
{
|
||||
for (int i = 0; i < PERIPH_SKIP_SLEEP_NO; i++)
|
||||
{
|
||||
if (g_periph_skip_sleep_cb[i])
|
||||
{
|
||||
if (g_periph_skip_sleep_cb[i]() == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_sleep_enable_timer_wakeup
|
||||
* Name: esp32c3_pm_register_skip_sleep_callback
|
||||
*
|
||||
* Description:
|
||||
* Configure wake-up interval
|
||||
* Unregister callback function of skipping light sleep.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_pm_register_skip_sleep_callback(skip_light_sleep_cb_t cb)
|
||||
{
|
||||
for (int i = 0; i < PERIPH_SKIP_SLEEP_NO; i++)
|
||||
{
|
||||
if (g_periph_skip_sleep_cb[i] == cb)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
else if (g_periph_skip_sleep_cb[i] == NULL)
|
||||
{
|
||||
g_periph_skip_sleep_cb[i] = cb;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_unregister_skip_sleep_callback
|
||||
*
|
||||
* Description:
|
||||
* Register callback function of skipping light sleep.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_pm_unregister_skip_sleep_callback(skip_light_sleep_cb_t cb)
|
||||
{
|
||||
for (int i = 0; i < PERIPH_SKIP_SLEEP_NO; i++)
|
||||
{
|
||||
if (g_periph_skip_sleep_cb[i] == cb)
|
||||
{
|
||||
g_periph_skip_sleep_cb[i] = NULL;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_should_skip_light_sleep
|
||||
*
|
||||
* Description:
|
||||
* Indicates if light sleep shoule be skipped.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* True is returned on success. Otherwise false.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool IRAM_ATTR esp32c3_should_skip_light_sleep(void)
|
||||
{
|
||||
if (esp32c3_periph_should_skip_sleep() == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_register_inform_out_sleep_overhead_callback
|
||||
*
|
||||
* Description:
|
||||
* Register informing peripherals of light sleep wakeup overhead time
|
||||
* callback function.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cb - callback function
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_pm_register_inform_out_sleep_overhead_callback(
|
||||
inform_out_sleep_overhead_cb_t cb)
|
||||
{
|
||||
for (int i = 0; i < PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO; i++)
|
||||
{
|
||||
if (g_periph_inform_out_sleep_overhead_cb[i] == cb)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
else if (g_periph_inform_out_sleep_overhead_cb[i] == NULL)
|
||||
{
|
||||
g_periph_inform_out_sleep_overhead_cb[i] = cb;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_unregister_inform_out_sleep_overhead_callback
|
||||
*
|
||||
* Description:
|
||||
* Unregister informing peripherals of light sleep wakeup overhead time
|
||||
* callback function.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cb - callback function
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_pm_unregister_inform_out_sleep_overhead_callback(
|
||||
inform_out_sleep_overhead_cb_t cb)
|
||||
{
|
||||
for (int i = 0; i < PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO; i++)
|
||||
{
|
||||
if (g_periph_inform_out_sleep_overhead_cb[i] == cb)
|
||||
{
|
||||
g_periph_inform_out_sleep_overhead_cb[i] = NULL;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_periph_inform_out_sleep_overhead
|
||||
*
|
||||
* Description:
|
||||
* Inform peripherals of light sleep wakeup overhead time
|
||||
*
|
||||
* Input Parameters:
|
||||
* us - light sleep wakeup overhead time
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void IRAM_ATTR esp32c3_periph_inform_out_sleep_overhead(uint32_t us)
|
||||
{
|
||||
for (int i = 0; i < PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO; i++)
|
||||
{
|
||||
if (g_periph_inform_out_sleep_overhead_cb[i])
|
||||
{
|
||||
g_periph_inform_out_sleep_overhead_cb[i](us);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_sleep_enable_rtc_timer_wakeup
|
||||
*
|
||||
* Description:
|
||||
* Configure RTC TIMER wake-up interval
|
||||
*
|
||||
* Input Parameters:
|
||||
* time_in_us - Configure wake-up time interval
|
||||
@ -1036,12 +1381,31 @@ static int IRAM_ATTR esp32c3_light_sleep_inner(uint32_t pd_flags,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32c3_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
||||
void IRAM_ATTR esp32c3_sleep_enable_rtc_timer_wakeup(uint64_t time_in_us)
|
||||
{
|
||||
s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN;
|
||||
s_config.sleep_duration = time_in_us;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_sleep_enable_wifi_wakeup
|
||||
*
|
||||
* Description:
|
||||
* Configure Wi-Fi wake-up source
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32c3_sleep_enable_wifi_wakeup(void)
|
||||
{
|
||||
s_config.wakeup_triggers |= RTC_WIFI_TRIG_EN;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_light_sleep_start
|
||||
*
|
||||
@ -1049,14 +1413,14 @@ void esp32c3_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
||||
* Enter light sleep mode
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
* sleep_time - Actual sleep time
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 is returned on success or a negated errno value is returned
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_light_sleep_start(void)
|
||||
int IRAM_ATTR esp32c3_light_sleep_start(uint64_t *sleep_time)
|
||||
{
|
||||
int ret = OK;
|
||||
irqstate_t flags;
|
||||
@ -1141,12 +1505,22 @@ int esp32c3_light_sleep_start(void)
|
||||
}
|
||||
}
|
||||
|
||||
esp32c3_periph_inform_out_sleep_overhead(
|
||||
s_config.sleep_time_adjustment - sleep_time_overhead_in);
|
||||
|
||||
esp32c3_get_vddsdio_config(&vddsdio_config);
|
||||
|
||||
/* Enter sleep, then wait for flash to be ready on wakeup */
|
||||
|
||||
ret = esp32c3_light_sleep_inner(pd_flags, flash_enable_time_us,
|
||||
vddsdio_config);
|
||||
|
||||
if (sleep_time != NULL)
|
||||
{
|
||||
*sleep_time = esp32c3_rtc_time_slowclk_to_us(esp32c3_rtc_time_get() -
|
||||
s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period);
|
||||
}
|
||||
|
||||
s_config.sleep_time_overhead_out = (esp32c3_cpu_cycle_count() -
|
||||
s_config.ccount_ticks_record) / (esp32c3_clk_cpu_freq() / 1000000ULL);
|
||||
|
||||
@ -1175,6 +1549,7 @@ void esp32c3_pminit(void)
|
||||
|
||||
esp32c3_rtc_init();
|
||||
esp32c3_rtc_clk_set();
|
||||
esp32c3_perip_clk_init();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1193,11 +1568,41 @@ void esp32c3_pminit(void)
|
||||
|
||||
void esp32c3_pmstandby(uint64_t time_in_us)
|
||||
{
|
||||
uint64_t rtc_diff_us;
|
||||
#ifdef CONFIG_ESP32C3_RT_TIMER
|
||||
uint64_t hw_start_us;
|
||||
uint64_t hw_end_us;
|
||||
uint64_t hw_diff_us;
|
||||
#endif
|
||||
|
||||
/* don't power down XTAL — powering it up takes different time on. */
|
||||
|
||||
fflush(stdout);
|
||||
esp32c3_sleep_enable_timer_wakeup(time_in_us);
|
||||
esp32c3_light_sleep_start();
|
||||
esp32c3_sleep_enable_rtc_timer_wakeup(time_in_us);
|
||||
#ifdef CONFIG_ESP32C3_RT_TIMER
|
||||
/* Get rt-timer timestamp before entering sleep */
|
||||
|
||||
hw_start_us = rt_timer_time_us();
|
||||
#endif
|
||||
|
||||
esp32c3_light_sleep_start(&rtc_diff_us);
|
||||
|
||||
#ifdef CONFIG_ESP32C3_RT_TIMER
|
||||
/* Get rt-timer timestamp after waking up from sleep */
|
||||
|
||||
hw_end_us = rt_timer_time_us();
|
||||
hw_diff_us = hw_end_us - hw_start_us;
|
||||
DEBUGASSERT(rtc_diff_us > hw_diff_us);
|
||||
|
||||
rt_timer_calibration(rtc_diff_us - hw_diff_us);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
up_step_idletime((uint32_t)time_in_us);
|
||||
#endif
|
||||
|
||||
pwrinfo("Returned from auto-sleep, slept for %" PRIu32 " ms\n",
|
||||
(uint32_t)(rtc_diff_us) / 1000);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1259,8 +1664,47 @@ void IRAM_ATTR esp32c3_deep_sleep_start(void)
|
||||
void esp32c3_pmsleep(uint64_t time_in_us)
|
||||
{
|
||||
fflush(stdout);
|
||||
esp32c3_sleep_enable_timer_wakeup(time_in_us);
|
||||
esp32c3_sleep_enable_rtc_timer_wakeup(time_in_us);
|
||||
esp32c3_deep_sleep_start();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_lockacquire
|
||||
*
|
||||
* Description:
|
||||
* Take a power management lock
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void IRAM_ATTR esp32c3_pm_lockacquire(void)
|
||||
{
|
||||
++pm_wakelock;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_lockrelease
|
||||
*
|
||||
* Description:
|
||||
* Release the lock taken using esp32c3_pm_lockacquire.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void IRAM_ATTR esp32c3_pm_lockrelease(void)
|
||||
{
|
||||
--pm_wakelock;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_lockstatus
|
||||
*
|
||||
* Description:
|
||||
* Return power management lock status.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t IRAM_ATTR esp32c3_pm_lockstatus(void)
|
||||
{
|
||||
return pm_wakelock;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
@ -30,6 +30,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@ -44,12 +45,26 @@ extern "C"
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Callback function type for peripherals to
|
||||
* know light sleep wakeup overhead.
|
||||
*/
|
||||
|
||||
typedef void (*inform_out_sleep_overhead_cb_t)(uint32_t);
|
||||
|
||||
/* Callback function type for peripherals to skip light sleep. */
|
||||
|
||||
typedef bool (*skip_light_sleep_cb_t)(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_sleep_enable_timer_wakeup
|
||||
* Name: esp32c3_sleep_enable_rtc_timer_wakeup
|
||||
*
|
||||
* Description:
|
||||
* Configure wake-up interval
|
||||
@ -62,23 +77,23 @@ extern "C"
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32c3_sleep_enable_timer_wakeup(uint64_t time_in_us);
|
||||
void esp32c3_sleep_enable_rtc_timer_wakeup(uint64_t time_in_us);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_light_sleep_start
|
||||
*
|
||||
* Description:
|
||||
* Enter sleep mode
|
||||
* Enter light sleep mode
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
* sleep_time - Actual sleep time
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 is returned on success or a negated errno value is returned
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_light_sleep_start(void);
|
||||
int esp32c3_light_sleep_start(uint64_t *sleep_time);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pminit
|
||||
@ -144,6 +159,136 @@ void esp32c3_deep_sleep_start(void);
|
||||
|
||||
void esp32c3_pmsleep(uint64_t time_in_us);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_lockacquire
|
||||
*
|
||||
* Description:
|
||||
* Take a power management lock
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32c3_pm_lockacquire(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_lockrelease
|
||||
*
|
||||
* Description:
|
||||
* Release the lock taken using esp32c3_pm_lockacquire.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32c3_pm_lockrelease(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_lockstatus
|
||||
*
|
||||
* Description:
|
||||
* Return power management lock status.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t esp32c3_pm_lockstatus(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_sleep_enable_wifi_wakeup
|
||||
*
|
||||
* Description:
|
||||
* Configure Wi-Fi wake-up source
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32c3_sleep_enable_wifi_wakeup(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_should_skip_light_sleep
|
||||
*
|
||||
* Description:
|
||||
* Indicates if light sleep shoule be skipped.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* True is returned on success. Otherwise false.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool esp32c3_should_skip_light_sleep(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_register_inform_out_sleep_overhead_callback
|
||||
*
|
||||
* Description:
|
||||
* Register informing peripherals of light sleep wakeup overhead time
|
||||
* callback function.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cb - callback function
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_pm_register_inform_out_sleep_overhead_callback(
|
||||
inform_out_sleep_overhead_cb_t cb);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_unregister_inform_out_sleep_overhead_callback
|
||||
*
|
||||
* Description:
|
||||
* Unregister informing peripherals of light sleep wakeup overhead time
|
||||
* callback function.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cb - callback function
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_pm_unregister_inform_out_sleep_overhead_callback(
|
||||
inform_out_sleep_overhead_cb_t cb);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_register_skip_sleep_callback
|
||||
*
|
||||
* Description:
|
||||
* Unregister callback function of skipping light sleep.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_pm_register_skip_sleep_callback(skip_light_sleep_cb_t cb);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_pm_unregister_skip_sleep_callback
|
||||
*
|
||||
* Description:
|
||||
* Register callback function of skipping light sleep.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32c3_pm_unregister_skip_sleep_callback(skip_light_sleep_cb_t cb);
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "hardware/esp32c3_soc.h"
|
||||
#include "esp32c3_tim.h"
|
||||
#include "esp32c3_rt_timer.h"
|
||||
#include "esp32c3_attr.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@ -590,7 +591,7 @@ void rt_timer_delete(FAR struct rt_timer_s *timer)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint64_t rt_timer_time_us(void)
|
||||
uint64_t IRAM_ATTR rt_timer_time_us(void)
|
||||
{
|
||||
uint64_t counter;
|
||||
struct esp32c3_tim_dev_s *tim = s_esp32c3_tim_dev;
|
||||
@ -600,6 +601,74 @@ uint64_t rt_timer_time_us(void)
|
||||
return counter;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rt_timer_get_alarm
|
||||
*
|
||||
* Description:
|
||||
* Get the timestamp when the next timeout is expected to occur.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Timestamp of the nearest timer event, in microseconds.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint64_t IRAM_ATTR rt_timer_get_alarm(void)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint64_t counter;
|
||||
struct esp32c3_tim_dev_s *tim = s_esp32c3_tim_dev;
|
||||
uint64_t alarm_value = 0;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
ESP32C3_TIM_GETCTR(tim, &counter);
|
||||
ESP32C3_TIM_GETALRVL(tim, &alarm_value);
|
||||
|
||||
if (alarm_value <= counter)
|
||||
{
|
||||
alarm_value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
alarm_value -= counter;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return alarm_value;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rt_timer_calibration
|
||||
*
|
||||
* Description:
|
||||
* Adjust current RT timer by a certain value.
|
||||
*
|
||||
* Input Parameters:
|
||||
* time_us - adjustment to apply to RT timer, in microseconds
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void IRAM_ATTR rt_timer_calibration(uint64_t time_us)
|
||||
{
|
||||
uint64_t counter;
|
||||
struct esp32c3_tim_dev_s *tim = s_esp32c3_tim_dev;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
ESP32C3_TIM_GETCTR(tim, &counter);
|
||||
counter += time_us;
|
||||
ESP32C3_TIM_SETCTR(tim, counter);
|
||||
ESP32C3_TIM_RLD_NOW(tim);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_rt_timer_init
|
||||
*
|
||||
|
@ -166,6 +166,38 @@ void rt_timer_delete(struct rt_timer_s *timer);
|
||||
|
||||
uint64_t rt_timer_time_us(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rt_timer_get_alarm
|
||||
*
|
||||
* Description:
|
||||
* Get the timestamp when the next timeout is expected to occur.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Timestamp of the nearest timer event, in microseconds.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint64_t rt_timer_get_alarm(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rt_timer_calibration
|
||||
*
|
||||
* Description:
|
||||
* Adjust current RT timer by a certain value.
|
||||
*
|
||||
* Input Parameters:
|
||||
* time_us - adjustment to apply to RT timer, in microseconds
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void rt_timer_calibration(uint64_t time_us);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_rt_timer_init
|
||||
*
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "hardware/esp32c3_rtccntl.h"
|
||||
#include "hardware/esp32c3_soc.h"
|
||||
#include "hardware/esp32c3_system.h"
|
||||
#include "hardware/esp32c3_syscon.h"
|
||||
#include "hardware/esp32c3_tim.h"
|
||||
#include "hardware/apb_ctrl_reg.h"
|
||||
#include "hardware/bb_reg.h"
|
||||
@ -1577,6 +1578,43 @@ void IRAM_ATTR esp32c3_rtc_init()
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_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 esp32c3_rtc_get_time_us(void)
|
||||
{
|
||||
const uint32_t cal = getreg32(RTC_SLOW_CLK_CAL_REG);
|
||||
const uint64_t rtc_this_ticks = esp32c3_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: esp32c3_rtc_time_get
|
||||
*
|
||||
|
@ -428,6 +428,22 @@ void esp32c3_rtc_clk_cpu_freq_get_config(
|
||||
|
||||
void esp32c3_rtc_sleep_set_wakeup_time(uint64_t t);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_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 esp32c3_rtc_get_time_us(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
607
arch/risc-v/src/esp32c3/esp32c3_tickless.c
Normal file
607
arch/risc-v/src/esp32c3/esp32c3_tickless.c
Normal file
@ -0,0 +1,607 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/esp32c3/esp32c3_tickless.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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Tickless OS Support.
|
||||
*
|
||||
* When CONFIG_SCHED_TICKLESS is enabled, all support for timer interrupts
|
||||
* is suppressed and the platform specific code is expected to provide the
|
||||
* following custom functions.
|
||||
*
|
||||
* void up_timer_initialize(void): Initializes the timer facilities.
|
||||
* Called early in the initialization sequence (by up_initialize()).
|
||||
* int up_timer_gettime(FAR struct timespec *ts): Returns the current
|
||||
* time from the platform specific time source.
|
||||
* int up_timer_cancel(void): Cancels the interval timer.
|
||||
* int up_timer_start(FAR const struct timespec *ts): Start (or re-starts)
|
||||
* the interval timer.
|
||||
*
|
||||
* The RTOS will provide the following interfaces for use by the platform-
|
||||
* specific interval timer implementation:
|
||||
*
|
||||
* void sched_timer_expiration(void): Called by the platform-specific
|
||||
* logic when the interval timer expires.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "esp32c3_attr.h"
|
||||
#include "chip.h"
|
||||
#include "esp32c3.h"
|
||||
#include "esp32c3_irq.h"
|
||||
#include "hardware/esp32c3_systimer.h"
|
||||
#include "hardware/esp32c3_system.h"
|
||||
#include "hardware/esp32c3_soc.h"
|
||||
|
||||
#include "esp32c3_rtc.h"
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define ESP32C3_SYSTIMER_TICKS_PER_SEC (16 * 1000 * 1000)
|
||||
|
||||
#define CTICK_PER_SEC (ESP32C3_SYSTIMER_TICKS_PER_SEC)
|
||||
#define CTICK_PER_USEC (CTICK_PER_SEC / USEC_PER_SEC)
|
||||
|
||||
#define SEC_2_CTICK(s) ((s) * CTICK_PER_SEC)
|
||||
#define USEC_2_CTICK(us) ((us) * CTICK_PER_USEC)
|
||||
#define NSEC_2_CTICK(nsec) (((nsec) * CTICK_PER_USEC) / NSEC_PER_USEC)
|
||||
|
||||
#define CTICK_2_SEC(tick) ((tick) / CTICK_PER_SEC)
|
||||
#define CTICK_2_USEC(tick) ((tick) / CTICK_PER_USEC)
|
||||
#define CTICK_2_NSEC(tick) ((tick) * 1000 / CTICK_PER_USEC)
|
||||
|
||||
#define CPU_TICKS_MAX (UINT32_MAX / 4 * 3)
|
||||
|
||||
/* The structure of the counter value in systimer */
|
||||
|
||||
struct systimer_counter_value_s
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t lo : SOC_SYSTIMER_BIT_WIDTH_LO; /* Low part of counter value */
|
||||
uint64_t hi : SOC_SYSTIMER_BIT_WIDTH_HI; /* High part of counter value */
|
||||
};
|
||||
uint64_t val; /* counter value */
|
||||
};
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint64_t up_tmr_getcounter(void);
|
||||
static inline uint64_t up_tmr_getalarmvalue(void);
|
||||
static inline void up_tmr_counter_advance(uint64_t tick);
|
||||
static void IRAM_ATTR up_tmr_setcounter(uint64_t ticks);
|
||||
static void IRAM_ATTR up_timer_expire(int irq, void *regs, FAR void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static bool g_timer_started; /* Whether an interval timer is being started */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_tmr_getcounter
|
||||
*
|
||||
* Description:
|
||||
* Return the total ticks of system since power-on.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Total system ticks
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint64_t up_tmr_getcounter(void)
|
||||
{
|
||||
uint32_t lo;
|
||||
uint32_t lo_start;
|
||||
uint32_t hi;
|
||||
|
||||
/* Set the "update" bit and wait for acknowledgment */
|
||||
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_UNIT0_OP_REG, 1 << 30);
|
||||
while (!REG_GET_BIT(SYS_TIMER_SYSTIMER_UNIT0_OP_REG, 1 << 29));
|
||||
|
||||
/* Read LO, HI, then LO again, check that LO returns the same value.
|
||||
* This accounts for the case when an interrupt may happen between reading
|
||||
* HI and LO values, and this function may get called from the ISR.
|
||||
* In this case, the repeated read will return consistent values.
|
||||
*/
|
||||
|
||||
lo_start = getreg32(SYS_TIMER_SYSTIMER_UNIT0_VALUE_HI_REG);
|
||||
do
|
||||
{
|
||||
lo = lo_start;
|
||||
hi = getreg32(SYS_TIMER_SYSTIMER_UNIT0_VALUE_HI_REG);
|
||||
lo_start = getreg32(SYS_TIMER_SYSTIMER_UNIT0_VALUE_LO_REG);
|
||||
}
|
||||
while (lo_start != lo);
|
||||
|
||||
struct systimer_counter_value_s result =
|
||||
{
|
||||
.lo = lo,
|
||||
.hi = hi
|
||||
};
|
||||
|
||||
return result.val;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_tmr_getalarmvalue
|
||||
*
|
||||
* Description:
|
||||
* Return the remaining ticks in the currently running timer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Remaining ticks
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint64_t up_tmr_getalarmvalue(void)
|
||||
{
|
||||
return ((uint64_t) getreg32(SYS_TIMER_SYSTIMER_TARGET0_HI_REG) << 32) \
|
||||
| getreg32(SYS_TIMER_SYSTIMER_TARGET0_LO_REG);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_tmr_counter_advance
|
||||
*
|
||||
* Description:
|
||||
* Adjust current system tick by a certain value
|
||||
*
|
||||
* Input Parameters:
|
||||
* ticks - Adjustment to apply to system time, in microseconds
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void up_tmr_counter_advance(uint64_t tick)
|
||||
{
|
||||
/* set_counter_value */
|
||||
|
||||
putreg32(tick & 0xffffffff, SYS_TIMER_SYSTIMER_UNIT0_LOAD_LO_REG);
|
||||
putreg32((tick >> 32) & 0xfffff, SYS_TIMER_SYSTIMER_UNIT0_LOAD_HI_REG);
|
||||
|
||||
/* apply_counter_value */
|
||||
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_UNIT0_LOAD_REG, SYS_TIMER_TIMER_UNIT0_LOAD);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_tmr_setcounter
|
||||
*
|
||||
* Description:
|
||||
* Set the new value of the compare register
|
||||
*
|
||||
* Input Parameters:
|
||||
* ticks - ticks for a timer operation
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void IRAM_ATTR up_tmr_setcounter(uint64_t ticks)
|
||||
{
|
||||
uint64_t alarm_ticks = up_tmr_getcounter() + ticks;
|
||||
|
||||
/* select_alarm_mode */
|
||||
|
||||
REG_CLR_BIT(SYS_TIMER_SYSTIMER_TARGET0_CONF_REG,
|
||||
SYS_TIMER_TARGET0_PERIOD_MODE);
|
||||
|
||||
/* set alarm value */
|
||||
|
||||
putreg32(alarm_ticks & 0xffffffff, SYS_TIMER_SYSTIMER_TARGET0_LO_REG);
|
||||
putreg32((alarm_ticks >> 32) & 0xfffff, SYS_TIMER_SYSTIMER_TARGET0_HI_REG);
|
||||
|
||||
/* apply alarm vaule */
|
||||
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_COMP0_LOAD_REG, SYS_TIMER_TIMER_COMP0_LOAD);
|
||||
|
||||
/* Enable alarm */
|
||||
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_CONF_REG, SYS_TIMER_TARGET0_WORK_EN);
|
||||
|
||||
/* Enable interrupt */
|
||||
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_INT_CLR_REG, SYS_TIMER_TARGET0_INT_CLR);
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_INT_ENA_REG, SYS_TIMER_TARGET0_INT_ENA);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_timer_expire
|
||||
*
|
||||
* Description:
|
||||
* Called as the IRQ handler for timer expiration.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void IRAM_ATTR up_timer_expire(int irq, void *regs, FAR void *arg)
|
||||
{
|
||||
g_timer_started = false;
|
||||
setbits(SYS_TIMER_TARGET0_INT_CLR, SYS_TIMER_SYSTIMER_INT_CLR_REG);
|
||||
nxsched_timer_expiration();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_timer_gettime
|
||||
*
|
||||
* Description:
|
||||
* Return the elapsed time since power-up (or, more correctly, since
|
||||
* up_timer_initialize() was called). This function is functionally
|
||||
* equivalent to:
|
||||
*
|
||||
* int clock_gettime(clockid_t clockid, FAR struct timespec *ts);
|
||||
*
|
||||
* when clockid is CLOCK_MONOTONIC.
|
||||
*
|
||||
* This function provides the basis for reporting the current time and
|
||||
* also is used to eliminate error build-up from small errors in interval
|
||||
* time calculations.
|
||||
*
|
||||
* Provided by platform-specific code and called from the RTOS base code.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ts - Provides the location in which to return the up-time.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from the normal tasking context. The implementation must
|
||||
* provide whatever mutual exclusion is necessary for correct operation.
|
||||
* This can include disabling interrupts in order to assure atomic register
|
||||
* operations.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int IRAM_ATTR up_timer_gettime(FAR struct timespec *ts)
|
||||
{
|
||||
uint64_t ticks;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
ticks = up_tmr_getcounter();
|
||||
ts->tv_sec = CTICK_2_SEC(ticks);
|
||||
ts->tv_nsec = CTICK_2_NSEC(ticks % CTICK_PER_SEC);
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_timer_cancel
|
||||
*
|
||||
* Description:
|
||||
* Cancel the interval timer and return the time remaining on the timer.
|
||||
* These two steps need to be as nearly atomic as possible.
|
||||
* nxsched_timer_expiration() will not be called unless the timer is
|
||||
* restarted with up_timer_start().
|
||||
*
|
||||
* If, as a race condition, the timer has already expired when this
|
||||
* function is called, then that pending interrupt must be cleared so
|
||||
* that up_timer_start() and the remaining time of zero should be
|
||||
* returned.
|
||||
*
|
||||
* NOTE: This function may execute at a high rate with no timer running (as
|
||||
* when pre-emption is enabled and disabled).
|
||||
*
|
||||
* Provided by platform-specific code and called from the RTOS base code.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ts - Location to return the remaining time. Zero should be returned
|
||||
* if the timer is not active. ts may be zero in which case the
|
||||
* time remaining is not returned.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A call to up_timer_cancel() when
|
||||
* the timer is not active should also return success; a negated errno
|
||||
* value is returned on any failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* May be called from interrupt level handling or from the normal tasking
|
||||
* level. Interrupts may need to be disabled internally to assure
|
||||
* non-reentrancy.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int IRAM_ATTR up_timer_cancel(FAR struct timespec *ts)
|
||||
{
|
||||
uint64_t alarm_value;
|
||||
uint64_t counter;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (ts != NULL)
|
||||
{
|
||||
if (g_timer_started == false)
|
||||
{
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
alarm_value = up_tmr_getalarmvalue();
|
||||
counter = up_tmr_getcounter();
|
||||
if (alarm_value <= counter)
|
||||
{
|
||||
alarm_value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
alarm_value -= counter;
|
||||
}
|
||||
|
||||
ts->tv_sec = CTICK_2_SEC(alarm_value);
|
||||
ts->tv_nsec = CTICK_2_NSEC(alarm_value % CTICK_PER_SEC);
|
||||
}
|
||||
}
|
||||
|
||||
g_timer_started = false;
|
||||
REG_CLR_BIT(SYS_TIMER_SYSTIMER_CONF_REG, SYS_TIMER_TARGET0_WORK_EN);
|
||||
REG_CLR_BIT(SYS_TIMER_SYSTIMER_INT_ENA_REG, SYS_TIMER_TARGET0_INT_ENA);
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_INT_CLR_REG, SYS_TIMER_TARGET0_INT_CLR);
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_timer_start
|
||||
*
|
||||
* Description:
|
||||
* Start the interval timer. nxsched_timer_expiration() will be
|
||||
* called at the completion of the timeout (unless up_timer_cancel
|
||||
* is called to stop the timing.
|
||||
*
|
||||
* Provided by platform-specific code and called from the RTOS base code.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ts - Provides the time interval until nxsched_timer_expiration() is
|
||||
* called.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* May be called from interrupt level handling or from the normal tasking
|
||||
* level. Interrupts may need to be disabled internally to assure
|
||||
* non-reentrancy.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int IRAM_ATTR up_timer_start(FAR const struct timespec *ts)
|
||||
{
|
||||
uint64_t cpu_ticks;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (g_timer_started == true)
|
||||
{
|
||||
up_timer_cancel(NULL);
|
||||
}
|
||||
|
||||
cpu_ticks = SEC_2_CTICK((uint64_t)ts->tv_sec) +
|
||||
NSEC_2_CTICK((uint64_t)ts->tv_nsec);
|
||||
|
||||
up_tmr_setcounter(cpu_ticks);
|
||||
g_timer_started = true;
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_timer_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initializes all platform-specific timer facilities. This function is
|
||||
* called early in the initialization sequence by up_initialize().
|
||||
* On return, the current up-time should be available from
|
||||
* up_timer_gettime() and the interval timer is ready for use (but not
|
||||
* actively timing.
|
||||
*
|
||||
* Provided by platform-specific code and called from the architecture-
|
||||
* specific logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Called early in the initialization sequence before any special
|
||||
* concurrency protections are required.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_timer_initialize(void)
|
||||
{
|
||||
int cpuint;
|
||||
|
||||
g_timer_started = false;
|
||||
|
||||
/* Enable timer clock */
|
||||
|
||||
setbits(SYSTEM_SYSTIMER_CLK_EN, SYSTEM_PERIP_CLK_EN0_REG);
|
||||
resetbits(SYSTEM_SYSTIMER_RST, SYSTEM_PERIP_RST_EN0_REG);
|
||||
|
||||
setbits(SYS_TIMER_CLK_EN, SYS_TIMER_SYSTIMER_CONF_REG);
|
||||
|
||||
/* Stall timer when stall CPU, specially when using JTAG to debug */
|
||||
|
||||
setbits(SYS_TIMER_TIMER_UNIT0_CORE0_STALL_EN, SYS_TIMER_SYSTIMER_CONF_REG);
|
||||
|
||||
/* NOTE: Timer 0 is an internal interrupt source so we do not need to
|
||||
* attach any peripheral ID to the dedicated CPU interrupt.
|
||||
*/
|
||||
|
||||
/* Attach the timer interrupt */
|
||||
|
||||
cpuint = esp32c3_request_irq(ESP32C3_PERIPH_SYSTIMER_T0,
|
||||
ESP32C3_INT_PRIO_DEF,
|
||||
ESP32C3_INT_LEVEL);
|
||||
|
||||
/* Attach the timer interrupt. */
|
||||
|
||||
irq_attach(ESP32C3_IRQ_SYSTIMER_T0, (xcpt_t)up_timer_expire, NULL);
|
||||
|
||||
/* Enable the allocated CPU interrupt. */
|
||||
|
||||
up_enable_irq(cpuint);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_idletime
|
||||
*
|
||||
* Description:
|
||||
* This function returns the idle time.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* The time in system ticks remaining for idle.
|
||||
* Zero means system is busy.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t IRAM_ATTR up_get_idletime(void)
|
||||
{
|
||||
uint32_t us;
|
||||
uint64_t alarm_value;
|
||||
uint64_t counter;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
if (g_timer_started == false)
|
||||
{
|
||||
us = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
alarm_value = up_tmr_getalarmvalue();
|
||||
counter = up_tmr_getcounter();
|
||||
if (alarm_value > counter)
|
||||
{
|
||||
us = CTICK_2_USEC(alarm_value - counter);
|
||||
}
|
||||
else
|
||||
{
|
||||
us = 0;
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return us;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_step_idletime
|
||||
*
|
||||
* Description:
|
||||
* Add system time by idletime_us.
|
||||
*
|
||||
* Input Parameters:
|
||||
* us - Idle time(us)
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void IRAM_ATTR up_step_idletime(uint32_t us)
|
||||
{
|
||||
uint64_t step_counter;
|
||||
uint64_t alarm_value;
|
||||
irqstate_t flags;
|
||||
|
||||
DEBUGASSERT(g_timer_started);
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
alarm_value = up_tmr_getalarmvalue();
|
||||
step_counter = USEC_2_CTICK((uint64_t)us) + up_tmr_getcounter();
|
||||
if (step_counter > alarm_value)
|
||||
{
|
||||
DEBUGASSERT(0);
|
||||
}
|
||||
|
||||
up_tmr_counter_advance(step_counter);
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCHED_TICKLESS */
|
67
arch/risc-v/src/esp32c3/esp32c3_tickless.h
Normal file
67
arch/risc-v/src/esp32c3/esp32c3_tickless.h
Normal file
@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/esp32c3/esp32c3_tickless.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_ESP32C3_ESP32C3_TICKLESS_H
|
||||
#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_TICKLESS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_idletime
|
||||
*
|
||||
* Description:
|
||||
* This function returns the idle time.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* The time in system ticks remaining for idle.
|
||||
* Zero means system is busy.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t up_get_idletime(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_step_idletime
|
||||
*
|
||||
* Description:
|
||||
* Add system time by idletime_us.
|
||||
*
|
||||
* Input Parameters:
|
||||
* idletime_us - Idle time(us)
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_step_idletime(uint32_t idletime_us);
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_TICKLESS_H */
|
@ -50,6 +50,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/wireless/wireless.h>
|
||||
|
||||
#include "hardware/esp32c3_rtccntl.h"
|
||||
#include "hardware/esp32c3_syscon.h"
|
||||
#include "esp32c3.h"
|
||||
#include "esp32c3_attr.h"
|
||||
@ -58,6 +59,10 @@
|
||||
#include "esp32c3_rt_timer.h"
|
||||
#include "esp32c3_wifi_utils.h"
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#include "esp32c3_pm.h"
|
||||
#endif
|
||||
|
||||
#include "espidf_wifi.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -90,6 +95,27 @@
|
||||
#define ESP_MAX_STA_CONN (4)
|
||||
#define ESP_WIFI_CHANNEL (6)
|
||||
|
||||
#ifndef CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL
|
||||
#define CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL 3
|
||||
#endif
|
||||
|
||||
#define DEFAULT_LISTEN_INTERVAL CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL
|
||||
|
||||
/* CONFIG_POWER_SAVE_MODEM */
|
||||
|
||||
#if defined(CONFIG_EXAMPLE_POWER_SAVE_MIN_MODEM)
|
||||
# define DEFAULT_PS_MODE WIFI_PS_MIN_MODEM
|
||||
#elif defined(CONFIG_EXAMPLE_POWER_SAVE_MAX_MODEM)
|
||||
# define DEFAULT_PS_MODE WIFI_PS_MAX_MODEM
|
||||
#elif defined(CONFIG_EXAMPLE_POWER_SAVE_NONE)
|
||||
# define DEFAULT_PS_MODE WIFI_PS_NONE
|
||||
#else
|
||||
# define DEFAULT_PS_MODE WIFI_PS_NONE
|
||||
#endif
|
||||
|
||||
#define RTC_CLK_CAL_FRACT (19)
|
||||
#define SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH (12)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -2062,7 +2088,7 @@ static void esp_evt_work_cb(FAR void *arg)
|
||||
case WIFI_ADPT_EVT_STA_START:
|
||||
wlinfo("INFO: Wi-Fi sta start\n");
|
||||
g_sta_connected = false;
|
||||
ret = esp_wifi_set_ps(WIFI_PS_NONE);
|
||||
ret = esp_wifi_set_ps(DEFAULT_PS_MODE);
|
||||
if (ret)
|
||||
{
|
||||
wlerr("ERROR: Failed to close PS\n");
|
||||
@ -2334,24 +2360,30 @@ static void esp_dport_access_stall_other_cpu_end(void)
|
||||
* Name: wifi_apb80m_request
|
||||
*
|
||||
* Description:
|
||||
* Don't support
|
||||
* Take Wi-Fi lock in auto-sleep
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wifi_apb80m_request(void)
|
||||
{
|
||||
#ifdef CONFIG_ESP32C3_AUTO_SLEEP
|
||||
esp32c3_pm_lockacquire();
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wifi_apb80m_release
|
||||
*
|
||||
* Description:
|
||||
* Don't support
|
||||
* Release Wi-Fi lock in auto-sleep
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wifi_apb80m_release(void)
|
||||
{
|
||||
#ifdef CONFIG_ESP32C3_AUTO_SLEEP
|
||||
esp32c3_pm_lockrelease();
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -3419,11 +3451,26 @@ static int esp_get_time(void *t)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp_clk_slowclk_cal_get_wrapper
|
||||
*
|
||||
* Description:
|
||||
* Get the calibration value of RTC slow clock
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* The calibration value obtained using rtc_clk_cal
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t esp_clk_slowclk_cal_get_wrapper(void)
|
||||
{
|
||||
return 28639;
|
||||
/* The bit width of Wi-Fi light sleep clock calibration is 12 while the one
|
||||
* of system is 19. It should shift 19 - 12 = 7.
|
||||
*/
|
||||
|
||||
return (getreg32(RTC_SLOW_CLK_CAL_REG) >> (RTC_CLK_CAL_FRACT -
|
||||
SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -4616,6 +4663,26 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if SOC_WIFI_HW_TSF
|
||||
ret = esp32c3_pm_register_skip_sleep_callback(
|
||||
esp_wifi_internal_is_tsf_active);
|
||||
if (ret != OK)
|
||||
{
|
||||
wlerr("ERROR: Failed to register skip sleep callback (0x%x)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp32c3_pm_register_inform_out_sleep_overhead_callback(
|
||||
esp_wifi_internal_update_light_sleep_wake_ahead_time);
|
||||
if (ret != OK)
|
||||
{
|
||||
wlerr("ERROR: Failed to register overhead callback (0x%x)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp32c3_sleep_enable_wifi_wakeup();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4651,6 +4718,12 @@ esp_err_t esp_wifi_deinit(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if SOC_WIFI_HW_TSF
|
||||
esp32c3_pm_unregister_skip_sleep_callback(
|
||||
esp_wifi_internal_is_tsf_active);
|
||||
esp32c3_pm_unregister_inform_out_sleep_overhead_callback(
|
||||
esp_wifi_internal_update_light_sleep_wake_ahead_time);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4793,13 +4866,6 @@ int esp_wifi_adapter_init(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
ret = esp32c3_rt_timer_init();
|
||||
if (ret < 0)
|
||||
{
|
||||
wlerr("ERROR: Failed to initialize RT timer error=%d\n", ret);
|
||||
goto errout_init_timer;
|
||||
}
|
||||
|
||||
sq_init(&g_wifi_evt_queue);
|
||||
|
||||
#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM
|
||||
@ -4867,8 +4933,6 @@ int esp_wifi_adapter_init(void)
|
||||
errout_init_txdone:
|
||||
esp_wifi_deinit();
|
||||
errout_init_wifi:
|
||||
esp32c3_rt_timer_deinit();
|
||||
errout_init_timer:
|
||||
esp_wifi_lock(false);
|
||||
return ret;
|
||||
}
|
||||
@ -5145,6 +5209,7 @@ int esp_wifi_sta_password(struct iwreq *iwr, bool set)
|
||||
memcpy(wifi_cfg.sta.password, pdata, len);
|
||||
|
||||
wifi_cfg.sta.pmf_cfg.capable = true;
|
||||
wifi_cfg.sta.listen_interval = DEFAULT_LISTEN_INTERVAL;
|
||||
|
||||
ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
|
||||
if (ret)
|
||||
|
@ -117,4 +117,4 @@ int esp_wifi_scan_init(void);
|
||||
#undef EXTERN
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_UTILS_H */
|
||||
#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_UTILS_H */
|
||||
|
@ -35,6 +35,8 @@
|
||||
|
||||
#define APB_CTRL_MEM_POWER_UP_REG (DR_REG_APB_CTRL_BASE + 0x0AC)
|
||||
|
||||
#define APB_CTRL_RETENTION_CTRL_REG (DR_REG_APB_CTRL_BASE + 0x0A0)
|
||||
|
||||
/* APB_CTRL_DC_MEM_FORCE_PU : R/W ;bitpos:[4] ;default: 1'b1 ; */
|
||||
|
||||
#define APB_CTRL_DC_MEM_FORCE_PU (BIT(4))
|
||||
@ -70,4 +72,11 @@
|
||||
#define APB_CTRL_ROM_POWER_UP_V 0x3
|
||||
#define APB_CTRL_ROM_POWER_UP_S 0
|
||||
|
||||
/* APB_CTRL_RETENTION_LINK_ADDR : R/W ;bitpos:[26:0] ;default: 27'd0 ; */
|
||||
|
||||
#define APB_CTRL_RETENTION_LINK_ADDR 0x07FFFFFF
|
||||
#define APB_CTRL_RETENTION_LINK_ADDR_M ((APB_CTRL_RETENTION_LINK_ADDR_V)<<(APB_CTRL_RETENTION_LINK_ADDR_S))
|
||||
#define APB_CTRL_RETENTION_LINK_ADDR_V 0x7FFFFFF
|
||||
#define APB_CTRL_RETENTION_LINK_ADDR_S 0
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_APB_CTRL_REG_H_ */
|
||||
|
@ -3615,4 +3615,13 @@
|
||||
#define RTC_CNTL_CNTL_DATE_V 0xFFFFFFF
|
||||
#define RTC_CNTL_CNTL_DATE_S 0
|
||||
|
||||
#define RTC_SLOW_CLK_CAL_REG RTC_CNTL_STORE1_REG
|
||||
#define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG
|
||||
#define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG
|
||||
#define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG
|
||||
#define RTC_APB_FREQ_REG RTC_CNTL_STORE5_REG
|
||||
#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG
|
||||
#define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG
|
||||
#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_ESP32C3_RTCCNTL_H */
|
||||
|
@ -303,4 +303,7 @@
|
||||
|
||||
#define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S)))))
|
||||
|
||||
#define SOC_SYSTIMER_BIT_WIDTH_LO (32) /* Bit width of systimer low part */
|
||||
#define SOC_SYSTIMER_BIT_WIDTH_HI (20) /* Bit width of systimer high part */
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_ESP32C3_SOC_H */
|
||||
|
@ -0,0 +1,68 @@
|
||||
#
|
||||
# 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="risc-v"
|
||||
CONFIG_ARCH_BOARD="esp32c3-devkit"
|
||||
CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
|
||||
CONFIG_ARCH_CHIP="esp32c3"
|
||||
CONFIG_ARCH_CHIP_ESP32C3=y
|
||||
CONFIG_ARCH_CHIP_ESP32C3WROOM02=y
|
||||
CONFIG_ARCH_INTERRUPTSTACK=1536
|
||||
CONFIG_ARCH_RISCV=y
|
||||
CONFIG_ARCH_STACKDUMP=y
|
||||
CONFIG_BOARD_LOOPSPERMSEC=16717
|
||||
CONFIG_BUILTIN=y
|
||||
CONFIG_DRIVERS_IEEE80211=y
|
||||
CONFIG_DRIVERS_WIRELESS=y
|
||||
CONFIG_ESP32C3_AUTO_SLEEP=y
|
||||
CONFIG_ESP32C3_WIRELESS=y
|
||||
CONFIG_EXAMPLE_POWER_SAVE_MIN_MODEM=y
|
||||
CONFIG_FS_PROCFS=y
|
||||
CONFIG_HAVE_CXX=y
|
||||
CONFIG_HAVE_CXXINITIALIZE=y
|
||||
CONFIG_IDLETHREAD_STACKSIZE=3072
|
||||
CONFIG_INTELHEX_BINARY=y
|
||||
CONFIG_LIBC_FLOATINGPOINT=y
|
||||
CONFIG_NAME_MAX=48
|
||||
CONFIG_NETDB_DNSCLIENT=y
|
||||
CONFIG_NETDEV_LATEINIT=y
|
||||
CONFIG_NETDEV_PHY_IOCTL=y
|
||||
CONFIG_NETDEV_WIRELESS_IOCTL=y
|
||||
CONFIG_NETINIT_DHCPC=y
|
||||
CONFIG_NET_BROADCAST=y
|
||||
CONFIG_NET_ETH_PKTSIZE=1514
|
||||
CONFIG_NET_ICMP=y
|
||||
CONFIG_NET_ICMP_SOCKET=y
|
||||
CONFIG_NET_SOCKOPTS=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_UDP=y
|
||||
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_PTHREAD_MUTEX_TYPES=y
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_SCHED_LPWORK=y
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_SIG_DEFAULT=y
|
||||
CONFIG_START_DAY=6
|
||||
CONFIG_START_MONTH=12
|
||||
CONFIG_START_YEAR=2011
|
||||
CONFIG_SYSTEM_DHCPC_RENEW=y
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_SYSTEM_PING=y
|
||||
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||
CONFIG_USER_ENTRYPOINT="nsh_main"
|
||||
CONFIG_WIRELESS=y
|
||||
CONFIG_WIRELESS_WAPI=y
|
||||
CONFIG_WIRELESS_WAPI_CMDTOOL=y
|
||||
CONFIG_WIRELESS_WAPI_STACKSIZE=4096
|
@ -0,0 +1,44 @@
|
||||
#
|
||||
# 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="risc-v"
|
||||
CONFIG_ARCH_BOARD="esp32c3-devkit"
|
||||
CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
|
||||
CONFIG_ARCH_CHIP="esp32c3"
|
||||
CONFIG_ARCH_CHIP_ESP32C3=y
|
||||
CONFIG_ARCH_CHIP_ESP32C3WROOM02=y
|
||||
CONFIG_ARCH_INTERRUPTSTACK=1536
|
||||
CONFIG_ARCH_RISCV=y
|
||||
CONFIG_ARCH_STACKDUMP=y
|
||||
CONFIG_BOARD_LOOPSPERMSEC=15000
|
||||
CONFIG_BUILTIN=y
|
||||
CONFIG_DEV_ZERO=y
|
||||
CONFIG_ESP32C3_TICKLESS=y
|
||||
CONFIG_FS_PROCFS=y
|
||||
CONFIG_IDLETHREAD_STACKSIZE=2048
|
||||
CONFIG_INTELHEX_BINARY=y
|
||||
CONFIG_LIBC_PERROR_STDOUT=y
|
||||
CONFIG_LIBC_STRERROR=y
|
||||
CONFIG_MAX_TASKS=16
|
||||
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||
CONFIG_NSH_ARCHINIT=y
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
CONFIG_NSH_FILEIOSIZE=512
|
||||
CONFIG_NSH_READLINE=y
|
||||
CONFIG_NSH_STRERROR=y
|
||||
CONFIG_PREALLOC_TIMERS=0
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_START_DAY=29
|
||||
CONFIG_START_MONTH=11
|
||||
CONFIG_START_YEAR=2019
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||
CONFIG_USER_ENTRYPOINT="nsh_main"
|
@ -46,10 +46,16 @@
|
||||
# include "esp32c3_spi.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32C3_RT_TIMER
|
||||
# include "esp32c3_rt_timer.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TIMER
|
||||
# include "esp32c3_tim_lowerhalf.h"
|
||||
#endif
|
||||
|
||||
#include "esp32c3_rtc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@ -250,6 +256,14 @@ int esp32c3_bringup(void)
|
||||
|
||||
#endif /* CONFIG_ONESHOT */
|
||||
|
||||
#ifdef CONFIG_ESP32C3_RT_TIMER
|
||||
ret = esp32c3_rt_timer_init();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize RT timer: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32C3_WIRELESS
|
||||
|
||||
#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM
|
||||
|
Loading…
Reference in New Issue
Block a user