Skip to content

Commit ae36f84

Browse files
committed
feat(i2s): enable i2s test on c5
1 parent 0cb4bdc commit ae36f84

File tree

15 files changed

+134
-60
lines changed

15 files changed

+134
-60
lines changed

components/esp_driver_i2s/i2s_common.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@
4141

4242
#include "esp_private/i2s_platform.h"
4343
#include "esp_private/esp_clk.h"
44+
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
4445
#include "esp_private/sleep_retention.h"
46+
#endif
4547

4648
#include "driver/gpio.h"
4749
#include "esp_private/gpio.h"
@@ -258,7 +260,7 @@ static i2s_controller_t *i2s_acquire_controller_obj(int id)
258260
#endif
259261

260262
#if I2S_USE_RETENTION_LINK
261-
sleep_retention_module_t module = i2s_periph_signal[id].retention_module;
263+
sleep_retention_module_t module = i2s_reg_retention_info[id].retention_module;
262264
sleep_retention_module_init_param_t init_param = {
263265
.cbs = {
264266
.create = {
@@ -936,7 +938,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *
936938
ESP_RETURN_ON_FALSE(chan_cfg->dma_desc_num >= 2, ESP_ERR_INVALID_ARG, TAG, "there should be at least 2 DMA buffers");
937939
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");
938940
#if !SOC_I2S_SUPPORT_SLEEP_RETENTION
939-
ESP_RETURN_ON_FALSE(!chan_cfg->backup_before_sleep, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
941+
ESP_RETURN_ON_FALSE(!chan_cfg->allow_pd, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
940942
#endif
941943

942944
esp_err_t ret = ESP_OK;
@@ -997,7 +999,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *
997999
i2s_obj->full_duplex = true;
9981000
}
9991001
#if I2S_USE_RETENTION_LINK
1000-
if (chan_cfg->backup_before_sleep) {
1002+
if (chan_cfg->allow_pd) {
10011003
s_i2s_create_retention_module(i2s_obj);
10021004
}
10031005
#endif

components/esp_driver_i2s/i2s_private.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
#endif
2727
#include "esp_private/periph_ctrl.h"
2828
#include "esp_private/esp_gpio_reserve.h"
29+
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
2930
#include "esp_private/sleep_retention.h"
31+
#endif
3032
#include "esp_pm.h"
3133
#include "esp_err.h"
3234
#include "sdkconfig.h"
@@ -135,8 +137,10 @@ typedef struct {
135137
i2s_chan_handle_t tx_chan; /*!< tx channel handler */
136138
i2s_chan_handle_t rx_chan; /*!< rx channel handler */
137139
_lock_t mutex; /*!< mutex for controller */
140+
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
138141
sleep_retention_module_t slp_retention_mod; /*!< Sleep retention module */
139142
bool retention_link_created; /*!< Whether the retention link is created */
143+
#endif
140144
int mclk; /*!< MCK out pin, shared by tx/rx*/
141145
#if CONFIG_IDF_TARGET_ESP32
142146
esp_clock_output_mapping_handle_t mclk_out_hdl; /*!< The handle of MCLK output signal */

components/esp_driver_i2s/include/driver/i2s_common.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extern "C" {
2626
.dma_frame_num = 240, \
2727
.auto_clear_after_cb = false, \
2828
.auto_clear_before_cb = false, \
29-
.backup_before_sleep = false, \
29+
.allow_pd = false, \
3030
.intr_priority = 0, \
3131
}
3232

@@ -74,9 +74,10 @@ typedef struct {
7474
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
7575
* So that user can access data in the callback that just finished to send.
7676
*/
77-
bool backup_before_sleep; /*!< If set, the driver will backup/restore the I2S registers before/after entering/exist sleep mode.
78-
By this approach, the system can power off I2S's power domain.
79-
This can save power, but at the expense of more RAM being consumed */
77+
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.
78+
* By this approach, the system can power off I2S's power domain.
79+
* This can save power, but at the expense of more RAM being consumed.
80+
*/
8081
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) */
8182
} i2s_chan_config_t;
8283

components/esp_driver_i2s/test_apps/.build-test-rules.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
components/esp_driver_i2s/test_apps/i2s:
44
disable:
55
- if: SOC_I2S_SUPPORTED != 1
6-
disable_test:
7-
- if: IDF_TARGET == "esp32c5"
8-
temporary: true
9-
reason: target test failed # TODO [ESP32C5] IDF-10343
106
depends_components:
117
- esp_driver_i2s
128
- esp_driver_pcnt
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
set(srcs "test_app_main.c"
22
"test_i2s.c"
3-
"test_i2s_iram.c")
3+
"test_i2s_iram.c"
4+
"test_i2s_sleep.c")
45

56
if(CONFIG_SOC_I2S_SUPPORTS_ETM AND CONFIG_SOC_GPIO_SUPPORT_ETM)
67
set(srcs ${srcs} "test_i2s_etm.c")
78
endif()
89

9-
if(CONFIG_SOC_I2S_SUPPORT_SLEEP_RETENTION)
10-
list(APPEND srcs "test_i2s_slp_retention.c")
11-
endif()
12-
1310
idf_component_register(SRCS ${srcs}
1411
PRIV_REQUIRES unity esp_driver_pcnt spi_flash esp_driver_gpio esp_driver_i2s esp_driver_uart
1512
WHOLE_ARCHIVE)

components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ static void i2s_test_common_sample_rate(i2s_chan_handle_t rx_chan, i2s_std_clk_c
776776
printf("[%"PRIu32" Hz] %d pulses, expected %d, err %d\n", test_freq[i], real_pulse, expt_pulse, real_pulse - expt_pulse);
777777
TEST_ESP_OK(i2s_channel_disable(rx_chan));
778778
// Check if the error between real pulse number and expected pulse number is within 1%
779-
TEST_ASSERT_INT_WITHIN(expt_pulse * 0.01, expt_pulse, real_pulse);
779+
TEST_ASSERT_INT_WITHIN(expt_pulse * 0.02, expt_pulse, real_pulse);
780780
}
781781
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
782782
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));

components/esp_driver_i2s/test_apps/i2s/main/test_i2s_slp_retention.c renamed to components/esp_driver_i2s/test_apps/i2s/main/test_i2s_sleep.c

Lines changed: 74 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
#include "esp_private/esp_pmu.h"
2020
#include "../../test_inc/test_i2s.h"
2121

22-
#if SOC_I2S_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
22+
#define TEST_I2S_PD_SLEEP (SOC_I2S_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
2323

2424
extern void i2s_read_write_test(i2s_chan_handle_t tx_chan, i2s_chan_handle_t rx_chan);
2525

26-
static void test_i2s_enter_light_sleep(int sec)
26+
static void s_test_i2s_enter_light_sleep(int sec, bool allow_power_down)
2727
{
2828
esp_sleep_context_t sleep_ctx;
2929
esp_sleep_set_sleep_context(&sleep_ctx);
@@ -42,43 +42,40 @@ static void test_i2s_enter_light_sleep(int sec)
4242
printf("Woke up from light sleep\n");
4343

4444
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
45-
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
45+
#if SOC_I2S_SUPPORT_SLEEP_RETENTION
46+
// check if the power domain also is powered down
47+
TEST_ASSERT_EQUAL(allow_power_down ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
48+
#endif
4649
esp_sleep_set_sleep_context(NULL);
4750
}
4851

49-
TEST_CASE("I2S_sleep_retention_test", "[i2s]")
52+
static void s_test_i2s_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle, bool allow_power_down)
5053
{
51-
i2s_chan_handle_t tx_handle;
52-
i2s_chan_handle_t rx_handle;
54+
/* Enter light sleep before I2S channel enabled and wake up after 1 second */
55+
s_test_i2s_enter_light_sleep(1, allow_power_down);
56+
/* Check whether I2S can work correctly after light sleep */
57+
TEST_ESP_OK(i2s_channel_enable(tx_handle));
58+
TEST_ESP_OK(i2s_channel_enable(rx_handle));
59+
i2s_read_write_test(tx_handle, rx_handle);
60+
}
5361

54-
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
55-
chan_cfg.backup_before_sleep = true;
56-
i2s_std_config_t std_cfg = {
57-
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
58-
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(SAMPLE_BITS, I2S_SLOT_MODE_STEREO),
59-
.gpio_cfg = I2S_TEST_MASTER_DEFAULT_PIN,
60-
};
61-
std_cfg.gpio_cfg.din = std_cfg.gpio_cfg.dout;
62-
TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
63-
TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
64-
TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
62+
static void s_test_i2s_power_on_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle)
63+
{
64+
s_test_i2s_sleep(tx_handle, rx_handle, false);
65+
}
6566

67+
#if TEST_I2S_PD_SLEEP
68+
static void s_test_i2s_power_down_sleep(i2s_chan_handle_t tx_handle, i2s_chan_handle_t rx_handle)
69+
{
70+
#if SOC_GDMA_SUPPORT_SLEEP_RETENTION
71+
s_test_i2s_sleep(tx_handle, rx_handle, true);
72+
#else
6673
/* I2S retention is depended on GDMA retention.
6774
* Only take two registers as sample to check the I2S retention when GDMA retention has not been supported. */
68-
#if !SOC_GDMA_SUPPORT_SLEEP_RETENTION
6975
i2s_tx_conf_reg_t tx_reg_before_slp = I2S0.tx_conf;
7076
i2s_rx_conf_reg_t rx_reg_before_slp = I2S0.rx_conf;
71-
#endif
72-
73-
/* Enter light sleep and wake up after 1 second */
74-
test_i2s_enter_light_sleep(1);
75-
76-
#if SOC_GDMA_SUPPORT_SLEEP_RETENTION
77-
/* Check whether I2S can work correctly after light sleep */
78-
TEST_ESP_OK(i2s_channel_enable(tx_handle));
79-
TEST_ESP_OK(i2s_channel_enable(rx_handle));
80-
i2s_read_write_test(tx_handle, rx_handle);
81-
#else
77+
/* Enter light sleep before I2S channel enabled and wake up after 1 second */
78+
s_test_i2s_enter_light_sleep(1, true);
8279
/* Only check whether the register values are restored if GDMA retention has not been supported */
8380
i2s_tx_conf_reg_t tx_reg_after_slp = I2S0.tx_conf;
8481
i2s_rx_conf_reg_t rx_reg_after_slp = I2S0.rx_conf;
@@ -88,6 +85,45 @@ TEST_CASE("I2S_sleep_retention_test", "[i2s]")
8885

8986
TEST_ESP_OK(i2s_channel_enable(tx_handle));
9087
TEST_ESP_OK(i2s_channel_enable(rx_handle));
88+
89+
tx_reg_before_slp.val = I2S0.tx_conf.val;
90+
rx_reg_before_slp.val = I2S0.rx_conf.val;
91+
/* Enter light sleep before I2S channel enabled and wake up after 1 second */
92+
s_test_i2s_enter_light_sleep(1, true);
93+
/* Only check whether the register values are restored if GDMA retention has not been supported */
94+
tx_reg_after_slp.val = I2S0.tx_conf.val;
95+
rx_reg_after_slp.val = I2S0.rx_conf.val;
96+
97+
TEST_ASSERT_EQUAL_UINT32(tx_reg_before_slp.val, tx_reg_after_slp.val);
98+
TEST_ASSERT_EQUAL_UINT32(rx_reg_before_slp.val, rx_reg_after_slp.val);
99+
#endif // SOC_GDMA_SUPPORT_SLEEP_RETENTION
100+
}
101+
#endif // TEST_I2S_PD_SLEEP
102+
103+
void test_i2s_sleep_usability(bool allow_power_down)
104+
{
105+
i2s_chan_handle_t tx_handle;
106+
i2s_chan_handle_t rx_handle;
107+
108+
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
109+
chan_cfg.allow_pd = allow_power_down;
110+
i2s_std_config_t std_cfg = {
111+
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
112+
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(SAMPLE_BITS, I2S_SLOT_MODE_STEREO),
113+
.gpio_cfg = I2S_TEST_MASTER_DEFAULT_PIN,
114+
};
115+
std_cfg.gpio_cfg.din = std_cfg.gpio_cfg.dout;
116+
TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
117+
TEST_ESP_OK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
118+
TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
119+
120+
if (!allow_power_down) {
121+
s_test_i2s_power_on_sleep(tx_handle, rx_handle);
122+
}
123+
#if TEST_I2S_PD_SLEEP
124+
else {
125+
s_test_i2s_power_down_sleep(tx_handle, rx_handle);
126+
}
91127
#endif
92128

93129
printf("I2S works as expected after light sleep\n");
@@ -98,4 +134,12 @@ TEST_CASE("I2S_sleep_retention_test", "[i2s]")
98134
TEST_ESP_OK(i2s_del_channel(rx_handle));
99135
}
100136

101-
#endif // SOC_I2S_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
137+
TEST_CASE("I2S_light_sleep_usability_test", "[i2s]")
138+
{
139+
printf("\nTesting I2S power on light sleep...\n");
140+
test_i2s_sleep_usability(false);
141+
#if TEST_I2S_PD_SLEEP
142+
printf("\nTesting I2S power down light sleep...\n");
143+
test_i2s_sleep_usability(true);
144+
#endif
145+
}

components/esp_driver_i2s/test_apps/i2s/pytest_i2s.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
@pytest.mark.esp32
88
@pytest.mark.esp32s2
99
@pytest.mark.esp32c3
10-
# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF-10343
10+
@pytest.mark.esp32c5
1111
@pytest.mark.esp32c6
1212
@pytest.mark.esp32s3
1313
@pytest.mark.esp32h2

components/soc/esp32c5/i2s_periph.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
3131
.data_in_sig = I2SI_SD_IN_IDX,
3232

3333
.irq = ETS_I2S1_INTR_SOURCE,
34-
.retention_module = SLEEP_RETENTION_MODULE_I2S0,
3534
}
3635
};
3736

