esp32s2beta: add APIs added to esp32 target after IDF 3.1
This commit is contained in:
parent
bcb9ba6783
commit
792598c04a
2 changed files with 125 additions and 44 deletions
|
@ -56,11 +56,14 @@ typedef enum {
|
|||
*/
|
||||
typedef enum {
|
||||
ESP_SLEEP_WAKEUP_UNDEFINED, //!< In case of deep sleep, reset was not caused by exit from deep sleep
|
||||
ESP_SLEEP_WAKEUP_ALL, //!< Not a wakeup cause, used to disable all wakeup sources with esp_sleep_disable_wakeup_source
|
||||
ESP_SLEEP_WAKEUP_EXT0, //!< Wakeup caused by external signal using RTC_IO
|
||||
ESP_SLEEP_WAKEUP_EXT1, //!< Wakeup caused by external signal using RTC_CNTL
|
||||
ESP_SLEEP_WAKEUP_TIMER, //!< Wakeup caused by timer
|
||||
ESP_SLEEP_WAKEUP_TOUCHPAD, //!< Wakeup caused by touchpad
|
||||
ESP_SLEEP_WAKEUP_ULP, //!< Wakeup caused by ULP program
|
||||
ESP_SLEEP_WAKEUP_GPIO, //!< Wakeup caused by GPIO (light sleep only)
|
||||
ESP_SLEEP_WAKEUP_UART, //!< Wakeup caused by UART (light sleep only)
|
||||
} esp_sleep_source_t;
|
||||
|
||||
/* Leave this type define for compatibility */
|
||||
|
@ -92,6 +95,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source);
|
|||
* source is used.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NOT_SUPPORTED if additional current by touch (CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) is enabled.
|
||||
* - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled or if wakeup triggers conflict
|
||||
*/
|
||||
esp_err_t esp_sleep_enable_ulp_wakeup(void);
|
||||
|
@ -118,6 +122,7 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us);
|
|||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NOT_SUPPORTED if additional current by touch (CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) is enabled.
|
||||
* - ESP_ERR_INVALID_STATE if wakeup triggers conflict
|
||||
*/
|
||||
esp_err_t esp_sleep_enable_touchpad_wakeup(void);
|
||||
|
@ -189,6 +194,41 @@ esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);
|
|||
*/
|
||||
esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Enable wakeup from light sleep using GPIOs
|
||||
*
|
||||
* Each GPIO supports wakeup function, which can be triggered on either low level
|
||||
* or high level. Unlike EXT0 and EXT1 wakeup sources, this method can be used
|
||||
* both for all IOs: RTC IOs and digital IOs. It can only be used to wakeup from
|
||||
* light sleep though.
|
||||
*
|
||||
* To enable wakeup, first call gpio_wakeup_enable, specifying gpio number and
|
||||
* wakeup level, for each GPIO which is used for wakeup.
|
||||
* Then call this function to enable wakeup feature.
|
||||
*
|
||||
* @note In revisions 0 and 1 of the ESP32, GPIO wakeup source
|
||||
* can not be used together with touch or ULP wakeup sources.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if wakeup triggers conflict
|
||||
*/
|
||||
esp_err_t esp_sleep_enable_gpio_wakeup(void);
|
||||
|
||||
/**
|
||||
* @brief Enable wakeup from light sleep using UART
|
||||
*
|
||||
* Use uart_set_wakeup_threshold function to configure UART wakeup threshold.
|
||||
*
|
||||
* Wakeup from light sleep takes some time, so not every character sent
|
||||
* to the UART can be received by the application.
|
||||
*
|
||||
* @param uart_num UART port to wake up from
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if wakeup from given UART is not supported
|
||||
*/
|
||||
esp_err_t esp_sleep_enable_uart_wakeup(int uart_num);
|
||||
|
||||
/**
|
||||
* @brief Get the bit mask of GPIOs which caused wakeup (ext1)
|
||||
|
@ -253,21 +293,11 @@ esp_err_t esp_light_sleep_start(void);
|
|||
*/
|
||||
void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn));
|
||||
|
||||
/**
|
||||
* @brief Enter deep-sleep mode
|
||||
*
|
||||
* Function has been renamed to esp_deep_sleep.
|
||||
* This name is deprecated and will be removed in a future version.
|
||||
*
|
||||
* @param time_in_us deep-sleep time, unit: microsecond
|
||||
*/
|
||||
void system_deep_sleep(uint64_t time_in_us) __attribute__((noreturn, deprecated));
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the source which caused wakeup from sleep
|
||||
* @brief Get the wakeup source which caused wakeup from sleep
|
||||
*
|
||||
* @return wakeup cause, or ESP_DEEP_SLEEP_WAKEUP_UNDEFINED if reset happened for reason other than deep sleep wakeup
|
||||
* @return cause of wake up from last sleep (deep sleep or light sleep)
|
||||
*/
|
||||
esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void);
|
||||
|
||||
|
|
|
@ -28,15 +28,13 @@
|
|||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc_wdt.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/uart_caps.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/uart.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
|
@ -83,6 +81,10 @@ static sleep_config_t s_config = {
|
|||
.wakeup_triggers = 0
|
||||
};
|
||||
|
||||
/* Internal variable used to track if light sleep wakeup sources are to be
|
||||
expected when determining wakeup cause. */
|
||||
static bool s_light_sleep_wakeup = false;
|
||||
|
||||
/* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc()
|
||||
is not thread-safe. */
|
||||
static _lock_t lock_rtc_memory_crc;
|
||||
|
@ -106,11 +108,14 @@ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
|
|||
REG_WRITE(RTC_MEMORY_CRC_REG, stored_crc);
|
||||
_lock_release(&lock_rtc_memory_crc);
|
||||
|
||||
if(stored_crc == calc_crc) {
|
||||
return (esp_deep_sleep_wake_stub_fn_t)REG_READ(RTC_ENTRY_ADDR_REG);
|
||||
} else {
|
||||
if (stored_crc != calc_crc) {
|
||||
return NULL;
|
||||
}
|
||||
esp_deep_sleep_wake_stub_fn_t stub_ptr = (esp_deep_sleep_wake_stub_fn_t) REG_READ(RTC_ENTRY_ADDR_REG);
|
||||
if (!esp_ptr_executable(stub_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
return stub_ptr;
|
||||
}
|
||||
|
||||
void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
|
||||
|
@ -135,6 +140,13 @@ void esp_deep_sleep(uint64_t time_in_us)
|
|||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
static void IRAM_ATTR flush_uarts(void)
|
||||
{
|
||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||
uart_tx_wait_idle(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR suspend_uarts(void)
|
||||
{
|
||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||
|
@ -150,8 +162,14 @@ static void IRAM_ATTR resume_uarts(void)
|
|||
|
||||
static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
{
|
||||
// Stop UART output so that output is not lost due to APB frequency change
|
||||
// Stop UART output so that output is not lost due to APB frequency change.
|
||||
// For light sleep, suspend UART output — it will resume after wakeup.
|
||||
// For deep sleep, wait for the contents of UART FIFO to be sent.
|
||||
if (pd_flags & RTC_SLEEP_PD_DIG) {
|
||||
flush_uarts();
|
||||
} else {
|
||||
suspend_uarts();
|
||||
}
|
||||
|
||||
// Save current frequency and switch to XTAL
|
||||
rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get();
|
||||
|
@ -166,8 +184,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
|||
}
|
||||
// Enable ULP wakeup
|
||||
if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) {
|
||||
//TODO, esp32s2 does not have this bit
|
||||
//SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_WAKEUP_FORCE_EN);
|
||||
// no-op for esp32s2beta
|
||||
}
|
||||
|
||||
// Enter sleep
|
||||
|
@ -269,7 +286,7 @@ esp_err_t esp_light_sleep_start(void)
|
|||
// If it needs to be powered down, adjust sleep time.
|
||||
const uint32_t flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US;
|
||||
|
||||
#ifndef CONFIG_ESP32S2_SPIRAM_SUPPORT
|
||||
#ifndef CONFIG_SPIRAM
|
||||
const uint32_t vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US,
|
||||
flash_enable_time_us + LIGHT_SLEEP_TIME_OVERHEAD_US + LIGHT_SLEEP_MIN_TIME_US);
|
||||
|
||||
|
@ -277,7 +294,7 @@ esp_err_t esp_light_sleep_start(void)
|
|||
pd_flags |= RTC_SLEEP_PD_VDDSDIO;
|
||||
s_config.sleep_time_adjustment += flash_enable_time_us;
|
||||
}
|
||||
#endif //CONFIG_ESP32S2_SPIRAM_SUPPORT
|
||||
#endif //CONFIG_SPIRAM
|
||||
|
||||
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
|
||||
|
||||
|
@ -298,6 +315,8 @@ esp_err_t esp_light_sleep_start(void)
|
|||
esp_err_t err = esp_light_sleep_inner(pd_flags,
|
||||
flash_enable_time_us, vddsdio_config);
|
||||
|
||||
s_light_sleep_wakeup = true;
|
||||
|
||||
// FRC1 has been clock gated for the duration of the sleep, correct for that.
|
||||
uint64_t rtc_ticks_at_end = rtc_time_get();
|
||||
uint64_t frc_time_at_end = esp_timer_get_time();
|
||||
|
@ -325,30 +344,36 @@ esp_err_t esp_light_sleep_start(void)
|
|||
return err;
|
||||
}
|
||||
|
||||
void system_deep_sleep(uint64_t) __attribute__((alias("esp_deep_sleep")));
|
||||
|
||||
esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
|
||||
{
|
||||
// For most of sources it is enough to set trigger mask in local
|
||||
// configuration structure. The actual RTC wake up options
|
||||
// will be updated by esp_sleep_start().
|
||||
if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) {
|
||||
if (source == ESP_SLEEP_WAKEUP_ALL) {
|
||||
s_config.wakeup_triggers = 0;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) {
|
||||
s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN;
|
||||
s_config.sleep_duration = 0;
|
||||
}
|
||||
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) {
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) {
|
||||
s_config.ext0_rtc_gpio_num = 0;
|
||||
s_config.ext0_trigger_level = 0;
|
||||
s_config.wakeup_triggers &= ~RTC_EXT0_TRIG_EN;
|
||||
}
|
||||
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT1, RTC_EXT1_TRIG_EN)) {
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT1, RTC_EXT1_TRIG_EN)) {
|
||||
s_config.ext1_rtc_gpio_mask = 0;
|
||||
s_config.ext1_trigger_mode = 0;
|
||||
s_config.wakeup_triggers &= ~RTC_EXT1_TRIG_EN;
|
||||
}
|
||||
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TOUCHPAD, RTC_TOUCH_TRIG_EN)) {
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TOUCHPAD, RTC_TOUCH_TRIG_EN)) {
|
||||
s_config.wakeup_triggers &= ~RTC_TOUCH_TRIG_EN;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_GPIO, RTC_GPIO_TRIG_EN)) {
|
||||
s_config.wakeup_triggers &= ~RTC_GPIO_TRIG_EN;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) {
|
||||
s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN);
|
||||
}
|
||||
#ifdef CONFIG_ESP32S2_ULP_COPROC_ENABLED
|
||||
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) {
|
||||
s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
ESP_LOGE(TAG, "Incorrect wakeup source (%d) to disable.", (int) source);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
|
@ -376,7 +401,6 @@ static void timer_wakeup_prepare(void)
|
|||
sleep_duration = 0;
|
||||
}
|
||||
int64_t rtc_count_delta = rtc_time_us_to_slowclk(sleep_duration, period);
|
||||
|
||||
rtc_sleep_set_wakeup_time(s_config.rtc_ticks_at_sleep_start + rtc_count_delta);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_MAIN_TIMER_INT_CLR_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
|
||||
|
@ -516,9 +540,32 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void)
|
|||
return gpio_mask;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_gpio_wakeup(void)
|
||||
{
|
||||
if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
||||
ESP_LOGE(TAG, "Conflicting wake-up triggers: touch / ULP");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_config.wakeup_triggers |= RTC_GPIO_TRIG_EN;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_uart_wakeup(int uart_num)
|
||||
{
|
||||
if (uart_num == UART_NUM_0) {
|
||||
s_config.wakeup_triggers |= RTC_UART0_TRIG_EN;
|
||||
} else if (uart_num == UART_NUM_1) {
|
||||
s_config.wakeup_triggers |= RTC_UART1_TRIG_EN;
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
|
||||
{
|
||||
if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET) {
|
||||
if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET && !s_light_sleep_wakeup) {
|
||||
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||
}
|
||||
|
||||
|
@ -533,6 +580,10 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
|
|||
return ESP_SLEEP_WAKEUP_TOUCHPAD;
|
||||
} else if (wakeup_cause & RTC_ULP_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_ULP;
|
||||
} else if (wakeup_cause & RTC_GPIO_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_GPIO;
|
||||
} else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) {
|
||||
return ESP_SLEEP_WAKEUP_UART;
|
||||
} else {
|
||||
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||
}
|
||||
|
@ -557,11 +608,11 @@ static uint32_t get_power_down_flags(void)
|
|||
// If there is any data placed into .rtc.data or .rtc.bss segments, and
|
||||
// RTC_SLOW_MEM is Auto, keep it powered up as well.
|
||||
|
||||
// These labels are defined in the linker script:
|
||||
extern int _rtc_data_start, _rtc_data_end, _rtc_bss_start, _rtc_bss_end;
|
||||
// Labels are defined in the linker script, see esp32s2beta.ld.
|
||||
extern int _rtc_slow_length;
|
||||
|
||||
if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) &&
|
||||
(&_rtc_data_end > &_rtc_data_start || &_rtc_bss_end > &_rtc_bss_start ||
|
||||
((size_t) &_rtc_slow_length > 0 ||
|
||||
(s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON;
|
||||
}
|
||||
|
@ -575,10 +626,10 @@ static uint32_t get_power_down_flags(void)
|
|||
s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON;
|
||||
}
|
||||
|
||||
// RTC_PERIPH is needed for EXT0 wakeup.
|
||||
// If RTC_PERIPH is auto, and EXT0 isn't enabled, power down RTC_PERIPH.
|
||||
// RTC_PERIPH is needed for EXT0 wakeup and GPIO wakeup.
|
||||
// If RTC_PERIPH is auto, and EXT0/GPIO aren't enabled, power down RTC_PERIPH.
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) {
|
||||
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
|
||||
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN | RTC_GPIO_TRIG_EN)) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON;
|
||||
} else if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
||||
// In both rev. 0 and rev. 1 of ESP32, forcing power up of RTC_PERIPH
|
||||
|
|
Loading…
Reference in a new issue