further fix spi flash/ram current leakage

Currently, we pull up cs io for spi flash/ram to reduce current leakage during
light sleep. But some kind of spi flash/ram chip need all io pull up. Otherwise,
current leakage will still exist.
This commit is contained in:
jingli 2022-07-25 15:08:51 +08:00
parent 0d83001bd4
commit 236bd27134
13 changed files with 241 additions and 45 deletions

View File

@ -26,7 +26,7 @@
extern "C" { extern "C" {
#endif #endif
/// Type of hold a GPIO in low state // Type of hold a GPIO in low state
typedef enum { typedef enum {
GPIO_LONG_HOLD = 1, /*!< The long hold GPIO */ GPIO_LONG_HOLD = 1, /*!< The long hold GPIO */
GPIO_SHORT_HOLD = -1, /*!< The short hold GPIO */ GPIO_SHORT_HOLD = -1, /*!< The short hold GPIO */

View File

@ -22,7 +22,7 @@ menu "Hardware Settings"
config ESP_SLEEP_POWER_DOWN_FLASH config ESP_SLEEP_POWER_DOWN_FLASH
bool "Power down flash in light sleep when there is no SPIRAM" bool "Power down flash in light sleep when there is no SPIRAM"
depends on !SPIRAM depends on !SPIRAM
default y default n
help help
If enabled, chip will try to power down flash as part of esp_light_sleep_start(), which costs If enabled, chip will try to power down flash as part of esp_light_sleep_start(), which costs
more time when chip wakes up. Can only be enabled if there is no SPIRAM configured. more time when chip wakes up. Can only be enabled if there is no SPIRAM configured.
@ -58,6 +58,7 @@ menu "Hardware Settings"
config ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND config ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND
bool "PSRAM leakage current workaround in light sleep" bool "PSRAM leakage current workaround in light sleep"
depends on SPIRAM depends on SPIRAM
default y
help help
When the CS pin of SPIRAM is not pulled up, the sleep current will When the CS pin of SPIRAM is not pulled up, the sleep current will
increase during light sleep. If the CS pin of SPIRAM has an external increase during light sleep. If the CS pin of SPIRAM has an external
@ -66,11 +67,21 @@ menu "Hardware Settings"
config ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND config ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
bool "Flash leakage current workaround in light sleep" bool "Flash leakage current workaround in light sleep"
default y
help help
When the CS pin of Flash is not pulled up, the sleep current will When the CS pin of Flash is not pulled up, the sleep current will
increase during light sleep. If the CS pin of Flash has an external increase during light sleep. If the CS pin of Flash has an external
pull-up, you do not need to select this option, otherwise, you pull-up, you do not need to select this option, otherwise, you
should enable this option. should enable this option.
config ESP_SLEEP_MSPI_NEED_ALL_IO_PU
bool "All pins of mspi need pull up"
depends on ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND || ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
default y if IDF_TARGET_ESP32S3
help
To reduce leakage current, some types of SPI Flash/RAM only need to pull up the CS pin
during light sleep. But there are also some kinds of SPI Flash/RAM that need to pull up
all pins. It depends on the SPI Flash/RAM chip used.
endmenu endmenu
menu "RTC Clock Config" menu "RTC Clock Config"

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -19,15 +19,7 @@
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_private/gpio.h" #include "esp_private/gpio.h"
#include "esp_private/sleep_gpio.h" #include "esp_private/sleep_gpio.h"
#include "bootloader_common.h" #include "esp_private/spi_flash_os.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#include "esp32/spiram.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/spiram.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/spiram.h"
#endif
static const char *TAG = "sleep"; static const char *TAG = "sleep";
@ -55,24 +47,41 @@ IRAM_ATTR void gpio_sleep_mode_config_unapply(void)
void esp_sleep_config_gpio_isolate(void) void esp_sleep_config_gpio_isolate(void)
{ {
ESP_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state"); ESP_EARLY_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state");
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) { if (GPIO_IS_VALID_GPIO(gpio_num)) {
gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE); gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE);
gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING); gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING);
} }
} }
#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM #if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM
gpio_sleep_set_pull_mode(esp_spiram_get_cs_io(), GPIO_PULLUP_ONLY); gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS1), GPIO_PULLUP_ONLY);
#endif #endif // CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM
#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND #if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
gpio_sleep_set_pull_mode(bootloader_flash_get_cs_io(), GPIO_PULLUP_ONLY); gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS0), GPIO_PULLUP_ONLY);
#endif #endif // CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
#if CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CLK), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_Q), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_HD), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_WP), GPIO_PULLUP_ONLY);
#if CONFIG_SPIRAM_MODE_OCT || CONFIG_ESPTOOLPY_FLASHMODE_OPI
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_DQS), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D4), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D5), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D6), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D7), GPIO_PULLUP_ONLY);
#endif // CONFIG_SPIRAM_MODE_OCT || CONFIG_ESPTOOLPY_FLASHMODE_OPI
#endif // CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU
} }
void esp_sleep_enable_gpio_switch(bool enable) void esp_sleep_enable_gpio_switch(bool enable)
{ {
ESP_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable"); ESP_EARLY_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable");
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) { if (GPIO_IS_VALID_GPIO(gpio_num)) {
if (enable) { if (enable) {

View File

@ -11,12 +11,14 @@ if(target STREQUAL "linux")
"${target}/esp_rom_crc.c" "${target}/esp_rom_crc.c"
"${target}/esp_rom_md5.c" "${target}/esp_rom_md5.c"
"${target}/esp_rom_efuse.c") "${target}/esp_rom_efuse.c")
list(APPEND include_dirs "${IDF_PATH}/tools/mocks/soc/include")
else() else()
list(APPEND include_dirs "${target}") list(APPEND include_dirs "${target}")
list(APPEND sources "patches/esp_rom_crc.c" list(APPEND sources "patches/esp_rom_crc.c"
"patches/esp_rom_sys.c" "patches/esp_rom_sys.c"
"patches/esp_rom_uart.c" "patches/esp_rom_uart.c"
"patches/esp_rom_tjpgd.c") "patches/esp_rom_tjpgd.c"
"patches/esp_rom_efuse.c")
list(APPEND private_required_comp soc hal) list(APPEND private_required_comp soc hal)
endif() endif()

View File

@ -16,6 +16,7 @@ PROVIDE ( esp_rom_gpio_connect_out_signal = gpio_matrix_out );
PROVIDE ( esp_rom_efuse_mac_address_crc8 = esp_crc8 ); PROVIDE ( esp_rom_efuse_mac_address_crc8 = esp_crc8 );
PROVIDE ( esp_rom_efuse_get_flash_gpio_info = ets_efuse_get_spiconfig ); PROVIDE ( esp_rom_efuse_get_flash_gpio_info = ets_efuse_get_spiconfig );
PROVIDE ( esp_rom_efuse_get_flash_wp_gpio = ets_efuse_get_wp_pad ); PROVIDE ( esp_rom_efuse_get_flash_wp_gpio = ets_efuse_get_wp_pad );
PROVIDE ( esp_rom_efuse_get_opiconfig = ets_efuse_get_opiconfig );
PROVIDE ( esp_rom_efuse_is_secure_boot_enabled = ets_efuse_secure_boot_enabled ); PROVIDE ( esp_rom_efuse_is_secure_boot_enabled = ets_efuse_secure_boot_enabled );
PROVIDE ( esp_rom_uart_flush_tx = uart_tx_flush ); PROVIDE ( esp_rom_uart_flush_tx = uart_tx_flush );

View File

@ -1,16 +1,8 @@
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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 #pragma once
@ -20,6 +12,7 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "soc/soc_caps.h"
#define ESP_ROM_EFUSE_FLASH_DEFAULT_SPI (0) #define ESP_ROM_EFUSE_FLASH_DEFAULT_SPI (0)
#define ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI (1) #define ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI (1)
@ -56,6 +49,18 @@ uint32_t esp_rom_efuse_get_flash_gpio_info(void);
*/ */
uint32_t esp_rom_efuse_get_flash_wp_gpio(void); uint32_t esp_rom_efuse_get_flash_wp_gpio(void);
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
/**
* @brief Read opi flash pads configuration from Efuse
*
* @return
* - 0 for default SPI pins.
* - Other values define a custom pin configuration mask. From the LSB, every 6 bits represent a GPIO number which stand for:
* DQS, D4, D5, D6, D7 accordingly.
*/
uint32_t esp_rom_efuse_get_opiconfig(void);
#endif // SOC_SPI_MEM_SUPPORT_OPI_MODE
/** /**
* @brief Read eFuse to check whether secure boot has been enabled or not * @brief Read eFuse to check whether secure boot has been enabled or not
* *

View File

@ -1,16 +1,8 @@
// Copyright 2021 Espressif Systems (Shanghai) CO LTD /*
// * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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 "esp_rom_efuse.h" #include "esp_rom_efuse.h"
@ -49,6 +41,13 @@ uint32_t esp_rom_efuse_get_flash_wp_gpio(void)
return 0; return 0;
} }
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
uint32_t esp_rom_efuse_get_opiconfig(void)
{
return 0;
}
#endif // SOC_SPI_MEM_SUPPORT_OPI_MODE
bool esp_rom_efuse_is_secure_boot_enabled(void) bool esp_rom_efuse_is_secure_boot_enabled(void)
{ {
return false; return false;

View File

@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/efuse_reg.h"
#if CONFIG_IDF_TARGET_ESP32S3
/**
* Since rom of esp32s3 does not export function ets_efuse_get_opiconfig,
* patch this function here.
*/
uint32_t esp_rom_efuse_get_opiconfig(void)
{
uint64_t spiconfig1 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_2_REG, EFUSE_SPI_PAD_CONF_1);
uint64_t spiconfig2 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_SPI_PAD_CONF_2);
uint64_t opiconfig = (spiconfig2 << 12) | (spiconfig1 >> 20);
if (opiconfig == 0 || opiconfig == 0x3fffffffllu) {
return 0;
}
// MSBEFUSE_SPI_PAD_CONF_2(18bit) + EFUSE_SPI_PAD_CONF_1(32bit) + EFUSE_SPI_PAD_CONF_0(16bit) (LSB)
// [36:41] -- DQS
// [42:47] -- D4
// [48:53] -- D5
// [54:59] -- D6
// [60:65] -- D7
return opiconfig & 0x3fffffff;
}
#endif

