Skip to content

Commit

Permalink
Merge branch 'bugfix/check_i2s_intr_alloc_failure' into 'master'
Browse files Browse the repository at this point in the history
fix(i2s): check gdma callback register state and add missed port2 on p4

See merge request espressif/esp-idf!31018
  • Loading branch information
L-KAYA committed May 27, 2024
2 parents ea2f512 + 42cee2b commit b1a5d80
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 107 deletions.
10 changes: 9 additions & 1 deletion components/driver/deprecated/i2s_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,14 +349,22 @@ static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num, int intr_flag)
gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S};

switch (i2s_num) {
#if SOC_I2S_NUM > 2
case I2S_NUM_2:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S2;
break;
#endif
#if SOC_I2S_NUM > 1
case I2S_NUM_1:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1;
break;
#endif
default:
case I2S_NUM_0:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0;
break;
default:
ESP_LOGE(TAG, "Unsupported I2S port number");
return ESP_ERR_NOT_SUPPORTED;
}

/* Set GDMA config */
Expand Down
29 changes: 23 additions & 6 deletions components/esp_driver_i2s/i2s_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -697,21 +697,30 @@ static void IRAM_ATTR i2s_dma_tx_callback(void *arg)
*/
esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
{
esp_err_t ret = ESP_OK;
i2s_port_t port_id = handle->controller->id;
ESP_RETURN_ON_FALSE((port_id >= 0) && (port_id < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "invalid handle");
#if SOC_GDMA_SUPPORTED
/* Set GDMA trigger module */
gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S};

switch (port_id) {
#if SOC_I2S_NUM > 2
case I2S_NUM_2:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S2;
break;
#endif
#if SOC_I2S_NUM > 1
case I2S_NUM_1:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1;
break;
#endif
default:
case I2S_NUM_0:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0;
break;
default:
ESP_LOGE(TAG, "Unsupported I2S port number");
return ESP_ERR_NOT_SUPPORTED;
}

/* Set GDMA config */
Expand All @@ -720,18 +729,18 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX;
/* Register a new GDMA tx channel */
ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &handle->dma.dma_chan), TAG, "Register tx dma channel error");
ESP_RETURN_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), TAG, "Connect tx dma channel error");
ESP_GOTO_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), err1, TAG, "Connect tx dma channel error");
gdma_tx_event_callbacks_t cb = {.on_trans_eof = i2s_dma_tx_callback};
/* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */
gdma_register_tx_event_callbacks(handle->dma.dma_chan, &cb, handle);
ESP_GOTO_ON_ERROR(gdma_register_tx_event_callbacks(handle->dma.dma_chan, &cb, handle), err2, TAG, "Register tx callback failed");
} else {
dma_cfg.direction = GDMA_CHANNEL_DIRECTION_RX;
/* Register a new GDMA rx channel */
ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &handle->dma.dma_chan), TAG, "Register rx dma channel error");
ESP_RETURN_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), TAG, "Connect rx dma channel error");
ESP_GOTO_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), err1, TAG, "Connect rx dma channel error");
gdma_rx_event_callbacks_t cb = {.on_recv_eof = i2s_dma_rx_callback};
/* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */
gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle);
ESP_GOTO_ON_ERROR(gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle), err2, TAG, "Register rx callback failed");
}
#else
intr_flag |= handle->intr_prio_flags;
Expand All @@ -748,7 +757,15 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
/* Start DMA */
i2s_ll_enable_dma(handle->controller->hal.dev, true);
#endif // SOC_GDMA_SUPPORTED
return ESP_OK;
return ret;
#if SOC_GDMA_SUPPORTED
err2:
gdma_disconnect(handle->dma.dma_chan);
err1:
gdma_del_channel(handle->dma.dma_chan);
handle->dma.dma_chan = NULL;
return ret;
#endif
}

