I2S_write blocks with unfilled DMA buffers

sparky3822
Posts: 5
Joined: Wed Dec 19, 2018 12:24 am

I2S_write blocks with unfilled DMA buffers

Postby sparky3822 » Wed Dec 19, 2018 1:00 am

The i2s_write() call blocks when I try to pre-fill the TX DMA buffers.

I'd like to fill the DMA buffers before I call I2S_start() to minimize the possibility of underruns. However, i2s_write() doesn't return unless I2S is already started. Upon further testing and inspecting the i2s.c code, it seems, even if I2S is started, the i2s_write() api allows the filling of only one TX buffer at a time. After a single buffer is filled, a subsequent call will block from filling the next buffer until a i2s_reg->int_st.out_eof interrupt is received. Is my understanding correct? Is this the intended behavior? If so, what is the purpose of allocating multiple buffers?

Here is some sample code to illustrate the simplest case:

#define I2S_NUM (0)
void app_main()
{
size_t bytes_written;
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
.sample_rate = 16000,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
.dma_buf_count = 8,
.dma_buf_len = 400,
.use_apll = true,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // Interrupt level 1
.tx_desc_auto_clear = false,
};
i2s_pin_config_t pin_config = {
.bck_io_num = 19,
.ws_io_num = 23,
.data_out_num = 22,
.data_in_num = -1
};
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM, &pin_config);
i2s_stop(I2S_NUM);
ESP_LOGI(TAG, "begin write");
i2s_write(I2S_NUM, "X", 1, &bytes_written, portMAX_DELAY);
ESP_LOGI(TAG, "write complete"); /* never reaches here */
}

Who is online

Users browsing this forum: MicroController and 111 guests