Răsfoiți Sursa

Merge branch 'bugfix/i2s_write_timeout_when_setting_clock' into 'master'

i2s: fixed write timeout while setting the clock

Closes IDFGH-7273 and IDFGH-7261

See merge request espressif/esp-idf!18201
Kevin (Lao Kaiyao) 3 ani în urmă
părinte
comite
94d7ae03da
2 a modificat fișierele cu 40 adăugiri și 12 ștergeri
  1. 38 10
      components/driver/i2s.c
  2. 2 2
      components/soc/esp32/include/soc/i2s_struct.h

+ 38 - 10
components/driver/i2s.c

@@ -1025,6 +1025,14 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_
     ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
     ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_ARG, TAG, "I2S%d has not installed yet", i2s_num);
 
+    /* Acquire the lock before stop i2s, otherwise reading/writing operation will stuck on receiving the message queue from interrupt */
+    if (p_i2s[i2s_num]->dir & I2S_MODE_TX) {
+        xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
+    }
+    if (p_i2s[i2s_num]->dir & I2S_MODE_RX) {
+        xSemaphoreTake(p_i2s[i2s_num]->rx->mux, portMAX_DELAY);
+    }
+
     /* Stop I2S */
     i2s_stop(i2s_num);
 
@@ -1063,19 +1071,15 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_
     if (need_realloc) {
         esp_err_t ret = ESP_OK;
         if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
-            xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
             p_i2s[i2s_num]->tx->buf_size = buf_size;
             ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->tx);
             xQueueReset(p_i2s[i2s_num]->tx->queue);
-            xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
             ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d tx DMA buffer malloc failed", i2s_num);
         }
         if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
-            xSemaphoreTake(p_i2s[i2s_num]->rx->mux, portMAX_DELAY);
             p_i2s[i2s_num]->rx->buf_size = buf_size;
             ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->rx);
             xQueueReset(p_i2s[i2s_num]->rx->queue);
-            xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
             ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d rx DMA buffer malloc failed", i2s_num);
         }
     }
@@ -1085,6 +1089,13 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_
     /* I2S start */
     i2s_start(i2s_num);
 
+    if (p_i2s[i2s_num]->dir & I2S_MODE_TX) {
+        xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
+    }
+    if (p_i2s[i2s_num]->dir & I2S_MODE_RX) {
+        xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
+    }
+
     return ESP_OK;
 }
 
@@ -1107,6 +1118,13 @@ esp_err_t i2s_pcm_config(i2s_port_t i2s_num, const i2s_pcm_cfg_t *pcm_cfg)
 {
     ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet");
 
+    if (p_i2s[i2s_num]->dir & I2S_MODE_TX) {
+        xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
+    }
+    if (p_i2s[i2s_num]->dir & I2S_MODE_RX) {
+        xSemaphoreTake(p_i2s[i2s_num]->rx->mux, portMAX_DELAY);
+    }
+
     i2s_stop(i2s_num);
     I2S_ENTER_CRITICAL(i2s_num);
     if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
@@ -1117,6 +1135,14 @@ esp_err_t i2s_pcm_config(i2s_port_t i2s_num, const i2s_pcm_cfg_t *pcm_cfg)
     }
     I2S_EXIT_CRITICAL(i2s_num);
     i2s_start(i2s_num);
+
+    if (p_i2s[i2s_num]->dir & I2S_MODE_TX) {
+        xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
+    }
+    if (p_i2s[i2s_num]->dir & I2S_MODE_RX) {
+        xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
+    }
+
     return ESP_OK;
 }
 #endif
@@ -1126,13 +1152,14 @@ esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t downsampl
 {
     ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet");
     ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode");
+    xSemaphoreTake(p_i2s[i2s_num]->rx->mux, portMAX_DELAY);
     i2s_stop(i2s_num);
-    i2s_pdm_rx_slot_config_t *slot_cfg = (i2s_pdm_rx_slot_config_t*)p_i2s[i2s_num];
-    i2s_pdm_rx_clk_config_t *clk_cfg = (i2s_pdm_rx_clk_config_t*)p_i2s[i2s_num];
+    i2s_pdm_rx_slot_config_t *slot_cfg = (i2s_pdm_rx_slot_config_t*)p_i2s[i2s_num]->slot_cfg;
+    i2s_pdm_rx_clk_config_t *clk_cfg = (i2s_pdm_rx_clk_config_t*)p_i2s[i2s_num]->clk_cfg;
     clk_cfg->dn_sample_mode = downsample;
     i2s_ll_rx_set_pdm_dsr(p_i2s[i2s_num]->hal.dev, downsample);
-
-    // i2s will start in 'i2s_set_clk'
+    i2s_start(i2s_num);
+    xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
     return i2s_set_clk(i2s_num, clk_cfg->sample_rate_hz, slot_cfg->data_bit_width, slot_cfg->slot_mode);
 }
 #endif
@@ -1143,14 +1170,15 @@ esp_err_t i2s_set_pdm_tx_up_sample(i2s_port_t i2s_num, const i2s_pdm_tx_upsample
     ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet");
     ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM) && (p_i2s[i2s_num]->dir & I2S_DIR_TX),
                         ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode");
+    xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
     i2s_stop(i2s_num);
-
     i2s_pdm_tx_clk_config_t *clk_cfg = (i2s_pdm_tx_clk_config_t *)p_i2s[i2s_num]->clk_cfg;
     i2s_pdm_tx_slot_config_t *slot_cfg = (i2s_pdm_tx_slot_config_t *)p_i2s[i2s_num]->slot_cfg;
     clk_cfg->up_sample_fp = upsample_cfg->fp;
     clk_cfg->up_sample_fs = upsample_cfg->fs;
     i2s_ll_tx_set_pdm_fpfs(p_i2s[i2s_num]->hal.dev, upsample_cfg->fp, upsample_cfg->fs);
-    // i2s will start in 'i2s_set_clk'
+    i2s_start(i2s_num);
+    xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
     return i2s_set_clk(i2s_num, clk_cfg->sample_rate_hz, slot_cfg->data_bit_width, slot_cfg->slot_mode);
 }
 #endif

+ 2 - 2
components/soc/esp32/include/soc/i2s_struct.h

@@ -13,8 +13,8 @@ extern "C" {
 #endif
 
 typedef volatile struct i2s_dev_s {
-    uint32_t reserved_0;
-    uint32_t reserved_4;
+    uint32_t fifo_wr;
+    uint32_t fifo_rd;
     union {
         struct {
             uint32_t tx_reset:       1;