static uint64_t s_i2s_get_pair_chan_gpio_mask(i2s_chan_handle_t handle)
Expand Down
3 changes: 3 additions & 0 deletions components/esp_driver_i2s/include/driver/i2s_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ typedef enum {
I2S_NUM_0 = 0, /*!< I2S controller port 0 */
#if SOC_I2S_NUM > 1
I2S_NUM_1 = 1, /*!< I2S controller port 1 */
#endif
#if SOC_I2S_NUM > 2
I2S_NUM_2 = 2, /*!< I2S controller port 2 */
#endif
I2S_NUM_AUTO, /*!< Select whichever port is available */
} i2s_port_t;
Expand Down
17 changes: 15 additions & 2 deletions components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,20 @@ TEST_CASE("I2S_basic_channel_allocation_reconfig_deleting_test", "[i2s]")
TEST_ESP_OK(i2s_channel_enable(tx_handle));
TEST_ESP_OK(i2s_channel_disable(tx_handle));
TEST_ESP_OK(i2s_del_channel(tx_handle));
TEST_ASSERT(i2s_channel_get_info(tx_handle, &chan_info) == ESP_ERR_NOT_FOUND);
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_channel_get_info(tx_handle, &chan_info));

/* Exhaust test */
i2s_chan_handle_t tx_ex[SOC_I2S_NUM] = {};
for (int i = 0; i < SOC_I2S_NUM; i++) {
TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_ex[i], NULL));
TEST_ESP_OK(i2s_channel_init_std_mode(tx_ex[i], &std_cfg));
TEST_ESP_OK(i2s_channel_enable(tx_ex[i]));
}
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_new_channel(&chan_cfg, &tx_handle, NULL));
for (int i = 0; i < SOC_I2S_NUM; i++) {
TEST_ESP_OK(i2s_channel_disable(tx_ex[i]));
TEST_ESP_OK(i2s_del_channel(tx_ex[i]));
}

/* Duplex channel basic test */
chan_cfg.id = I2S_NUM_0; // Specify port id to I2S port 0
Expand All @@ -209,7 +222,7 @@ TEST_CASE("I2S_basic_channel_allocation_reconfig_deleting_test", "[i2s]")

/* Hold the occupation */
TEST_ESP_OK(i2s_platform_acquire_occupation(I2S_NUM_0, "test_i2s"));
TEST_ASSERT(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle) == ESP_ERR_NOT_FOUND);
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
TEST_ESP_OK(i2s_platform_release_occupation(I2S_NUM_0));
TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
TEST_ESP_OK(i2s_del_channel(tx_handle));
Expand Down
1 change: 0 additions & 1 deletion components/esp_lcd/i80/esp_lcd_panel_io_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
// enable I2S LCD master mode (refer to I2S TRM)
i2s_ll_enable_lcd(bus->hal.dev, true);
i2s_ll_tx_stop_on_fifo_empty(bus->hal.dev, true);
i2s_ll_tx_bypass_pcm(bus->hal.dev, true);
i2s_ll_tx_set_slave_mod(bus->hal.dev, false);
i2s_ll_tx_set_bits_mod(bus->hal.dev, bus_config->bus_width);
i2s_ll_tx_select_std_slot(bus->hal.dev, I2S_STD_SLOT_BOTH, true); // copy mono
Expand Down
25 changes: 7 additions & 18 deletions components/hal/esp32/include/hal/i2s_ll.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -74,7 +74,7 @@ static inline void i2s_ll_dma_enable_auto_write_back(i2s_dev_t *hw, bool en)
}

/**
* @brief I2S DMA generate EOF event on data in FIFO poped out
* @brief I2S DMA generate EOF event on data in FIFO popped out
*
* @param hw Peripheral I2S hardware instance address.
* @param en True to enable, False to disable
Expand Down Expand Up @@ -695,17 +695,6 @@ static inline void i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t *hw, bool en)
hw->conf1.tx_stop_en = en;
}

/**
* @brief Set whether to bypass the internal PCM module
*
* @param hw Peripheral I2S hardware instance address.
* @param bypass whether to bypass the PCM module
*/
static inline void i2s_ll_tx_bypass_pcm(i2s_dev_t *hw, bool bypass)
{
hw->conf1.tx_pcm_bypass = bypass;
}

/**
* @brief Enable I2S DMA
*
Expand Down Expand Up @@ -932,7 +921,7 @@ static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool loopback_en)
* @brief Configure RX PDM downsample
*
* @param hw Peripheral I2S hardware instance address.
* @param dsr PDM downsample configuration paramater
* @param dsr PDM downsample configuration parameter
*/
static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr)
{
Expand Down Expand Up @@ -1080,23 +1069,23 @@ static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f
}

/**
* @brief Get I2S TX PDM fp configuration paramater
* @brief Get I2S TX PDM fp configuration parameter
*
* @param hw Peripheral I2S hardware instance address.
* @return
* - fp configuration paramater
* - fp configuration parameter
*/
static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw)
{
return hw->pdm_freq_conf.tx_pdm_fp;
}

