mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-21 00:56:38 +08:00
feat(esp8266): add new power management method
This commit is contained in:
@ -99,7 +99,7 @@ IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
|
||||
cfg.alpn_protos = alpnProtocols;
|
||||
}
|
||||
|
||||
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M);
|
||||
esp_set_cpu_freq(ESP_CPU_FREQ_160M);
|
||||
|
||||
struct esp_tls *tls = esp_tls_conn_new(pNetwork->tlsConnectParams.pDestinationURL, strlen(pNetwork->tlsConnectParams.pDestinationURL), pNetwork->tlsConnectParams.DestinationPort, &cfg);
|
||||
|
||||
@ -110,7 +110,7 @@ IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
|
||||
tlsDataParams->timeout = pNetwork->tlsConnectParams.timeout_ms;
|
||||
tlsDataParams->handle = (esp_network_handle_t)tls;
|
||||
|
||||
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M);
|
||||
esp_set_cpu_freq(ESP_CPU_FREQ_80M);
|
||||
|
||||
return (IoT_Error_t) ret;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ else()
|
||||
set(srcs
|
||||
"source/chip_boot.c"
|
||||
"source/backtrace.c"
|
||||
"source/esp_sleep.c"
|
||||
"source/esp_err_to_name.c"
|
||||
"source/esp_timer.c"
|
||||
"source/esp_wifi_os_adapter.c"
|
||||
@ -60,7 +61,7 @@ else()
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib" "-lstdc++")
|
||||
|
||||
if(NOT CONFIG_NO_BLOBS)
|
||||
set(blobs "gcc" "hal" "core" "net80211" "phy" "pp" "smartconfig" "ssc" "wpa" "espnow" "wps")
|
||||
set(blobs "gcc" "hal" "core" "net80211" "phy" "clk" "pp" "smartconfig" "ssc" "wpa" "espnow" "wps")
|
||||
foreach(blob ${blobs})
|
||||
add_library(${blob} STATIC IMPORTED)
|
||||
set_property(TARGET ${blob} PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib/lib${blob}.a)
|
||||
|
@ -13,10 +13,10 @@ LIBS ?=
|
||||
ifndef CONFIG_NO_BLOBS
|
||||
ifndef CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE
|
||||
LIBS += gcc hal core net80211 \
|
||||
phy pp smartconfig ssc wpa espnow wps
|
||||
phy clk pp smartconfig ssc wpa espnow wps
|
||||
else
|
||||
LIBS += gcc hal core_dbg net80211_dbg \
|
||||
phy pp_dbg smartconfig ssc wpa_dbg espnow_dbg wps_dbg
|
||||
phy clk pp_dbg smartconfig ssc wpa_dbg espnow_dbg wps_dbg
|
||||
endif
|
||||
endif
|
||||
|
||||
|
120
components/esp8266/include/driver/rtc.h
Normal file
120
components/esp8266/include/driver/rtc.h
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp8266/eagle_soc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Wakeup option
|
||||
*/
|
||||
#define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup (light sleep only)
|
||||
#define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup
|
||||
|
||||
/**
|
||||
* @brief CPU frequency values
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CPU_FREQ_80M = 0, //!< 80 MHz
|
||||
RTC_CPU_FREQ_160M = 1, //!< 160 MHz
|
||||
} rtc_cpu_freq_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize RTC hardware
|
||||
*/
|
||||
void rtc_clk_init(void);
|
||||
|
||||
/**
|
||||
* @brief Get the currently used CPU frequency configuration
|
||||
*
|
||||
* @return CPU frequency
|
||||
*/
|
||||
rtc_cpu_freq_t rtc_clk_cpu_freq_get(void);
|
||||
|
||||
/**
|
||||
* @brief Switch CPU frequency
|
||||
*
|
||||
* This function sets CPU frequency according to the given configuration
|
||||
* structure. It enables PLLs, if necessary.
|
||||
*
|
||||
* @note This function in not intended to be called by applications in FreeRTOS
|
||||
* environment. This is because it does not adjust various timers based on the
|
||||
* new CPU frequency.
|
||||
*
|
||||
* @param cpu_freq CPU frequency
|
||||
*/
|
||||
void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq);
|
||||
|
||||
/**
|
||||
* @brief Enter light sleep mode
|
||||
*
|
||||
* @note CPU wakeup has 2672 ms time cost, so the real sleeping time is to_sleep_time_in_us - 2672
|
||||
*
|
||||
* @param rtc_ticks value of RTC counter at which wakeup from sleep will happen
|
||||
*
|
||||
* @param wakeup_opt bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags
|
||||
* combined with OR)
|
||||
* @param reject_opt bit mask of sleep reject reasons:
|
||||
* - RTC_CNTL_GPIO_REJECT_EN
|
||||
* - RTC_CNTL_SDIO_REJECT_EN
|
||||
* These flags are used to prevent entering sleep when e.g.
|
||||
* an external host is communicating via SDIO slave
|
||||
* @return non-zero if sleep was rejected by hardware
|
||||
*/
|
||||
uint32_t rtc_light_sleep_start(uint32_t rtc_ticks, uint32_t wakeup_opt, uint32_t reject_opt);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_CLK cycles
|
||||
*
|
||||
* @param time_in_us Time interval in microseconds
|
||||
* @param period Period of clock in microseconds (as returned by esp_clk_cal_get)
|
||||
*
|
||||
* @return number of clock cycles
|
||||
*/
|
||||
uint32_t rtc_time_us_to_clk(uint32_t time_in_us, uint32_t period);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from RTC_CLK to microseconds
|
||||
*
|
||||
* @param rtc_cycles Time interval in RTC_CLK cycles
|
||||
* @param period Period of clock in microseconds (as returned by esp_clk_cal_get)
|
||||
*
|
||||
* @return time interval in microseconds
|
||||
*/
|
||||
uint32_t rtc_time_clk_to_us(uint32_t rtc_cycles, uint32_t period);
|
||||
|
||||
/**
|
||||
* @brief Get the calibration value of RTC clock
|
||||
*
|
||||
* @param xtal_freq XTAL frequency, unit is MHz
|
||||
*
|
||||
* @return the calibration value
|
||||
*/
|
||||
uint32_t esp_clk_cal_get(uint32_t xtal_freq);
|
||||
|
||||
/**
|
||||
* @brief Get current value of RTC counter
|
||||
*
|
||||
* @return current value of RTC counter
|
||||
*/
|
||||
uint32_t rtc_time_get(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -178,6 +178,31 @@ void esp_wifi_enable_gpio_wakeup(uint32_t gpio_num, gpio_int_type_t intr_status)
|
||||
*/
|
||||
void esp_wifi_disable_gpio_wakeup(void);
|
||||
|
||||
/**
|
||||
* @brief Enable wakeup by timer
|
||||
* @param time_in_us time before wakeup, in microseconds
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if value is out of range (TBD)
|
||||
*/
|
||||
esp_err_t esp_sleep_enable_timer_wakeup(uint32_t time_in_us);
|
||||
|
||||
/**
|
||||
* @brief Enter light sleep with the configured wakeup options
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success (returned after wakeup)
|
||||
* - ESP_ERR_INVALID_STATE if WiFi or BT is not stopped
|
||||
*/
|
||||
esp_err_t esp_light_sleep_start(void);
|
||||
|
||||
/**
|
||||
* @brief Operation system start check time and enter sleep
|
||||
*
|
||||
* @note This function is called by system, user should not call this
|
||||
*/
|
||||
void esp_sleep_start(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -123,9 +123,9 @@ esp_err_t esp_derive_local_mac(uint8_t* local_mac, const uint8_t* universal_mac)
|
||||
* @brief CPU frequency values
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CPU_FREQ_80M = 1, //!< 80 MHz
|
||||
RTC_CPU_FREQ_160M = 2, //!< 160 MHz
|
||||
} rtc_cpu_freq_t;
|
||||
ESP_CPU_FREQ_80M = 1, //!< 80 MHz
|
||||
ESP_CPU_FREQ_160M = 2, //!< 160 MHz
|
||||
} esp_cpu_freq_t;
|
||||
|
||||
/**
|
||||
* @brief Switch CPU frequency
|
||||
@ -137,7 +137,7 @@ typedef enum {
|
||||
*
|
||||
* @param cpu_freq new CPU frequency
|
||||
*/
|
||||
void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq);
|
||||
void esp_set_cpu_freq(esp_cpu_freq_t cpu_freq);
|
||||
|
||||
/**
|
||||
* @brief Reset to default settings.
|
||||
|
@ -1,10 +1,10 @@
|
||||
gwen:
|
||||
core: 7f8c705
|
||||
core: f467b5d
|
||||
net80211: 7f8c705
|
||||
pp: 7f8c705
|
||||
wpa: 7f8c705
|
||||
wpa: f467b5d
|
||||
espnow: 7f8c705
|
||||
wps: 7f8c705
|
||||
|
||||
smartconfig: 2.8.1
|
||||
smartconfig: 2.8.2
|
||||
phy: 1055_22
|
||||
|
BIN
components/esp8266/lib/libclk.a
Normal file
BIN
components/esp8266/lib/libclk.a
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -14,3 +14,8 @@ entries:
|
||||
archive: libphy.a
|
||||
entries:
|
||||
* (noflash_text)
|
||||
|
||||
[mapping:rtc]
|
||||
archive: librtc_opensource.a
|
||||
entries:
|
||||
* (noflash_text)
|
||||
|
156
components/esp8266/source/esp_sleep.c
Normal file
156
components/esp8266/source/esp_sleep.c
Normal file
@ -0,0 +1,156 @@
|
||||
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
#include <sys/param.h>
|
||||
#include "esp_timer.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/soc.h"
|
||||
#include "esp8266/timer_struct.h"
|
||||
#include "esp8266/uart_struct.h"
|
||||
#include "esp8266/rom_functions.h"
|
||||
#include "driver/rtc.h"
|
||||
|
||||
|
||||
#define MIN_SLEEP_US (3 * 1000)
|
||||
#define WAKEUP_EARLY_US (2520)
|
||||
|
||||
#define TAG "esp8266_pm"
|
||||
|
||||
typedef struct pm_soc_clk {
|
||||
uint32_t ccount;
|
||||
} pm_soc_clk_t;
|
||||
|
||||
static uint32_t s_lock_cnt = 1;
|
||||
static uint32_t s_sleep_wakup_triggers;
|
||||
static uint32_t s_sleep_duration;
|
||||
|
||||
static inline uint32_t save_local_wdev(void)
|
||||
{
|
||||
extern uint32_t WDEV_INTEREST_EVENT;
|
||||
|
||||
uint32_t reg = WDEV_INTEREST_EVENT;
|
||||
|
||||
REG_WRITE(INT_ENA_WDEV, WDEV_TSF0_REACH_INT);
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
static inline void restore_local_wdev(uint32_t reg)
|
||||
{
|
||||
REG_WRITE(INT_ENA_WDEV, reg);
|
||||
}
|
||||
|
||||
static inline void save_soc_clk(pm_soc_clk_t *clk)
|
||||
{
|
||||
clk->ccount = soc_get_ccount();
|
||||
}
|
||||
|
||||
static inline uint32_t min_sleep_us(pm_soc_clk_t *clk)
|
||||
{
|
||||
const int32_t os_sleep_us = ((int32_t)soc_get_ccompare() - (int32_t)clk->ccount) / g_esp_ticks_per_us +
|
||||
prvGetExpectedIdleTime() * portTICK_RATE_MS * 1000;
|
||||
const uint32_t ccompare_sleep_us = os_sleep_us > 0 ? os_sleep_us : 0;
|
||||
|
||||
return MIN(ccompare_sleep_us, ccompare_sleep_us);
|
||||
}
|
||||
|
||||
static inline void update_soc_clk(pm_soc_clk_t *clk, uint32_t us)
|
||||
{
|
||||
const uint32_t os_ccount = us * g_esp_ticks_per_us + clk->ccount;
|
||||
|
||||
if (os_ccount >= _xt_tick_divisor)
|
||||
soc_set_ccompare(os_ccount + 32);
|
||||
soc_set_ccount(os_ccount);
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_timer_wakeup(uint32_t time_in_us)
|
||||
{
|
||||
if (time_in_us <= MIN_SLEEP_US)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
|
||||
s_sleep_duration = time_in_us;
|
||||
s_sleep_wakup_triggers |= RTC_TIMER_TRIG_EN;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_light_sleep_start(void)
|
||||
{
|
||||
const uint32_t rtc_cal = esp_clk_cal_get(CRYSTAL_USED);
|
||||
const uint32_t sleep_rtc_ticks = rtc_time_us_to_clk(s_sleep_duration - WAKEUP_EARLY_US, rtc_cal);
|
||||
const rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get();
|
||||
|
||||
rtc_light_sleep_start(sleep_rtc_ticks, s_sleep_wakup_triggers, 0);
|
||||
|
||||
rtc_clk_init();
|
||||
rtc_clk_cpu_freq_set(cpu_freq);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_sleep_lock(void)
|
||||
{
|
||||
const esp_irqflag_t irqflag = soc_save_local_irq();
|
||||
s_lock_cnt++;
|
||||
soc_restore_local_irq(irqflag);
|
||||
}
|
||||
|
||||
void esp_sleep_unlock(void)
|
||||
{
|
||||
const esp_irqflag_t irqflag = soc_save_local_irq();
|
||||
s_lock_cnt--;
|
||||
soc_restore_local_irq(irqflag);
|
||||
}
|
||||
|
||||
void IRAM_ATTR esp_sleep_start(void)
|
||||
{
|
||||
if (s_lock_cnt) {
|
||||
soc_wait_int();
|
||||
return ;
|
||||
}
|
||||
|
||||
int slept = 0;
|
||||
pm_soc_clk_t clk;
|
||||
const esp_irqflag_t irqflag = soc_save_local_irq();
|
||||
const uint32_t wdevflag = save_local_wdev();
|
||||
|
||||
save_soc_clk(&clk);
|
||||
|
||||
const uint32_t sleep_us = min_sleep_us(&clk);
|
||||
if (sleep_us > MIN_SLEEP_US) {
|
||||
const uint32_t rtc_cal = esp_clk_cal_get(CRYSTAL_USED);
|
||||
const uint32_t sleep_rtc_ticks = rtc_time_us_to_clk(sleep_us - WAKEUP_EARLY_US, rtc_cal);
|
||||
const rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get();
|
||||
|
||||
rtc_light_sleep_start(sleep_rtc_ticks, s_sleep_wakup_triggers | RTC_TIMER_TRIG_EN, 0);
|
||||
|
||||
rtc_clk_init();
|
||||
rtc_clk_cpu_freq_set(cpu_freq);
|
||||
|
||||
update_soc_clk(&clk, sleep_us);
|
||||
|
||||
slept = 1;
|
||||
}
|
||||
|
||||
restore_local_wdev(wdevflag);
|
||||
soc_restore_local_irq(irqflag);
|
||||
|
||||
if (!slept)
|
||||
soc_wait_int();
|
||||
}
|
@ -200,9 +200,9 @@ esp_err_t esp_timer_delete(esp_timer_handle_t timer)
|
||||
return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
int64_t esp_timer_get_time()
|
||||
int64_t esp_timer_get_time(void)
|
||||
{
|
||||
extern uint64_t g_esp_os_us;
|
||||
|
||||
return (int64_t)g_esp_os_us;
|
||||
return (int64_t)(g_esp_os_us + soc_get_ccount() / g_esp_ticks_per_us);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ static void user_init_entry(void *param)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP8266_DEFAULT_CPU_FREQ_160
|
||||
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M);
|
||||
esp_set_cpu_freq(ESP_CPU_FREQ_160M);
|
||||
#endif
|
||||
|
||||
app_main();
|
||||
|
@ -208,6 +208,15 @@ void esp_increase_tick_cnt(const TickType_t ticks);
|
||||
extern void esp_vApplicationIdleHook( void );
|
||||
extern void esp_vApplicationTickHook( void );
|
||||
|
||||
extern const uint32_t g_esp_ticks_per_us;
|
||||
|
||||
/*
|
||||
* @brief Get FreeRTOS system idle ticks
|
||||
*
|
||||
* @return idle ticks
|
||||
*/
|
||||
TickType_t prvGetExpectedIdleTime(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -41,6 +41,8 @@
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_libc.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#include "esp8266/eagle_soc.h"
|
||||
#include "rom/ets_sys.h"
|
||||
@ -151,13 +153,9 @@ void IRAM_ATTR xPortSysTickHandle(void *p)
|
||||
*
|
||||
* So add code here to calibrate system time.
|
||||
*/
|
||||
if (_xt_tick_divisor == (CPU_FREQ_80MHz / XT_TICK_PER_SEC)) {
|
||||
ccount = soc_get_ccount();
|
||||
us = ccount / CPU_80M_TICKS_PRT_US;
|
||||
} else {
|
||||
ccount = soc_get_ccount();
|
||||
us = ccount / CPU_160M_TICKS_PRT_US;
|
||||
}
|
||||
ccount = soc_get_ccount();
|
||||
us = ccount / g_esp_ticks_per_us;
|
||||
|
||||
g_esp_os_us += us;
|
||||
g_esp_os_cpu_clk += ccount;
|
||||
|
||||
@ -166,7 +164,6 @@ void IRAM_ATTR xPortSysTickHandle(void *p)
|
||||
|
||||
ticks = us / 1000 / portTICK_PERIOD_MS;
|
||||
if (!ticks) {
|
||||
ets_printf("\r\nERROR: CCOMPARE timer period");
|
||||
ticks = 1;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ uint32_t IRAM_ATTR esp_log_early_timestamp()
|
||||
extern uint64_t g_esp_os_us;
|
||||
extern uint64_t g_esp_boot_ccount;
|
||||
|
||||
const uint32_t ticks_per_ms = _xt_tick_divisor * configTICK_RATE_HZ / 1000;
|
||||
const uint32_t ticks_per_ms = g_esp_ticks_per_us * 1000;
|
||||
const uint32_t ms = g_esp_os_us / 1000 + g_esp_boot_ccount / ((CRYSTAL_USED * 2) * 1000);
|
||||
#else
|
||||
const uint32_t ticks_per_ms = ((CRYSTAL_USED * 2) * 1000);
|
||||
|
@ -32,8 +32,8 @@
|
||||
#define ssl_memcpy memcpy
|
||||
#define ssl_strlen strlen
|
||||
|
||||
#define ssl_speed_up_enter() rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M)
|
||||
#define ssl_speed_up_exit() rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M)
|
||||
#define ssl_speed_up_enter() esp_set_cpu_freq(ESP_CPU_FREQ_160M)
|
||||
#define ssl_speed_up_exit() esp_set_cpu_freq(ESP_CPU_FREQ_80M)
|
||||
|
||||
#define SSL_DEBUG_LOG printf
|
||||
|
||||
|
Reference in New Issue
Block a user