I2S driver for ESP32 is not working [IDFGH-5854]
-
- Posts: 15
- Joined: Thu Jul 12, 2018 11:09 am
I2S driver for ESP32 is not working [IDFGH-5854]
Hello,
I have an external ADC connected to ESP32 devkit 4. I am using the I2S interface to read left/right channel data from external ADC.
Here, I2S in ESP32 will act as master and in RX mode. So, ESP32 will generate a master clock for synchronization. My sampling frequency is 96000.
I am using GPIO0 to generate the master clock. When I checked with IDF v4.3 it was clean and perfect.
However, I am going to use the ESP32-S3 module moving further, I have updated ESP-IDF to the master branch(v4.4).
I run the latest ESP-IDF master branch code in the ESP32 chip and checked the master clock on GPIO0 to validate clock signal, It is not coming as expected. The clock signal is clipped.
Find attached image file to see the clock signal for your reference.
I have ESP32-S3 devkits-1 v1.0, I am validating the same with it. But the problem with I2S in S3 is also same, the master clock is not coming as expected. the signal is clipped.
FYI, I am looking at the below link for what are features are supported in ESP32-S3. I2S mention in the supported list.
https://www.esp32.com/viewtopic.php?f=10&t=21906
Let us know how to resolve this issue for ESP32 and ESP32-S3 in the latest master branch.
I have an external ADC connected to ESP32 devkit 4. I am using the I2S interface to read left/right channel data from external ADC.
Here, I2S in ESP32 will act as master and in RX mode. So, ESP32 will generate a master clock for synchronization. My sampling frequency is 96000.
I am using GPIO0 to generate the master clock. When I checked with IDF v4.3 it was clean and perfect.
However, I am going to use the ESP32-S3 module moving further, I have updated ESP-IDF to the master branch(v4.4).
I run the latest ESP-IDF master branch code in the ESP32 chip and checked the master clock on GPIO0 to validate clock signal, It is not coming as expected. The clock signal is clipped.
Find attached image file to see the clock signal for your reference.
I have ESP32-S3 devkits-1 v1.0, I am validating the same with it. But the problem with I2S in S3 is also same, the master clock is not coming as expected. the signal is clipped.
FYI, I am looking at the below link for what are features are supported in ESP32-S3. I2S mention in the supported list.
https://www.esp32.com/viewtopic.php?f=10&t=21906
Let us know how to resolve this issue for ESP32 and ESP32-S3 in the latest master branch.
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Moderator's note: edit the topic title for issue tracking, thanks for reporting.
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Thank you for your reporting!
Could you offer more details like what configurations you applied and is the issue only appears at 96000 Hz? And if possible, better to post a image to show how the clock clipped.
By the way, there is a bugfix for APLL on the way. If you're using APLL, please try to disable it currently, it can't generate a correct frequency now. Hope it can help
Could you offer more details like what configurations you applied and is the issue only appears at 96000 Hz? And if possible, better to post a image to show how the clock clipped.
By the way, there is a bugfix for APLL on the way. If you're using APLL, please try to disable it currently, it can't generate a correct frequency now. Hope it can help
-
- Posts: 15
- Joined: Thu Jul 12, 2018 11:09 am
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Thank you L-KAYA for the replay.
Following are the configuration for I2S driver from the application.
I have tried 48000 sampling freq also. But the results are the same. The Master clock is clipping. Find an attached image for of captured clock signal at a rate of 48k.
I have tried disabling apll source as well. But the output is the same.
Let me know you need more details.
Thanks.
Following are the configuration for I2S driver from the application.
Code: Select all
i2s_driver_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_RX, // Only RX
.sample_rate = I2S_SAMPLE_RATE, // 96000/48000
.bits_per_sample = I2S_SAMPLE_BITS, // 32 bits
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.dma_buf_count = I2S_DMA_BUF_CNT, //8 Number of DMA buffer
.dma_buf_len = I2S_DMA_BUF_LEN, // 128 //Size of each DMA buffer in Sample, 1024 * <Size of each sample which is 8 Bytes > = 8K
.use_apll = true,
.fixed_mclk = MASTER_CLK, //(12288000 * 2)
.tx_desc_auto_clear = true, //I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability)
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, //Interrupt level 1
I have tried disabling apll source as well. But the output is the same.
Let me know you need more details.
Thanks.
- Attachments
-
- mclk_signal_48k.PNG (51.5 KiB) Viewed 20557 times
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Strange, I tested signals on S3 at 96000Hz, here are my results from Oscilloscope, the clock seems not clipped
MCLK BCLK LRCK
MCLK BCLK LRCK
Last edited by L-KAYA on Tue Sep 14, 2021 9:41 am, edited 2 times in total.
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Another question, do you call any other I2S APIs after it is installed? The clock looks like disturbed by something.
Here is my test code and output for reference, I connect two s3 boards and set one in slave mode, another in master mode. at least the data seems correct.
These are the ouputs
Here is my test code and output for reference, I connect two s3 boards and set one in slave mode, another in master mode. at least the data seems correct.
- #include <stdio.h>
- #include <string.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "driver/i2s.h"
- #include "driver/gpio.h"
- #include "esp_system.h"
- #include "esp_log.h"
- #include <math.h>
- #include "hal/i2s_hal.h"
- #define SAMPLE_RATE (96000)
- #define BITS_PER_SAMPLE I2S_BITS_PER_SAMPLE_16BIT
- // #define BITS_PER_CHAN I2S_BITS_PER_CHAN_16BIT
- #define I2S_BUFF_SIZE (2560)
- #define SLAVE_MODE 0
- #define USE_I2S 0
- static const char *TAG = "i2s_loop";
- static void i2s_send(void *args)
- {
- size_t i2s_bytes_write = 0;
- uint16_t *samples_data = malloc(I2S_BUFF_SIZE * sizeof(uint16_t));
- if (!samples_data) {
- ESP_LOGE(TAG, "No memory for write data buffer");
- }
- // memset(samples_data, 0xba, I2S_BUFF_SIZE);
- for (int i = 0; i < I2S_BUFF_SIZE; i += 4) {
- samples_data[i] = 0x1234;
- samples_data[i + 1] = 0x5678;
- samples_data[i + 2] = 0x9abc;
- samples_data[i + 3] = 0xdef0;
- }
- while (1) {
- // i2s send
- if (i2s_write(USE_I2S, samples_data, I2S_BUFF_SIZE, &i2s_bytes_write, 100) != ESP_OK) {
- printf("i2s write failed.\n");
- } else {
- printf("i2s write success, %d bytes written.\n", i2s_bytes_write);
- }
- vTaskDelay(500 / portTICK_RATE_MS);
- }
- }
- static void i2s_recv(void *args)
- {
- uint16_t *read_data = malloc(I2S_BUFF_SIZE);
- if (!read_data) {
- ESP_LOGE(TAG, "No memory for read data buffer");
- }
- size_t i2s_bytes_read = 0;
- while (1) {
- memset(read_data, 0, I2S_BUFF_SIZE);
- #if 0
- // #if SOC_I2S_NUM > 1
- esp_err_t ret = i2s_read(1, read_data, I2S_BUFF_SIZE, &i2s_bytes_read, 100);
- #else
- esp_err_t ret = i2s_read(USE_I2S, read_data, I2S_BUFF_SIZE, &i2s_bytes_read, portMAX_DELAY);
- #endif
- if (ret != ESP_OK || i2s_bytes_read == 0) {
- printf("i2s read failed. read status %d, read bytes %d\n", ret, i2s_bytes_read);
- } else {
- printf("\n\ni2s read success, %d bytes read.\n---------------------------------------------------\n", i2s_bytes_read);
- printf("[0]: %x [1]: %x [2]: %x [3]: %x [4]: %x\n", read_data[100], read_data[101], read_data[102], read_data[103], read_data[104]);
- }
- #if 1
- vTaskDelay(500 / portTICK_RATE_MS);
- #else
- i2s_stop(USE_I2S);
- vTaskDelay(5000 / portTICK_RATE_MS);
- i2s_start(USE_I2S);
- #endif
- }
- }
- void app_main(void)
- {
- i2s_config_t i2s0_config = {
- #if SLAVE_MODE
- .mode = I2S_MODE_SLAVE | I2S_MODE_TX | I2S_MODE_RX,
- #else
- .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX,
- #endif
- .sample_rate = SAMPLE_RATE,
- .communication_format = I2S_COMM_FORMAT_STAND_MSB,
- .bits_per_sample = BITS_PER_SAMPLE,
- // .bits_per_chan = I2S_BITS_PER_CHAN_16BIT,
- .channel_format = I2S_CHANNEL_FMT_ALL_LEFT,
- // .channel_format = I2S_CHANNEL_FMT_MULTIPLE,
- #if SOC_I2S_SUPPORTS_TDM // TDM is only available on s3 and c3
- .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1 | I2S_TDM_ACTIVE_CH2 | I2S_TDM_ACTIVE_CH3,
- .total_chan = 4,
- .big_edin = 1,
- #endif
- .dma_buf_count = 8,
- .dma_buf_len = 128,
- .use_apll = 0,
- .fixed_mclk = 0,
- // .tx_desc_auto_clear = true,
- // .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1
- };
- i2s_pin_config_t i2s0_pin = {
- .mck_io_num = GPIO_NUM_0,
- .bck_io_num = GPIO_NUM_4,
- .ws_io_num = GPIO_NUM_5,
- .data_out_num = GPIO_NUM_18,
- .data_in_num = GPIO_NUM_19
- };
- i2s_driver_install(USE_I2S, &i2s0_config, 0, NULL);
- i2s_set_pin(USE_I2S, &i2s0_pin);
- xTaskCreate(i2s_send, "i2s_send", 4096, NULL, 5, NULL);
- xTaskCreate(i2s_recv, "i2s_recv", 4096, NULL, 5, NULL);
- }
-
- Posts: 15
- Joined: Thu Jul 12, 2018 11:09 am
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Thank you L-KAYA for explaining with example.
When I probed the MCK, BCK, LRCK with same setting, looks like outcome is matching with your sent images.
But problem is here, I am feeding 5Khz sine wave to external ADC, and capturing this data at 96000/48000 sampling frequency.
With the same code even with the correct clock on all pins, data is not coming properly. I have seen data missing in-between frequently.
Please find attached Captured sine wave image for your reference.
FYI, I have verified with ESP32 in IDF4.3, Data is absolutely prefect.
In code,
I am capturing data in one task and processing in other task using freeRTOS Queue.
Following are the codes,
Code in one task to capture and store in Queue.
Code in other task to receive and store into flash.
Can you let us know what things going wrong here.
Many thanks.
When I probed the MCK, BCK, LRCK with same setting, looks like outcome is matching with your sent images.
But problem is here, I am feeding 5Khz sine wave to external ADC, and capturing this data at 96000/48000 sampling frequency.
With the same code even with the correct clock on all pins, data is not coming properly. I have seen data missing in-between frequently.
Please find attached Captured sine wave image for your reference.
FYI, I have verified with ESP32 in IDF4.3, Data is absolutely prefect.
In code,
I am capturing data in one task and processing in other task using freeRTOS Queue.
Following are the codes,
Code: Select all
i2s_driver_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_RX, // Only RX
.sample_rate = I2S_SAMPLE_RATE, // 96000/48000
.bits_per_sample = I2S_SAMPLE_BITS, // 32 bits
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.dma_buf_count = I2S_DMA_BUF_CNT, //8 Number of DMA buffer
.dma_buf_len = I2S_DMA_BUF_LEN, // 128 Size of each DMA buffer in Sample, 1024 * <Size of each sample which is 8 Bytes > = 8K
.use_apll = false,
.fixed_mclk = 0,//MASTER_CLK, //(12288000 * 2)
.tx_desc_auto_clear = true, //I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability)
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, //Interrupt level 1
//.mclk_multiple = I2S_MCLK_MULTIPLE_256,
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_BCK_IO,
.ws_io_num = I2S_WS_IO,
.data_out_num = I2S_DO_IO,
.data_in_num = I2S_DI_IO,
.mck_io_num = I2S_MCK_IO
};
i2s_driver_install(I2S_NUM, &i2s_config, 4, &m_i2sQueue);
i2s_set_pin(I2S_NUM, &pin_config);
Code: Select all
int i2s_read_len = 128*8;
struct AMessage
{
char ucData[ 128*8 ];
} xMessage;
struct AMessage *pxMessage;
m_i2s_rcv_Queue = xQueueCreate(8, sizeof( struct AMessage * ));
while (1) {
// wait for some data to arrive on the queue
i2s_event_t evt;
if (xQueueReceive(m_i2sQueue, &evt, portMAX_DELAY) == pdPASS) {
if (evt.type == I2S_EVENT_RX_DONE) {
size_t bytesRead = 0;
//do {
// read data from the I2S peripheral
i2s_read(I2S_NUM, (void*)pxMessage->ucData, i2s_read_len, &bytesRead, 10);
// process the raw data
pxMessage = &xMessage;
if (xQueueSendToBack(m_i2s_rcv_Queue,(void *)&pxMessage,(TickType_t )portMAX_DELAY) != pdPASS ) {
//printf("Send message failed\n");
}
memset(pxMessage->ucData,0,sizeof(struct AMessage));
//} while (bytesRead > 0);
}
}
}
Code: Select all
#define FLASH_RECORD_SIZE ((I2S_CHANNEL_NUM * I2S_SAMPLE_RATE * I2S_SAMPLE_BITS / 8 ) // 1 sec
struct BMessage *pxRxedMessage;
while (1) {
if (xQueueReceive(m_i2s_rcv_Queue, &pxRxedMessage,
portMAX_DELAY) == pdPASS) {
#if 1
if (flash_wr_size < FLASH_RECORD_SIZE) {
//read data from I2S bus, in this case, from ADC.
fseek(f, flash_wr_size, SEEK_SET);
fwrite(pxRxedMessage->ucData, 1, i2s_read_len, f);
flash_wr_size += i2s_read_len;
memset(pxRxedMessage->ucData,0,sizeof(struct BMessage));
}
if (flash_wr_size >= FLASH_RECORD_SIZE) {
ESP_LOGI(TAG, "flash_wr_size %d, FLASH_RECORD_SIZE %d\n",
flash_wr_size, FLASH_RECORD_SIZE);
fclose(f);
fflush(f);
printf("Done.\n");
vTaskDelete(NULL);
}
#endif
}
}
Many thanks.
- Attachments
-
- data_singal_96k.PNG (65.5 KiB) Viewed 20446 times
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Oh, I see, I just thought the output MCLK signal clipped. Sorry for the misunderstanding.
So as you mentioned, the signal on wires is correct but the reading data is not complete, some data seems to be dropped.
Since you're using event queue, the received data can be dropped if the event queue is overflow.
To check whether the queue overflow, you can catch 'I2S_EVENT_RX_Q_OVF' event on esp-s3 (esp32 and esp-s2 not support, It will support later).
If you can catch the overflow event, you can try following ways:
1. Try to Increase the length of event queue, I2S_DMA_BUF_CNT and I2S_DMA_BUF_LEN;
2. Input a max block time in 'i2s_read' like
i2s_read(I2S_NUM, (void*)pxMessage->ucData, i2s_read_len, &bytesRead, portMAX_DELAY);
3. If method 2 not works, please try not using event queue and reading data by `i2s_read` directly(use the code in method 2). Actually I think use event queue here is not that necessary.
So as you mentioned, the signal on wires is correct but the reading data is not complete, some data seems to be dropped.
Since you're using event queue, the received data can be dropped if the event queue is overflow.
To check whether the queue overflow, you can catch 'I2S_EVENT_RX_Q_OVF' event on esp-s3 (esp32 and esp-s2 not support, It will support later).
If you can catch the overflow event, you can try following ways:
1. Try to Increase the length of event queue, I2S_DMA_BUF_CNT and I2S_DMA_BUF_LEN;
2. Input a max block time in 'i2s_read' like
i2s_read(I2S_NUM, (void*)pxMessage->ucData, i2s_read_len, &bytesRead, portMAX_DELAY);
3. If method 2 not works, please try not using event queue and reading data by `i2s_read` directly(use the code in method 2). Actually I think use event queue here is not that necessary.
-
- Posts: 15
- Joined: Thu Jul 12, 2018 11:09 am
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Dear L-KAYA,
Thanks for prompt reply.
1)As per your suggestion I checked for queue overflow, adding more validation for this 'I2S_EVENT_RX_Q_OVF' event.
However, I did not see any single time queue event overflow.
2)For extra safety, I increased queue to double the size. But the result are the same.
3) I have added max block time in 'i2s_read' call also, But the result are the same.
4) I removed event queue from code and captured data directly from i2s_read call by adding portMAX_DELAY as a last parameter.
Following are the code for that.
Find attached captured sine wave signal from other task for your reference.
Looks like here, there are something problem in I2S driver code in new IDF.
Can you help me to how figure out this problem.
Thanks for prompt reply.
1)As per your suggestion I checked for queue overflow, adding more validation for this 'I2S_EVENT_RX_Q_OVF' event.
However, I did not see any single time queue event overflow.
2)For extra safety, I increased queue to double the size. But the result are the same.
3) I have added max block time in 'i2s_read' call also, But the result are the same.
4) I removed event queue from code and captured data directly from i2s_read call by adding portMAX_DELAY as a last parameter.
Following are the code for that.
Code: Select all
//I2S DMA buffer count
#define I2S_DMA_BUF_CNT 16
//I2S DMA buffer length in samples where, Size of each sample is 8 bytes
#define I2S_DMA_BUF_LEN 128
size_t bytesRead = 0;
while (1) {
esp_err_t ret = i2s_read(I2S_NUM, (void*)pxMessage->ucData, i2s_read_len, &bytesRead, portMAX_DELAY);
if (ret != ESP_OK || bytesRead == 0) {
printf("i2s read failed. read status %d, read bytes %d\n", ret, bytesRead);
} else {
// process the raw data
pxMessage = &xMessage;
if (xQueueSendToBack(m_i2s_rcv_Queue,(void *)&pxMessage,(TickType_t )portMAX_DELAY) != pdPASS ) {
printf("Send message failed\n");
}
}
}
Looks like here, there are something problem in I2S driver code in new IDF.
Can you help me to how figure out this problem.
- Attachments
-
- data_singal_96k_without_queue.PNG (106.21 KiB) Viewed 20387 times
Re: I2S driver for ESP32 is not working [IDFGH-5854]
Sorry to hear those suggestions didn't work. Then it should be an internal issue, I don't have an available ADC board currently, so, it should still take me some time to reproduce this issue, if I find any clue, I'll post here right away.
By the way, may I ask what ADC you are using?
By the way, may I ask what ADC you are using?
Who is online
Users browsing this forum: No registered users and 136 guests