View File

@ -15,6 +15,7 @@
#include <freertos/semphr.h> #include <freertos/semphr.h>
#include <soc/soc.h> #include <soc/soc.h>
#include <soc/soc_memory_layout.h> #include <soc/soc_memory_layout.h>
#include "soc/io_mux_reg.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_spi_flash.h" #include "esp_spi_flash.h"
@ -51,7 +52,18 @@
#include "esp_flash.h" #include "esp_flash.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "bootloader_flash.h" #include "bootloader_flash.h"
#include "bootloader_flash_config.h"
#include "esp_compiler.h" #include "esp_compiler.h"
#include "esp_rom_efuse.h"
#if CONFIG_SPIRAM
#ifdef CONFIG_IDF_TARGET_ESP32
#include "esp32/spiram.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/spiram.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/spiram.h"
#endif
#endif
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size); esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size);
@ -928,3 +940,84 @@ void IRAM_ATTR spi_flash_set_vendor_required_regs(void)
#endif // CONFIG_ESPTOOLPY_OCT_FLASH #endif // CONFIG_ESPTOOLPY_OCT_FLASH
} }
#endif #endif
static const uint8_t s_mspi_io_num_default[] = {
SPI_CLK_GPIO_NUM,
SPI_Q_GPIO_NUM,
SPI_D_GPIO_NUM,
SPI_CS0_GPIO_NUM,
SPI_HD_GPIO_NUM,
SPI_WP_GPIO_NUM,
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
SPI_DQS_GPIO_NUM,
SPI_D4_GPIO_NUM,
SPI_D5_GPIO_NUM,
SPI_D6_GPIO_NUM,
SPI_D7_GPIO_NUM
#endif // SOC_SPI_MEM_SUPPORT_OPI_MODE
};
uint8_t esp_mspi_get_io(esp_mspi_io_t io)
{
#if CONFIG_SPIRAM
if (io == ESP_MSPI_IO_CS1) {
return esp_spiram_get_cs_io();
}
#endif
assert(io >= ESP_MSPI_IO_CLK);
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
assert(io <= ESP_MSPI_IO_D7);
#else
assert(io <= ESP_MSPI_IO_WP);
#endif
uint8_t mspi_io = 0;
uint32_t spiconfig = 0;
if (io == ESP_MSPI_IO_WP) {
/**
* wp pad is a bit special:
* 1. since 32's efuse does not have enough bits for wp pad, so wp pad config put in flash bin header
* 2. rom code take 0x3f as invalid wp pad num, but take 0 as other invalid mspi pads num
*/
#if CONFIG_IDF_TARGET_ESP32
return bootloader_flash_get_wp_pin();
#else
spiconfig = esp_rom_efuse_get_flash_wp_gpio();
return (spiconfig == 0x3f) ? s_mspi_io_num_default[io] : spiconfig & 0x3f;
#endif
}
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
spiconfig = (io < ESP_MSPI_IO_WP) ? esp_rom_efuse_get_flash_gpio_info() : esp_rom_efuse_get_opiconfig();
#else
spiconfig = esp_rom_efuse_get_flash_gpio_info();
#endif // SOC_SPI_MEM_SUPPORT_OPI_MODE
if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) {
mspi_io = s_mspi_io_num_default[io];
} else if (io < ESP_MSPI_IO_WP) {
/**
* [0 : 5] -- CLK
* [6 :11] -- Q(D1)
* [12:17] -- D(D0)
* [18:23] -- CS
* [24:29] -- HD(D3)
*/
mspi_io = (spiconfig >> io * 6) & 0x3f;
}
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
else {
/**
* [0 : 5] -- DQS
* [6 :11] -- D4
* [12:17] -- D5
* [18:23] -- D6
* [24:29] -- D7
*/
mspi_io = (spiconfig >> (io - ESP_MSPI_IO_DQS) * 6) & 0x3f;
}
#endif // SOC_SPI_MEM_SUPPORT_OPI_MODE
return mspi_io;
}

