mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(psram): allow PSRAM to enter halfsleep mode during light sleep
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -64,6 +64,8 @@
|
||||
|
||||
#define AP_HEX_PSRAM_REF_DATA 0x5a6b7c8d
|
||||
|
||||
#define AP_HEX_PSRAM_ULP_MODE_HALFSLEEP 0xF0
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
@@ -78,7 +80,7 @@ typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t vendor_id: 5;
|
||||
uint8_t rsvd0_2: 2;
|
||||
uint8_t rsvd5_7: 3;
|
||||
uint8_t ulp: 1;
|
||||
};
|
||||
uint8_t val;
|
||||
@@ -93,9 +95,9 @@ typedef struct {
|
||||
} mr2;
|
||||
union {
|
||||
struct {
|
||||
uint8_t rsvd3_7: 4;
|
||||
uint8_t rsvd0_3: 4;
|
||||
uint8_t srf: 2;
|
||||
uint8_t rsvd0: 1;
|
||||
uint8_t rsvd6: 1;
|
||||
uint8_t rbx_en: 1;
|
||||
};
|
||||
uint8_t val;
|
||||
@@ -108,6 +110,13 @@ typedef struct {
|
||||
};
|
||||
uint8_t val;
|
||||
} mr4;
|
||||
union {
|
||||
struct {
|
||||
uint8_t rsvd0_3: 4;
|
||||
uint8_t halfsleep: 4;
|
||||
};
|
||||
uint8_t val;
|
||||
} mr6;
|
||||
union {
|
||||
struct {
|
||||
uint8_t bl: 2;
|
||||
@@ -510,3 +519,83 @@ esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes)
|
||||
#endif
|
||||
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
|
||||
/******************************* Halfsleep Mode *******************************/
|
||||
static PSRAM_HALFSLEEP_DATA_ATTR struct {
|
||||
uint8_t mr4;
|
||||
bool is_hex_line_mode;
|
||||
uint64_t halfsleep_wakeup_tick;
|
||||
} s_halfsleep_ctx = {0};
|
||||
|
||||
PSRAM_HALFSLEEP_SLEEP_CODE_ATTR void esp_psram_impl_enter_halfsleep_mode(void)
|
||||
{
|
||||
// Backup line mode configuration and set to 8-line mode (MR registers R/W not support in hex line mode)
|
||||
s_halfsleep_ctx.is_hex_line_mode = psram_ctrlr_ll_is_hex_data_line_mode(PSRAM_CTRLR_LL_MSPI_ID_3);
|
||||
psram_ctrlr_ll_enable_hex_data_line_mode(PSRAM_CTRLR_LL_MSPI_ID_3, false);
|
||||
// Backup MR4
|
||||
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
|
||||
AP_HEX_PSRAM_REG_READ, AP_HEX_PSRAM_RD_CMD_BITLEN,
|
||||
0x4, AP_HEX_PSRAM_ADDR_BITLEN,
|
||||
AP_HEX_PSRAM_RD_REG_DUMMY_BITLEN,
|
||||
NULL, 0,
|
||||
&s_halfsleep_ctx.mr4, 16,
|
||||
false);
|
||||
// Set refresh rate to 0.5x
|
||||
hex_psram_mode_reg_t mode_reg;
|
||||
mode_reg.mr4.val = s_halfsleep_ctx.mr4;
|
||||
mode_reg.mr4.rf = 3; // (0:4x 1:1x 3:0.5x)
|
||||
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
|
||||
AP_HEX_PSRAM_REG_WRITE, AP_HEX_PSRAM_RD_CMD_BITLEN,
|
||||
0x4, AP_HEX_PSRAM_ADDR_BITLEN,
|
||||
0,
|
||||
&mode_reg.mr4.val, 16,
|
||||
NULL, 0,
|
||||
false);
|
||||
// Set halfsleep mode
|
||||
uint8_t halfsleep_cmd = AP_HEX_PSRAM_ULP_MODE_HALFSLEEP;
|
||||
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
|
||||
AP_HEX_PSRAM_REG_WRITE, AP_HEX_PSRAM_RD_CMD_BITLEN,
|
||||
0x6, AP_HEX_PSRAM_ADDR_BITLEN,
|
||||
0,
|
||||
&halfsleep_cmd, 16,
|
||||
NULL, 0,
|
||||
false);
|
||||
}
|
||||
|
||||
PSRAM_HALFSLEEP_SLEEP_CODE_ATTR void esp_psram_impl_exit_halfsleep_mode(void)
|
||||
{
|
||||
// Record the tick exiting halfsleep mode
|
||||
s_halfsleep_ctx.halfsleep_wakeup_tick = rtc_time_get();
|
||||
|
||||
// Do a SPI dummy write transmission to invalid address to wake up from halfsleep mode
|
||||
uint8_t null = 0;
|
||||
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
|
||||
AP_HEX_PSRAM_REG_WRITE, AP_HEX_PSRAM_WR_CMD_BITLEN,
|
||||
0xFF, AP_HEX_PSRAM_ADDR_BITLEN,
|
||||
0,
|
||||
&null, 0,
|
||||
NULL, 0,
|
||||
false);
|
||||
}
|
||||
|
||||
PSRAM_HALFSLEEP_RESUME_CODE_ATTR void esp_psram_impl_resume_from_halfsleep_mode(uint32_t slowclk_period)
|
||||
{
|
||||
uint64_t halfsleep_exit_tick = s_halfsleep_ctx.halfsleep_wakeup_tick + rtc_time_us_to_slowclk(CONFIG_PM_SLP_SPIRAM_HALFSLEEP_EXIT_WAIT_DELAY, slowclk_period);
|
||||
while (rtc_time_get() < halfsleep_exit_tick) {
|
||||
// Busy wait for PSRAM to exit halfsleep mode
|
||||
}
|
||||
|
||||
// Restore MR4 configuration (restore refresh rate)
|
||||
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
|
||||
AP_HEX_PSRAM_REG_WRITE, AP_HEX_PSRAM_WR_CMD_BITLEN,
|
||||
0x4, AP_HEX_PSRAM_ADDR_BITLEN,
|
||||
0,
|
||||
&s_halfsleep_ctx.mr4, 16,
|
||||
NULL, 0,
|
||||
false);
|
||||
|
||||
// Restore hex line mode if it was enabled before
|
||||
if (s_halfsleep_ctx.is_hex_line_mode) {
|
||||
psram_ctrlr_ll_enable_hex_data_line_mode(PSRAM_CTRLR_LL_MSPI_ID_3, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -434,6 +434,20 @@ static void config_psram_spi_phases(void)
|
||||
psram_ctrlr_ll_set_cs_pin(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_LL_CS_ID_1);
|
||||
}
|
||||
|
||||
/******************************* Halfsleep Mode *******************************/
|
||||
// This PSRAM device does not support halfsleep mode
|
||||
PSRAM_HALFSLEEP_SLEEP_CODE_ATTR void esp_psram_impl_enter_halfsleep_mode(void)
|
||||
{
|
||||
}
|
||||
|
||||
PSRAM_HALFSLEEP_SLEEP_CODE_ATTR void esp_psram_impl_exit_halfsleep_mode(void)
|
||||
{
|
||||
}
|
||||
|
||||
PSRAM_HALFSLEEP_RESUME_CODE_ATTR void esp_psram_impl_resume_from_halfsleep_mode(uint32_t slowclk_period)
|
||||
{
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------
|
||||
* Following APIs are not required to be IRAM-Safe
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -20,6 +21,21 @@ extern "C" {
|
||||
#define PSRAM_SIZE_32MB (32 * 1024 * 1024)
|
||||
#define PSRAM_SIZE_64MB (64 * 1024 * 1024)
|
||||
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define PSRAM_HALFSLEEP_DATA_ATTR SPM_DRAM_ATTR
|
||||
#define PSRAM_HALFSLEEP_SLEEP_CODE_ATTR SPM_IRAM_ATTR
|
||||
#else
|
||||
#define PSRAM_HALFSLEEP_DATA_ATTR DRAM_ATTR
|
||||
#define PSRAM_HALFSLEEP_SLEEP_CODE_ATTR IRAM_ATTR
|
||||
#endif
|
||||
#define PSRAM_HALFSLEEP_RESUME_CODE_ATTR IRAM_ATTR
|
||||
#else
|
||||
#define PSRAM_HALFSLEEP_DATA_ATTR
|
||||
#define PSRAM_HALFSLEEP_SLEEP_CODE_ATTR
|
||||
#define PSRAM_HALFSLEEP_RESUME_CODE_ATTR
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief To get the physical psram size in bytes.
|
||||
*
|
||||
@@ -51,6 +67,29 @@ esp_err_t esp_psram_impl_enable(void);
|
||||
*/
|
||||
uint8_t esp_psram_impl_get_cs_io(void);
|
||||
|
||||
/**
|
||||
* @brief Set psram to halfsleep mode to save power consumption
|
||||
*
|
||||
* It will also set refresh rate to 0.5x.
|
||||
*/
|
||||
void esp_psram_impl_enter_halfsleep_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Make psram exit halfsleep mode (no wait, wait is done in esp_psram_impl_resume_from_halfsleep_mode)
|
||||
*/
|
||||
void esp_psram_impl_exit_halfsleep_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Resume psram from halfsleep mode (also restore refresh rate)
|
||||
*
|
||||
* @param slowclk_period RTC slow clock period, calibration value obtained using rtc_clk_cal
|
||||
*
|
||||
* @note PSRAM requires some time (tHSPU) to fully recover from halfsleep mode.
|
||||
* This function examines the time between exiting halfsleep mode and current time, and busy wait if the time is not long enough.
|
||||
* This shortens the overall busy loop time if wait is done inside esp_psram_impl_exit_halfsleep_mode.
|
||||
*/
|
||||
void esp_psram_impl_resume_from_halfsleep_mode(uint32_t slowclk_period);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user