/**
* @brief Get I2S TX PDM fs configuration paramater
* @brief Get I2S TX PDM fs configuration parameter
*
* @param hw Peripheral I2S hardware instance address.
* @return
* - fs configuration paramater
* - fs configuration parameter
*/
static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw)
{
Expand Down
15 changes: 2 additions & 13 deletions components/hal/esp32s2/include/hal/i2s_ll.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -72,7 +72,7 @@ static inline void i2s_ll_dma_enable_auto_write_back(i2s_dev_t *hw, bool en)
}

/**
* @brief I2S DMA generate EOF event on data in FIFO poped out
* @brief I2S DMA generate EOF event on data in FIFO popped out
*
* @param hw Peripheral I2S hardware instance address.
* @param en True to enable, False to disable
Expand Down Expand Up @@ -997,17 +997,6 @@ static inline void i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t *hw, bool en)
hw->conf1.tx_stop_en = en;
}

/**
* @brief Set whether to bypass the internal PCM module
*
* @param hw Peripheral I2S hardware instance address.
* @param bypass whether to bypass the PCM module
*/
static inline void i2s_ll_tx_bypass_pcm(i2s_dev_t *hw, bool bypass)
{
hw->conf1.tx_pcm_bypass = bypass;
}

#ifdef __cplusplus
}
#endif
56 changes: 2 additions & 54 deletions components/soc/esp32s2/include/soc/i2s_reg.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -723,26 +723,6 @@ extern "C" {
#define I2S_TX_BCK_IN_DELAY_S 0

#define I2S_FIFO_CONF_REG(i) (REG_I2S_BASE(i) + 0x0020)
/* I2S_TX_24MSB_EN : R/W ;bitpos:[23] ;default: 1'b0 ; */
/*description: Only useful in tx 24bit mode. 1: the high 24 bits are effective
in i2s fifo 0: the low 24 bits are effective in i2s fifo*/
#define I2S_TX_24MSB_EN (BIT(23))
#define I2S_TX_24MSB_EN_M (BIT(23))
#define I2S_TX_24MSB_EN_V 0x1
#define I2S_TX_24MSB_EN_S 23
/* I2S_RX_24MSB_EN : R/W ;bitpos:[22] ;default: 1'b0 ; */
/*description: Only useful in rx 24bit mode. 1: the high 24 bits are effective
in i2s fifo 0: the low 24 bits are effective in i2s fifo*/
#define I2S_RX_24MSB_EN (BIT(22))
#define I2S_RX_24MSB_EN_M (BIT(22))
#define I2S_RX_24MSB_EN_V 0x1
#define I2S_RX_24MSB_EN_S 22
/* I2S_RX_FIFO_SYNC : R/W ;bitpos:[21] ;default: 1'b0 ; */
/*description: force write back rx data to memory*/
#define I2S_RX_FIFO_SYNC (BIT(21))
#define I2S_RX_FIFO_SYNC_M (BIT(21))
#define I2S_RX_FIFO_SYNC_V 0x1
#define I2S_RX_FIFO_SYNC_S 21
/* I2S_RX_FIFO_MOD_FORCE_EN : R/W ;bitpos:[20] ;default: 1'b0 ; */
/*description: The bit should always be set to 1*/
#define I2S_RX_FIFO_MOD_FORCE_EN (BIT(20))
Expand Down Expand Up @@ -1192,45 +1172,13 @@ extern "C" {
#define I2S_LC_FIFO_TIMEOUT_S 0

#define I2S_CONF1_REG(i) (REG_I2S_BASE(i) + 0x00a0)
/* I2S_TX_ZEROS_RM_EN : R/W ;bitpos:[9] ;default: 1'd0 ; */
/*description: don't use*/
#define I2S_TX_ZEROS_RM_EN (BIT(9))
#define I2S_TX_ZEROS_RM_EN_M (BIT(9))
#define I2S_TX_ZEROS_RM_EN_V 0x1
#define I2S_TX_ZEROS_RM_EN_S 9
/* I2S_TX_STOP_EN : R/W ;bitpos:[8] ;default: 1'd0 ; */
/*description: Set this bit to stop disable output BCK signal and WS signal
when tx FIFO is emtpy*/
when tx FIFO is empty*/
#define I2S_TX_STOP_EN (BIT(8))
#define I2S_TX_STOP_EN_M (BIT(8))
#define I2S_TX_STOP_EN_V 0x1
#define I2S_TX_STOP_EN_S 8
/* I2S_RX_PCM_BYPASS : R/W ;bitpos:[7] ;default: 1'h1 ; */
/*description: Set this bit to bypass Compress/Decompress module for received data.*/
#define I2S_RX_PCM_BYPASS (BIT(7))
#define I2S_RX_PCM_BYPASS_M (BIT(7))
#define I2S_RX_PCM_BYPASS_V 0x1
#define I2S_RX_PCM_BYPASS_S 7
/* I2S_RX_PCM_CONF : R/W ;bitpos:[6:4] ;default: 3'h0 ; */
/*description: Compress/Decompress module configuration bits. 0: decompress
received data 1:compress received data*/
#define I2S_RX_PCM_CONF 0x00000007
#define I2S_RX_PCM_CONF_M ((I2S_RX_PCM_CONF_V)<<(I2S_RX_PCM_CONF_S))
#define I2S_RX_PCM_CONF_V 0x7
#define I2S_RX_PCM_CONF_S 4
/* I2S_TX_PCM_BYPASS : R/W ;bitpos:[3] ;default: 1'h1 ; */
/*description: Set this bit to bypass Compress/Decompress module for transmitted data.*/
#define I2S_TX_PCM_BYPASS (BIT(3))
#define I2S_TX_PCM_BYPASS_M (BIT(3))
#define I2S_TX_PCM_BYPASS_V 0x1
#define I2S_TX_PCM_BYPASS_S 3
/* I2S_TX_PCM_CONF : R/W ;bitpos:[2:0] ;default: 3'h1 ; */
/*description: Compress/Decompress module configuration bits. 0: decompress
transmitted data 1:compress transmitted data*/
#define I2S_TX_PCM_CONF 0x00000007
#define I2S_TX_PCM_CONF_M ((I2S_TX_PCM_CONF_V)<<(I2S_TX_PCM_CONF_S))
#define I2S_TX_PCM_CONF_V 0x7
#define I2S_TX_PCM_CONF_S 0

#define I2S_PD_CONF_REG(i) (REG_I2S_BASE(i) + 0x00a4)
/* I2S_DMA_RAM_CLK_FO : R/W ;bitpos:[6] ;default: 1'h0 ; */
Expand Down
17 changes: 5 additions & 12 deletions components/soc/esp32s2/include/soc/i2s_struct.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -175,10 +175,7 @@ typedef volatile struct i2s_dev_s {
uint32_t rx_fifo_mod: 3; /*Receiver FIFO mode configuration bits*/
uint32_t tx_fifo_mod_force_en: 1; /*The bit should always be set to 1*/
uint32_t rx_fifo_mod_force_en: 1; /*The bit should always be set to 1*/
uint32_t rx_fifo_sync: 1; /*force write back rx data to memory*/
uint32_t rx_24msb_en: 1; /*Only useful in rx 24bit mode. 1: the high 24 bits are effective in i2s fifo 0: the low 24 bits are effective in i2s fifo*/
uint32_t tx_24msb_en: 1; /*Only useful in tx 24bit mode. 1: the high 24 bits are effective in i2s fifo 0: the low 24 bits are effective in i2s fifo*/
uint32_t reserved24: 8;
uint32_t reserved21: 11;
};
uint32_t val;
} fifo_conf;
Expand Down Expand Up @@ -314,13 +311,9 @@ typedef volatile struct i2s_dev_s {
uint32_t reserved_9c;
union {
struct {
uint32_t tx_pcm_conf: 3; /*Compress/Decompress module configuration bits. 0: decompress transmitted data 1:compress transmitted data*/
uint32_t tx_pcm_bypass: 1; /*Set this bit to bypass Compress/Decompress module for transmitted data.*/
uint32_t rx_pcm_conf: 3; /*Compress/Decompress module configuration bits. 0: decompress received data 1:compress received data*/
uint32_t rx_pcm_bypass: 1; /*Set this bit to bypass Compress/Decompress module for received data.*/
uint32_t tx_stop_en: 1; /*Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy*/
uint32_t tx_zeros_rm_en: 1; /*don't use*/
uint32_t reserved10: 22;
uint32_t reserved0: 8;
uint32_t tx_stop_en: 1; /*Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty*/
uint32_t reserved9: 23;
};
uint32_t val;
} conf1;
Expand Down

0 comments on commit b1a5d80

Please sign in to comment.