View File

@ -34,11 +34,32 @@
#endif #endif
#include "esp_flash.h" #include "esp_flash.h"
#include "hal/spi_flash_hal.h" #include "hal/spi_flash_hal.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
// Type of MSPI IO
typedef enum {
ESP_MSPI_IO_CLK = 0,
ESP_MSPI_IO_Q,
ESP_MSPI_IO_D,
ESP_MSPI_IO_CS0, /* cs for spi flash */
ESP_MSPI_IO_HD,
ESP_MSPI_IO_WP,
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
ESP_MSPI_IO_DQS,
ESP_MSPI_IO_D4,
ESP_MSPI_IO_D5,
ESP_MSPI_IO_D6,
ESP_MSPI_IO_D7,
#endif // SOC_SPI_MEM_SUPPORT_OPI_MODE
#if CONFIG_SPIRAM
ESP_MSPI_IO_CS1 /* cs for spi ram */
#endif
} esp_mspi_io_t;
/** /**
* @brief To setup Flash chip * @brief To setup Flash chip
*/ */
@ -80,6 +101,15 @@ void spi_timing_psram_tuning(void);
*/ */
void esp_mspi_pin_init(void); void esp_mspi_pin_init(void);
/**
* @brief Get the number of the GPIO corresponding to the given MSPI io
*
* @param[in] io MSPI io
*
* @return MSPI IO number
*/
uint8_t esp_mspi_get_io(esp_mspi_io_t io);
/** /**
* @brief Set SPI1 registers to make ROM functions work * @brief Set SPI1 registers to make ROM functions work
* @note This function is used for setting SPI1 registers to the state that ROM SPI functions work * @note This function is used for setting SPI1 registers to the state that ROM SPI functions work

View File

@ -6,6 +6,7 @@ SOURCE_FILES := \
partition.c \ partition.c \
flash_ops.c \ flash_ops.c \
esp32/flash_ops_esp32.c \ esp32/flash_ops_esp32.c \
../esp_rom/linux/esp_rom_efuse.c \
) \ ) \
INCLUDE_DIRS := \ INCLUDE_DIRS := \

View File

@ -48,3 +48,8 @@ void spi_flash_enable_interrupts_caches_no_os(void)
{ {
return; return;
} }
int bootloader_flash_get_wp_pin(void)
{
return 0;
}

View File

@ -0,0 +1,9 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* NOTE: this is not the original header file from the soc component. It is a stripped-down copy to support mocking.
*/