mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
Merge branch 'feature/support_i2s_retention' into 'master'
feat(i2s): support sleep retention Closes IDF-8468, IDF-9754, IDF-9783, and IDF-10343 See merge request espressif/esp-idf!33529
This commit is contained in:
commit
16d99f3e10
@ -41,6 +41,9 @@
|
||||
|
||||
#include "esp_private/i2s_platform.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#endif
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_private/gpio.h"
|
||||
@ -85,6 +88,34 @@ inline void *i2s_dma_calloc(i2s_chan_handle_t handle, size_t num, size_t size)
|
||||
Scope: This file only
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#if I2S_USE_RETENTION_LINK
|
||||
static esp_err_t s_i2s_create_sleep_retention_link_cb(void *arg)
|
||||
{
|
||||
i2s_controller_t *i2s_obj = (i2s_controller_t *)arg;
|
||||
ESP_RETURN_ON_ERROR(sleep_retention_entries_create(i2s_reg_retention_info[i2s_obj->id].entry_array,
|
||||
i2s_reg_retention_info[i2s_obj->id].array_size,
|
||||
REGDMA_LINK_PRI_I2S, i2s_obj->slp_retention_mod),
|
||||
TAG, "create retention link failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void s_i2s_create_retention_module(i2s_controller_t *i2s_obj)
|
||||
{
|
||||
sleep_retention_module_t module = i2s_obj->slp_retention_mod;
|
||||
|
||||
_lock_acquire(&i2s_obj->mutex);
|
||||
if (i2s_obj->retention_link_created == false) {
|
||||
if (sleep_retention_module_allocate(module) != ESP_OK) {
|
||||
// even though the sleep retention module create failed, I2S driver should still work, so just warning here
|
||||
ESP_LOGW(TAG, "create retention module failed, power domain can't turn off");
|
||||
} else {
|
||||
i2s_obj->retention_link_created = true;
|
||||
}
|
||||
}
|
||||
_lock_release(&i2s_obj->mutex);
|
||||
}
|
||||
#endif // I2S_USE_RETENTION_LINK
|
||||
|
||||
static void i2s_tx_channel_start(i2s_chan_handle_t handle)
|
||||
{
|
||||
i2s_hal_tx_reset(&(handle->controller->hal));
|
||||
@ -175,6 +206,14 @@ static esp_err_t i2s_destroy_controller_obj(i2s_controller_t **i2s_obj)
|
||||
#if SOC_I2S_HW_VERSION_1
|
||||
i2s_ll_enable_dma((*i2s_obj)->hal.dev, false);
|
||||
#endif
|
||||
#if I2S_USE_RETENTION_LINK
|
||||
if ((*i2s_obj)->slp_retention_mod) {
|
||||
if ((*i2s_obj)->retention_link_created) {
|
||||
sleep_retention_module_free((*i2s_obj)->slp_retention_mod);
|
||||
}
|
||||
sleep_retention_module_deinit((*i2s_obj)->slp_retention_mod);
|
||||
}
|
||||
#endif // I2S_USE_RETENTION_LINK
|
||||
free(*i2s_obj);
|
||||
*i2s_obj = NULL;
|
||||
return i2s_platform_release_occupation(I2S_CTLR_HP, id);
|
||||
@ -219,6 +258,25 @@ static i2s_controller_t *i2s_acquire_controller_obj(int id)
|
||||
adc_ll_digi_set_data_source(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if I2S_USE_RETENTION_LINK
|
||||
sleep_retention_module_t module = i2s_reg_retention_info[id].retention_module;
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = {
|
||||
.create = {
|
||||
.handle = s_i2s_create_sleep_retention_link_cb,
|
||||
.arg = i2s_obj,
|
||||
},
|
||||
},
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
|
||||
};
|
||||
if (sleep_retention_module_init(module, &init_param) == ESP_OK) {
|
||||
i2s_obj->slp_retention_mod = module;
|
||||
} else {
|
||||
// even the sleep retention module init failed, I2S driver should still work, so just warning here
|
||||
ESP_LOGW(TAG, "init sleep retention failed for I2S%d, power domain may be turned off during sleep", id);
|
||||
}
|
||||
#endif // I2S_USE_RETENTION_LINK
|
||||
} else {
|
||||
free(pre_alloc);
|
||||
portENTER_CRITICAL(&g_i2s.spinlock);
|
||||
@ -879,6 +937,9 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *
|
||||
ESP_RETURN_ON_FALSE(chan_cfg->id < SOC_I2S_NUM || chan_cfg->id == I2S_NUM_AUTO, ESP_ERR_INVALID_ARG, TAG, "invalid I2S port id");
|
||||
ESP_RETURN_ON_FALSE(chan_cfg->dma_desc_num >= 2, ESP_ERR_INVALID_ARG, TAG, "there should be at least 2 DMA buffers");
|
||||
ESP_RETURN_ON_FALSE(chan_cfg->intr_priority >= 0 && chan_cfg->intr_priority <= 7, ESP_ERR_INVALID_ARG, TAG, "intr_priority should be within 0~7");
|
||||
#if !SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(!chan_cfg->allow_pd, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#endif
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
i2s_controller_t *i2s_obj = NULL;
|
||||
@ -937,6 +998,11 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *
|
||||
if ((tx_handle != NULL) && (rx_handle != NULL)) {
|
||||
i2s_obj->full_duplex = true;
|
||||
}
|
||||
#if I2S_USE_RETENTION_LINK
|
||||
if (chan_cfg->allow_pd) {
|
||||
s_i2s_create_retention_module(i2s_obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
/* i2s_obj allocated but register channel failed */
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sys/lock.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
@ -25,6 +26,9 @@
|
||||
#endif
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/esp_gpio_reserve.h"
|
||||
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#endif
|
||||
#include "esp_pm.h"
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
@ -56,6 +60,8 @@ extern "C" {
|
||||
#define I2S_RCC_ATOMIC()
|
||||
#endif
|
||||
|
||||
#define I2S_USE_RETENTION_LINK (SOC_I2S_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
|
||||
#define I2S_NULL_POINTER_CHECK(tag, p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, tag, "input parameter '"#p"' is NULL")
|
||||
|
||||
/**
|
||||
@ -130,6 +136,11 @@ typedef struct {
|
||||
bool full_duplex; /*!< is full_duplex */
|
||||
i2s_chan_handle_t tx_chan; /*!< tx channel handler */
|
||||
i2s_chan_handle_t rx_chan; /*!< rx channel handler */
|
||||
_lock_t mutex; /*!< mutex for controller */
|
||||
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
sleep_retention_module_t slp_retention_mod; /*!< Sleep retention module */
|
||||
bool retention_link_created; /*!< Whether the retention link is created */
|
||||
#endif
|
||||
int mclk; /*!< MCK out pin, shared by tx/rx*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
esp_clock_output_mapping_handle_t mclk_out_hdl; /*!< The handle of MCLK output signal */
|
||||
|
@ -26,6 +26,7 @@ extern "C" {
|
||||
.dma_frame_num = 240, \
|
||||
.auto_clear_after_cb = false, \
|
||||
.auto_clear_before_cb = false, \
|
||||
.allow_pd = false, \
|
||||
.intr_priority = 0, \
|
||||
}
|
||||
|
||||
@ -73,6 +74,10 @@ typedef struct {
|
||||
bool auto_clear_before_cb; /*!< Set to auto clear DMA TX buffer before `on_sent` callback, I2S will always send zero automatically if no data to send
|
||||
* So that user can access data in the callback that just finished to send.
|
||||
*/
|
||||
bool allow_pd; /*!< Set to allow power down. When this flag set, the driver will backup/restore the I2S registers before/after entering/exist sleep mode.
|
||||
* By this approach, the system can power off I2S's power domain.
|
||||
* This can save power, but at the expense of more RAM being consumed.
|
||||
*/
|
||||
int intr_priority; /*!< I2S interrupt priority, range [0, 7], if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) */
|
||||
} i2s_chan_config_t;
|
||||
|
||||
|
@ -3,10 +3,6 @@
|
||||
components/esp_driver_i2s/test_apps/i2s:
|
||||
disable:
|
||||
- if: SOC_I2S_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c5"
|
||||
temporary: true
|
||||
reason: target test failed # TODO [ESP32C5] IDF-10343
|
||||
depends_components:
|
||||
- esp_driver_i2s
|
||||
- esp_driver_pcnt
|
||||
|
@ -1,11 +1,12 @@
|
||||
set(srcs "test_app_main.c"
|
||||
"test_i2s.c"
|
||||
"test_i2s_iram.c")
|
||||
"test_i2s_iram.c"
|
||||
"test_i2s_sleep.c")
|
||||
|
||||
if(CONFIG_SOC_I2S_SUPPORTS_ETM AND CONFIG_SOC_GPIO_SUPPORT_ETM)
|
||||
set(srcs ${srcs} "test_i2s_etm.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES unity esp_driver_pcnt spi_flash esp_driver_gpio esp_driver_i2s
|
||||
PRIV_REQUIRES unity esp_driver_pcnt spi_flash esp_driver_gpio esp_driver_i2s esp_driver_uart
|
||||
WHOLE_ARCHIVE)
|
||||
|
@ -94,7 +94,7 @@ static void i2s_test_io_config(int mode)
|
||||
}
|
||||
}
|
||||
|
||||
static void i2s_read_write_test(i2s_chan_handle_t tx_chan, i2s_chan_handle_t rx_chan)
|
||||
void i2s_read_write_test(i2s_chan_handle_t tx_chan, i2s_chan_handle_t rx_chan)
|
||||
{
|
||||
#define I2S_SEND_BUF_LEN 100
|
||||
#define I2S_RECV_BUF_LEN 10000
|
||||
@ -776,7 +776,7 @@ static void i2s_test_common_sample_rate(i2s_chan_handle_t rx_chan, i2s_std_clk_c
|
||||
printf("[%"PRIu32" Hz] %d pulses, expected %d, err %d\n", test_freq[i], real_pulse, expt_pulse, real_pulse - expt_pulse);
|
||||
TEST_ESP_OK(i2s_channel_disable(rx_chan));
|
||||
// Check if the error between real pulse number and expected pulse number is within 1%
|
||||
TEST_ASSERT_INT_WITHIN(expt_pulse * 0.01, expt_pulse, real_pulse);
|
||||
TEST_ASSERT_INT_WITHIN(expt_pulse * 0.02, expt_pulse, real_pulse);
|
||||
}
|
||||
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
|
||||
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
|
||||
|
145
components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c
Normal file
145
components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "unity.h"
|
||||
#include "unity_test_utils.h"
|
||||
#include "driver/i2s_std.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/i2s_struct.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_private/sleep_cpu.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "../../test_inc/test_i2s.h"
|
||||
|
||||
#define TEST_I2S_PD_SLEEP (SOC_I2S_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
|
||||
extern void i2s_read_write_test(i2s_chan_handle_t tx_chan, i2s_chan_handle_t rx_chan);
|
||||
|
||||
static void s_test_i2s_enter_light_sleep(int sec, bool allow_power_down)
|
||||
{
|
||||
esp_sleep_context_t sleep_ctx;
|
||||
esp_sleep_set_sleep_context(&sleep_ctx);
|
||||
printf("Entering light sleep for %d seconds\n", sec);
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
printf("Enable CPU power down\n");
|
||||
TEST_ESP_OK(sleep_cpu_configure(true));
|
||||
#endif
|
||||
uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(sec * 1000 * 1000));
|
||||
TEST_ESP_OK(esp_light_sleep_start());
|
||||
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
TEST_ESP_OK(sleep_cpu_configure(false));
|
||||
#endif
|
||||
printf("Woke up from light sleep\n");
|
||||
|
||||
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
|
||||
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
// check if the power domain also is powered down
|
||||
TEST_ASSERT_EQUAL(allow_power_down ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
|
||||
#endif
|
||||
esp_sleep_set_sleep_context(NULL);
|
||||
}
|
||||
|
||||
static void s_test_i2s_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle, bool allow_power_down)
|
||||
{
|
||||
/* Enter light sleep before I2S channel enabled and wake up after 1 second */
|
||||
s_test_i2s_enter_light_sleep(1, allow_power_down);
|
||||
/* Check whether I2S can work correctly after light sleep */
|
||||
TEST_ESP_OK(i2s_channel_enable(tx_handle));
|
||||
TEST_ESP_OK(i2s_channel_enable(rx_handle));
|
||||
i2s_read_write_test(tx_handle, rx_handle);
|
||||
}
|
||||
|
||||
static void s_test_i2s_power_on_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle)
|
||||
{
|
||||
s_test_i2s_sleep(tx_handle, rx_handle, false);
|
||||
}
|
||||
|
||||
#if TEST_I2S_PD_SLEEP
|
||||
static void s_test_i2s_power_down_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle)
|
||||
{
|
||||
#if SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
s_test_i2s_sleep(tx_handle, rx_handle, true);
|
||||
#else
|
||||
/* I2S retention is depended on GDMA retention.
|
||||
* Only take two registers as sample to check the I2S retention when GDMA retention has not been supported. */
|
||||
i2s_tx_conf_reg_t tx_reg_before_slp = I2S0.tx_conf;
|
||||
i2s_rx_conf_reg_t rx_reg_before_slp = I2S0.rx_conf;
|
||||
/* Enter light sleep before I2S channel enabled and wake up after 1 second */
|
||||
s_test_i2s_enter_light_sleep(1, true);
|
||||
/* Only check whether the register values are restored if GDMA retention has not been supported */
|
||||
i2s_tx_conf_reg_t tx_reg_after_slp = I2S0.tx_conf;
|
||||
i2s_rx_conf_reg_t rx_reg_after_slp = I2S0.rx_conf;
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT32(tx_reg_before_slp.val, tx_reg_after_slp.val);
|
||||
TEST_ASSERT_EQUAL_UINT32(rx_reg_before_slp.val, rx_reg_after_slp.val);
|
||||
|
||||
TEST_ESP_OK(i2s_channel_enable(tx_handle));
|
||||
TEST_ESP_OK(i2s_channel_enable(rx_handle));
|
||||
|
||||
tx_reg_before_slp.val = I2S0.tx_conf.val;
|
||||
rx_reg_before_slp.val = I2S0.rx_conf.val;
|
||||
/* Enter light sleep before I2S channel enabled and wake up after 1 second */
|
||||
s_test_i2s_enter_light_sleep(1, true);
|
||||
/* Only check whether the register values are restored if GDMA retention has not been supported */
|
||||
tx_reg_after_slp.val = I2S0.tx_conf.val;
|
||||
rx_reg_after_slp.val = I2S0.rx_conf.val;
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT32(tx_reg_before_slp.val, tx_reg_after_slp.val);
|
||||
TEST_ASSERT_EQUAL_UINT32(rx_reg_before_slp.val, rx_reg_after_slp.val);
|
||||
#endif // SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
}
|
||||
#endif // TEST_I2S_PD_SLEEP
|
||||
|
||||
void test_i2s_sleep_usability(bool allow_power_down)
|
||||
{
|
||||
i2s_chan_handle_t tx_handle;
|
||||
i2s_chan_handle_t rx_handle;
|
||||
|
||||
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
|
||||
chan_cfg.allow_pd = allow_power_down;
|
||||
i2s_std_config_t std_cfg = {
|
||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
|
||||
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(SAMPLE_BITS, I2S_SLOT_MODE_STEREO),
|
||||
.gpio_cfg = I2S_TEST_MASTER_DEFAULT_PIN,
|
||||
};
|
||||
std_cfg.gpio_cfg.din = std_cfg.gpio_cfg.dout;
|
||||
TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
|
||||
TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
|
||||
TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
|
||||
|
||||
if (!allow_power_down) {
|
||||
s_test_i2s_power_on_sleep(tx_handle, rx_handle);
|
||||
}
|
||||
#if TEST_I2S_PD_SLEEP
|
||||
else {
|
||||
s_test_i2s_power_down_sleep(tx_handle, rx_handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("I2S works as expected after light sleep\n");
|
||||
|
||||
TEST_ESP_OK(i2s_channel_disable(tx_handle));
|
||||
TEST_ESP_OK(i2s_channel_disable(rx_handle));
|
||||
TEST_ESP_OK(i2s_del_channel(tx_handle));
|
||||
TEST_ESP_OK(i2s_del_channel(rx_handle));
|
||||
}
|
||||
|
||||
TEST_CASE("I2S_light_sleep_usability_test", "[i2s]")
|
||||
{
|
||||
printf("\nTesting I2S power on light sleep...\n");
|
||||
test_i2s_sleep_usability(false);
|
||||
#if TEST_I2S_PD_SLEEP
|
||||
printf("\nTesting I2S power down light sleep...\n");
|
||||
test_i2s_sleep_usability(true);
|
||||
#endif
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
@ -7,7 +7,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32c3
|
||||
# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF-10343
|
||||
@pytest.mark.esp32c5
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32h2
|
||||
|
@ -3,3 +3,4 @@ CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
|
||||
|
@ -1,2 +1,4 @@
|
||||
CONFIG_I2S_ENABLE_DEBUG_LOG=y
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
# primitives for checking sleep internal state
|
||||
CONFIG_ESP_SLEEP_DEBUG=y
|
||||
|
@ -293,6 +293,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m
|
||||
}, \
|
||||
.backup_clk = ( \
|
||||
BIT(PMU_ICG_FUNC_ENA_REGDMA) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_GDMA) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG0) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG1) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_HPBUS) | \
|
||||
|
@ -292,6 +292,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m
|
||||
}, \
|
||||
.backup_clk = ( \
|
||||
BIT(PMU_ICG_FUNC_ENA_REGDMA) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_GDMA) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG0) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG1) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_HPBUS) | \
|
||||
|
@ -29,7 +29,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sig = I2S0I_DATA_IN15_IDX,
|
||||
|
||||
.irq = ETS_I2S0_INTR_SOURCE,
|
||||
.module = PERIPH_I2S0_MODULE,
|
||||
},
|
||||
{
|
||||
.mck_out_sig = -1, // Unavailable
|
||||
@ -49,6 +48,5 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sig = I2S1I_DATA_IN15_IDX,
|
||||
|
||||
.irq = ETS_I2S1_INTR_SOURCE,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
@ -30,6 +30,5 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sig = I2SI_SD_IN_IDX,
|
||||
|
||||
.irq = ETS_I2S1_INTR_SOURCE,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
/*
|
||||
@ -30,6 +31,43 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sig = I2SI_SD_IN_IDX,
|
||||
|
||||
.irq = ETS_I2S1_INTR_SOURCE,
|
||||
.module = -1,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* I2S Registers to be saved during sleep retention
|
||||
* - I2S_RX_CONF_REG
|
||||
* - I2S_TX_CONF_REG
|
||||
* - I2S_RX_CONF1_REG
|
||||
* - I2S_TX_CONF1_REG
|
||||
* - I2S_TX_PCM2PDM_CONF_REG
|
||||
* - I2S_TX_PCM2PDM_CONF1_REG
|
||||
* - I2S_RX_TDM_CTRL_REG
|
||||
* - I2S_TX_TDM_CTRL_REG
|
||||
* - I2S_RXEOF_NUM_REG
|
||||
* - I2S_ETM_CONF_REG
|
||||
*/
|
||||
#define I2S_RETENTION_REGS_CNT 10
|
||||
#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG(i)
|
||||
static const uint32_t i2s_regs_map[4] = {0x12360f, 0x0, 0x0, 0x0};
|
||||
#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \
|
||||
/* Save/restore the register values */ \
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \
|
||||
REGDMA_I2S_LINK(0x00), \
|
||||
I2S_RETENTION_REGS_BASE(i2s_port), \
|
||||
I2S_RETENTION_REGS_BASE(i2s_port), \
|
||||
I2S_RETENTION_REGS_CNT, 0, 0, \
|
||||
i2s_regs_map[0], i2s_regs_map[1], \
|
||||
i2s_regs_map[2], i2s_regs_map[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2)}, \
|
||||
};
|
||||
|
||||
static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(0);
|
||||
|
||||
const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = {
|
||||
[0] = {
|
||||
.retention_module = SLEEP_RETENTION_MODULE_I2S0,
|
||||
.entry_array = i2s0_regs_retention,
|
||||
.array_size = ARRAY_SIZE(i2s0_regs_retention)
|
||||
},
|
||||
};
|
||||
|
@ -675,6 +675,10 @@ config SOC_I2S_TDM_FULL_DATA_WIDTH
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
@ -36,6 +36,7 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_RMT0 = 13,
|
||||
SLEEP_RETENTION_MODULE_UART0 = 14,
|
||||
SLEEP_RETENTION_MODULE_UART1 = 15,
|
||||
SLEEP_RETENTION_MODULE_I2S0 = 16,
|
||||
|
||||
/* modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
|
||||
@ -74,6 +75,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0),
|
||||
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
|
||||
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
|
||||
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
|
||||
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0),
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1),
|
||||
@ -94,6 +96,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_RMT0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_UART0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_UART1 \
|
||||
| SLEEP_RETENTION_MODULE_BM_I2S0 \
|
||||
)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -288,6 +288,7 @@
|
||||
#define SOC_I2S_PDM_MAX_TX_LINES (2)
|
||||
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||
#define SOC_I2S_TDM_FULL_DATA_WIDTH (1) /*!< No limitation to data bit width when using multiple slots */
|
||||
#define SOC_I2S_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up I2S registers before sleep */
|
||||
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
|
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
/*
|
||||
@ -30,6 +31,43 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sig = I2SI_SD_IN_IDX,
|
||||
|
||||
.irq = ETS_I2S1_INTR_SOURCE,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* I2S Registers to be saved during sleep retention
|
||||
* - I2S_RX_CONF_REG
|
||||
* - I2S_TX_CONF_REG
|
||||
* - I2S_RX_CONF1_REG
|
||||
* - I2S_TX_CONF1_REG
|
||||
* - I2S_TX_PCM2PDM_CONF_REG
|
||||
* - I2S_TX_PCM2PDM_CONF1_REG
|
||||
* - I2S_RX_TDM_CTRL_REG
|
||||
* - I2S_TX_TDM_CTRL_REG
|
||||
* - I2S_RXEOF_NUM_REG
|
||||
* - I2S_ETM_CONF_REG
|
||||
*/
|
||||
#define I2S_RETENTION_REGS_CNT 10
|
||||
#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG(i)
|
||||
static const uint32_t i2s_regs_map[4] = {0x12330f, 0x0, 0x0, 0x0};
|
||||
#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \
|
||||
/* Save/restore the register values */ \
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \
|
||||
REGDMA_I2S_LINK(0x00), \
|
||||
I2S_RETENTION_REGS_BASE(i2s_port), \
|
||||
I2S_RETENTION_REGS_BASE(i2s_port), \
|
||||
I2S_RETENTION_REGS_CNT, 0, 0, \
|
||||
i2s_regs_map[0], i2s_regs_map[1], \
|
||||
i2s_regs_map[2], i2s_regs_map[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2)}, \
|
||||
};
|
||||
|
||||
static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(0);
|
||||
|
||||
const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = {
|
||||
[0] = {
|
||||
.retention_module = SLEEP_RETENTION_MODULE_I2S0,
|
||||
.entry_array = i2s0_regs_retention,
|
||||
.array_size = ARRAY_SIZE(i2s0_regs_retention)
|
||||
},
|
||||
};
|
||||
|
@ -671,6 +671,10 @@ config SOC_I2S_SUPPORTS_TDM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
@ -36,6 +36,7 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_RMT0 = 13,
|
||||
SLEEP_RETENTION_MODULE_UART0 = 14,
|
||||
SLEEP_RETENTION_MODULE_UART1 = 15,
|
||||
SLEEP_RETENTION_MODULE_I2S0 = 16,
|
||||
|
||||
/* Modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
|
||||
@ -68,6 +69,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0),
|
||||
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
|
||||
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
|
||||
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
|
||||
/* modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC),
|
||||
SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB),
|
||||
@ -90,6 +92,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_RMT0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_UART0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_UART1 \
|
||||
| SLEEP_RETENTION_MODULE_BM_I2S0 \
|
||||
)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -273,6 +273,7 @@
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_PDM_MAX_TX_LINES (2)
|
||||
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||
#define SOC_I2S_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up I2S registers before sleep */
|
||||
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
|
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
/*
|
||||
@ -29,6 +30,43 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sig = I2SI_SD_IN_IDX,
|
||||
|
||||
.irq = ETS_I2S1_INTR_SOURCE,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* I2S Registers to be saved during sleep retention
|
||||
* - I2S_RX_CONF_REG
|
||||
* - I2S_TX_CONF_REG
|
||||
* - I2S_RX_CONF1_REG
|
||||
* - I2S_TX_CONF1_REG
|
||||
* - I2S_TX_PCM2PDM_CONF_REG
|
||||
* - I2S_TX_PCM2PDM_CONF1_REG
|
||||
* - I2S_RX_TDM_CTRL_REG
|
||||
* - I2S_TX_TDM_CTRL_REG
|
||||
* - I2S_RXEOF_NUM_REG
|
||||
* - I2S_ETM_CONF_REG
|
||||
*/
|
||||
#define I2S_RETENTION_REGS_CNT 10
|
||||
#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG
|
||||
static const uint32_t i2s_regs_map[4] = {0x12330f, 0x0, 0x0, 0x0};
|
||||
#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \
|
||||
/* Save/restore the register values */ \
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \
|
||||
REGDMA_I2S_LINK(0x00), \
|
||||
I2S_RETENTION_REGS_BASE(i2s_port), \
|
||||
I2S_RETENTION_REGS_BASE(i2s_port), \
|
||||
I2S_RETENTION_REGS_CNT, 0, 0, \
|
||||
i2s_regs_map[0], i2s_regs_map[1], \
|
||||
i2s_regs_map[2], i2s_regs_map[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2)}, \
|
||||
};
|
||||
|
||||
static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(0);
|
||||
|
||||
const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = {
|
||||
[0] = {
|
||||
.retention_module = SLEEP_RETENTION_MODULE_I2S0,
|
||||
.entry_array = i2s0_regs_retention,
|
||||
.array_size = ARRAY_SIZE(i2s0_regs_retention)
|
||||
},
|
||||
};
|
||||
|
@ -675,6 +675,10 @@ config SOC_I2S_TDM_FULL_DATA_WIDTH
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
@ -37,6 +37,7 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_RMT0 = 14,
|
||||
SLEEP_RETENTION_MODULE_UART0 = 15,
|
||||
SLEEP_RETENTION_MODULE_UART1 = 16,
|
||||
SLEEP_RETENTION_MODULE_I2S0 = 17,
|
||||
|
||||
/* Modem module, which includes BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BLE_MAC = 28,
|
||||
@ -68,6 +69,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0),
|
||||
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
|
||||
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
|
||||
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
|
||||
/* modem module, which includes BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC),
|
||||
SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB),
|
||||
@ -89,6 +91,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_RMT0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_UART0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_UART1 \
|
||||
| SLEEP_RETENTION_MODULE_BM_I2S0 \
|
||||
)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -274,6 +274,7 @@
|
||||
#define SOC_I2S_PDM_MAX_TX_LINES (2)
|
||||
#define SOC_I2S_SUPPORTS_TDM (1)
|
||||
#define SOC_I2S_TDM_FULL_DATA_WIDTH (1) /*!< No limitation to data bit width when using multiple slots */
|
||||
#define SOC_I2S_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up I2S registers before sleep */
|
||||
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/lp_gpio_sig_map.h"
|
||||
|
||||
@ -34,7 +35,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sigs[3] = I2S0_I_SD3_PAD_IN_IDX,
|
||||
|
||||
.irq = ETS_I2S0_INTR_SOURCE,
|
||||
.module = PERIPH_I2S0_MODULE,
|
||||
},
|
||||
[1] = {
|
||||
.mck_out_sig = I2S1_MCLK_PAD_OUT_IDX,
|
||||
@ -58,7 +58,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sigs[3] = -1,
|
||||
|
||||
.irq = ETS_I2S1_INTR_SOURCE,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
},
|
||||
[2] = {
|
||||
.mck_out_sig = I2S2_MCLK_PAD_OUT_IDX,
|
||||
@ -82,7 +81,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sigs[3] = -1,
|
||||
|
||||
.irq = ETS_I2S2_INTR_SOURCE,
|
||||
.module = PERIPH_I2S2_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
@ -111,3 +109,54 @@ const i2s_signal_conn_t lp_i2s_periph_signal[SOC_LP_I2S_NUM] = {
|
||||
.irq = ETS_LP_I2S_INTR_SOURCE,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* I2S Registers to be saved during sleep retention
|
||||
* - I2S_RX_CONF_REG
|
||||
* - I2S_TX_CONF_REG
|
||||
* - I2S_RX_CONF1_REG
|
||||
* - I2S_TX_CONF1_REG
|
||||
* - I2S_TX_PCM2PDM_CONF_REG
|
||||
* - I2S_TX_PCM2PDM_CONF1_REG
|
||||
* - I2S_RX_PDM2PCM_CONF_REG
|
||||
* - I2S_RX_TDM_CTRL_REG
|
||||
* - I2S_TX_TDM_CTRL_REG
|
||||
* - I2S_RXEOF_NUM_REG
|
||||
* - I2S_ETM_CONF_REG
|
||||
*/
|
||||
#define I2S_RETENTION_REGS_CNT 11
|
||||
#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG(i)
|
||||
static const uint32_t i2s_regs_map[4] = {0x12370f, 0x0, 0x0, 0x0};
|
||||
#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \
|
||||
/* Save/restore the register values */ \
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \
|
||||
REGDMA_I2S_LINK(0x00), \
|
||||
I2S_RETENTION_REGS_BASE(i2s_port), \
|
||||
I2S_RETENTION_REGS_BASE(i2s_port), \
|
||||
I2S_RETENTION_REGS_CNT, 0, 0, \
|
||||
i2s_regs_map[0], i2s_regs_map[1], \
|
||||
i2s_regs_map[2], i2s_regs_map[3]), \
|
||||
.owner = ENTRY(0)}, \
|
||||
};
|
||||
|
||||
static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(0);
|
||||
static const regdma_entries_config_t i2s1_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(1);
|
||||
static const regdma_entries_config_t i2s2_regs_retention[] = I2S_SLEEP_RETENTION_ENTRIES(2);
|
||||
|
||||
const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = {
|
||||
[0] = {
|
||||
.retention_module = SLEEP_RETENTION_MODULE_I2S0,
|
||||
.entry_array = i2s0_regs_retention,
|
||||
.array_size = ARRAY_SIZE(i2s0_regs_retention)
|
||||
},
|
||||
[1] = {
|
||||
.retention_module = SLEEP_RETENTION_MODULE_I2S1,
|
||||
.entry_array = i2s1_regs_retention,
|
||||
.array_size = ARRAY_SIZE(i2s1_regs_retention)
|
||||
},
|
||||
[2] = {
|
||||
.retention_module = SLEEP_RETENTION_MODULE_I2S2,
|
||||
.entry_array = i2s2_regs_retention,
|
||||
.array_size = ARRAY_SIZE(i2s2_regs_retention)
|
||||
},
|
||||
};
|
||||
|
@ -843,6 +843,10 @@ config SOC_I2S_TDM_FULL_DATA_WIDTH
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_I2S_NUM
|
||||
int
|
||||
default 1
|
||||
|
@ -41,6 +41,10 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_AXI_DMA_CH1 = 17,
|
||||
SLEEP_RETENTION_MODULE_AXI_DMA_CH2 = 18,
|
||||
|
||||
SLEEP_RETENTION_MODULE_I2S0 = 19,
|
||||
SLEEP_RETENTION_MODULE_I2S1 = 20,
|
||||
SLEEP_RETENTION_MODULE_I2S2 = 21,
|
||||
|
||||
SLEEP_RETENTION_MODULE_MAX = 31
|
||||
} periph_retention_module_t;
|
||||
|
||||
@ -70,6 +74,9 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_UART3 = BIT(SLEEP_RETENTION_MODULE_UART3),
|
||||
SLEEP_RETENTION_MODULE_BM_UART4 = BIT(SLEEP_RETENTION_MODULE_UART4),
|
||||
SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0),
|
||||
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
|
||||
SLEEP_RETENTION_MODULE_BM_I2S1 = BIT(SLEEP_RETENTION_MODULE_I2S1),
|
||||
SLEEP_RETENTION_MODULE_BM_I2S2 = BIT(SLEEP_RETENTION_MODULE_I2S2),
|
||||
|
||||
SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1
|
||||
} periph_retention_module_bitmap_t;
|
||||
@ -91,6 +98,9 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_UART3 \
|
||||
| SLEEP_RETENTION_MODULE_BM_UART4 \
|
||||
| SLEEP_RETENTION_MODULE_BM_RMT0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_I2S0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_I2S1 \
|
||||
| SLEEP_RETENTION_MODULE_BM_I2S2 \
|
||||
)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -328,6 +328,7 @@
|
||||
#define SOC_I2S_PDM_MAX_TX_LINES (2) // On I2S0
|
||||
#define SOC_I2S_PDM_MAX_RX_LINES (4) // On I2S0
|
||||
#define SOC_I2S_TDM_FULL_DATA_WIDTH (1) /*!< No limitation to data bit width when using multiple slots */
|
||||
#define SOC_I2S_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up I2S registers before sleep */
|
||||
|
||||
/*-------------------------- LP_I2S CAPS -------------------------------------*/
|
||||
#define SOC_LP_I2S_NUM (1U)
|
||||
|
@ -29,6 +29,5 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sig = I2S0I_DATA_IN15_IDX,
|
||||
|
||||
.irq = ETS_I2S0_INTR_SOURCE,
|
||||
.module = PERIPH_I2S0_MODULE,
|
||||
}
|
||||
};
|
||||
|
@ -33,7 +33,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sigs[3] = I2S0I_SD3_IN_IDX,
|
||||
|
||||
.irq = ETS_I2S0_INTR_SOURCE,
|
||||
.module = PERIPH_I2S0_MODULE,
|
||||
},
|
||||
{
|
||||
.mck_out_sig = I2S1_MCLK_OUT_IDX,
|
||||
@ -57,6 +56,5 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
|
||||
.data_in_sigs[3] = -1,
|
||||
|
||||
.irq = ETS_I2S1_INTR_SOURCE,
|
||||
.module = PERIPH_I2S1_MODULE,
|
||||
}
|
||||
};
|
||||
|
@ -1,13 +1,17 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "soc/soc.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "soc/interrupts.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/regdma.h"
|
||||
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
#include "soc/retention_periph_defs.h"
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTED
|
||||
#include "soc/i2s_struct.h"
|
||||
@ -51,7 +55,6 @@ typedef struct {
|
||||
};
|
||||
|
||||
const uint8_t irq;
|
||||
const periph_module_t module;
|
||||
} i2s_signal_conn_t;
|
||||
|
||||
extern const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM];
|
||||
@ -62,6 +65,16 @@ extern const i2s_signal_conn_t lp_i2s_periph_signal[SOC_LP_I2S_NUM];
|
||||
|
||||
#endif // SOC_I2S_SUPPORTED
|
||||
|
||||
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
typedef struct {
|
||||
const periph_retention_module_t retention_module;
|
||||
const regdma_entries_config_t *entry_array;
|
||||
uint32_t array_size;
|
||||
} i2s_reg_retention_info_t;
|
||||
|
||||
extern const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM];
|
||||
#endif // SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -53,6 +53,7 @@ extern "C" {
|
||||
#define REGDMA_TG1_WDT_LINK(_pri) ((0x1B << 8) | _pri)
|
||||
#define REGDMA_TG0_TIMER_LINK(_pri) ((0x1C << 8) | _pri)
|
||||
#define REGDMA_TG1_TIMER_LINK(_pri) ((0x1D << 8) | _pri)
|
||||
#define REGDMA_I2S_LINK(_pri) ((0x1E << 8) | _pri)
|
||||
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
|
||||
|
||||
#define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0
|
||||
@ -69,6 +70,7 @@ extern "C" {
|
||||
#define REGDMA_LINK_PRI_RMT REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_GPTIMER REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_I2C REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_I2S REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
|
||||
typedef enum {
|
||||
|
@ -234,6 +234,15 @@ When the power management is enabled (i.e., :ref:`CONFIG_PM_ENABLE` is on), the
|
||||
|
||||
The I2S driver can prevent the system from changing or stopping the source clock by acquiring a power management lock. When the source clock is generated from APB, the lock type will be set to :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX` and when the source clock is APLL (if supported), it will be set to :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`. Whenever the user is reading or writing via I2S (i.e., calling :cpp:func:`i2s_channel_read` or :cpp:func:`i2s_channel_write`), the driver guarantees that the power management lock is acquired. Likewise, the driver releases the lock after the reading or writing finishes.
|
||||
|
||||
.. only:: SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
Sleep Retention
|
||||
"""""""""""""""
|
||||
|
||||
{IDF_TARGET_NAME} supports to retain the I2S register context before entering **light sleep** and restore them after woke up. Which means you don't have to re-init the I2S driver even the peripheral is power off during the light sleep.
|
||||
|
||||
This feature can be enabled by setting the flag :cpp:member:`i2s_chan_config_t::allow_pd`. It will allow the system to power down the I2S in light sleep, meanwhile save the I2S register context. It can help to save more power consumption with some extra cost of the memory.
|
||||
|
||||
Finite State Machine
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -153,6 +153,7 @@ The following peripheral drivers are not aware of DFS yet. Applications need to
|
||||
- SYSTIMER
|
||||
:SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT
|
||||
:SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C
|
||||
:SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S
|
||||
:SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs
|
||||
|
||||
The following peripherals are not yet supported:
|
||||
@ -164,7 +165,6 @@ The following peripheral drivers are not aware of DFS yet. Applications need to
|
||||
- Trace
|
||||
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA
|
||||
- SPI2
|
||||
- I2S
|
||||
- PCNT
|
||||
- USB-Serial-JTAG
|
||||
- TWAI
|
||||
|
@ -234,6 +234,15 @@ I2S 驱动中的资源可分为三个级别:
|
||||
|
||||
I2S 驱动可以获取电源管理锁,从而防止系统设置更改或时钟源被禁用。时钟源为 APB 时,锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`。时钟源为 APLL(若支持)时,锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`。用户通过 I2S 读写时(即调用 :cpp:func:`i2s_channel_read` 或 :cpp:func:`i2s_channel_write`),驱动程序将获取电源管理锁,并在读写完成后释放锁。
|
||||
|
||||
.. only:: SOC_I2S_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
睡眠保留
|
||||
""""""""
|
||||
|
||||
{IDF_TARGET_NAME} 支持在进入 **轻度睡眠** 之前保留 I2S 寄存器中的内容,并在唤醒后恢复。也就是说外设若因进入 **轻度睡眠** 而掉电,程序不需要在唤醒后重新配置 I2S。
|
||||
|
||||
该特性可以通过置位配置中的 :cpp:member:`i2s_chan_config_t::allow_pd` 标志位启用。启用后驱动允许系统在轻度睡眠时对 I2S 掉电,同时保存 I2S 的寄存器内容。它可以帮助降低轻度睡眠时的功耗,但需要花费一些额外的存储来保存寄存器的配置。
|
||||
|
||||
有限状态机
|
||||
^^^^^^^^^^
|
||||
|
||||
|
@ -152,7 +152,8 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
|
||||
- SPI0/1
|
||||
- SYSTIMER
|
||||
:SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT
|
||||
:SOC_I2C_SUPPORT_SLEEP_RETENTION:- I2C
|
||||
:SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C
|
||||
:SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S
|
||||
:SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs
|
||||
|
||||
以下外设尚未支持:
|
||||
@ -164,7 +165,6 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
|
||||
- Trace
|
||||
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA
|
||||
- SPI2
|
||||
- I2S
|
||||
- PCNT
|
||||
- USB-Serial-JTAG
|
||||
- TWAI
|
||||
|
Loading…
x
Reference in New Issue
Block a user