@@ -52,6 +51,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
5251
#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG(i)
5352
static const uint32_t i2s_regs_map[4] = {0x12360f, 0x0, 0x0, 0x0};
5453
#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \
54+
/* Save/restore the register values */ \
5555
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \
5656
REGDMA_I2S_LINK(0x00), \
5757
I2S_RETENTION_REGS_BASE(i2s_port), \
@@ -60,9 +60,11 @@ static const uint32_t i2s_regs_map[4] = {0x12360f, 0x0, 0x0, 0x0};
6060
i2s_regs_map[0], i2s_regs_map[1], \
6161
i2s_regs_map[2], i2s_regs_map[3]), \
6262
.owner = ENTRY(0) | ENTRY(2)}, \
63+
/* Set the RX_UPDATE after the retention to make sure the RX configurations are synchronized */ \
6364
[1] = { .config = REGDMA_LINK_WRITE_INIT( \
6465
REGDMA_I2S_LINK(0x01), I2S_RX_CONF_REG(i2s_port), I2S_RX_UPDATE, I2S_RX_UPDATE_M, 1, 0), \
6566
.owner = ENTRY(0) | ENTRY(2)}, \
67+
/* Set the TX_UPDATE after the retention to make sure the TX configurations are synchronized */ \
6668
[2] = { .config = REGDMA_LINK_WRITE_INIT( \
6769
REGDMA_I2S_LINK(0x02), I2S_TX_CONF_REG(i2s_port), I2S_TX_UPDATE, I2S_TX_UPDATE_M, 1, 0), \
6870
.owner = ENTRY(0) | ENTRY(2)} \
@@ -72,6 +74,7 @@ static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION
7274

7375
const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = {
7476
[0] = {
77+
.retention_module = SLEEP_RETENTION_MODULE_I2S0,
7578
.entry_array = i2s0_regs_retention,
7679
.array_size = ARRAY_SIZE(i2s0_regs_retention)
7780
},

components/soc/esp32c6/i2s_periph.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
3131
.data_in_sig = I2SI_SD_IN_IDX,
3232

3333
.irq = ETS_I2S1_INTR_SOURCE,
34-
.retention_module = SLEEP_RETENTION_MODULE_I2S0,
3534
}
3635
};
3736

@@ -52,6 +51,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
5251
#define I2S_RETENTION_REGS_BASE(i) I2S_RX_CONF_REG(i)
5352
static const uint32_t i2s_regs_map[4] = {0x12330f, 0x0, 0x0, 0x0};
5453
#define I2S_SLEEP_RETENTION_ENTRIES(i2s_port) { \
54+
/* Save/restore the register values */ \
5555
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT( \
5656
REGDMA_I2S_LINK(0x00), \
5757
I2S_RETENTION_REGS_BASE(i2s_port), \
@@ -60,9 +60,11 @@ static const uint32_t i2s_regs_map[4] = {0x12330f, 0x0, 0x0, 0x0};
6060
i2s_regs_map[0], i2s_regs_map[1], \
6161
i2s_regs_map[2], i2s_regs_map[3]), \
6262
.owner = ENTRY(0) | ENTRY(2)}, \
63+
/* Set the RX_UPDATE after the retention to make sure the RX configurations are synchronized */ \
6364
[1] = { .config = REGDMA_LINK_WRITE_INIT( \
6465
REGDMA_I2S_LINK(0x01), I2S_RX_CONF_REG(i2s_port), I2S_RX_UPDATE, I2S_RX_UPDATE_M, 1, 0), \
6566
.owner = ENTRY(0) | ENTRY(2)}, \
67+
/* Set the TX_UPDATE after the retention to make sure the TX configurations are synchronized */ \
6668
[2] = { .config = REGDMA_LINK_WRITE_INIT( \
6769
REGDMA_I2S_LINK(0x02), I2S_TX_CONF_REG(i2s_port), I2S_TX_UPDATE, I2S_TX_UPDATE_M, 1, 0), \
6870
.owner = ENTRY(0) | ENTRY(2)} \
@@ -72,6 +74,7 @@ static const regdma_entries_config_t i2s0_regs_retention[] = I2S_SLEEP_RETENTION
7274

7375
const i2s_reg_retention_info_t i2s_reg_retention_info[SOC_I2S_NUM] = {
7476
[0] = {
77+
.retention_module = SLEEP_RETENTION_MODULE_I2S0,
7578
.entry_array = i2s0_regs_retention,
7679
.array_size = ARRAY_SIZE(i2s0_regs_retention)
7780
},

0 commit comments

Comments
 (0)