I2S driver for ESP32 is not working [IDFGH-5854]

shailesh.korat
Posts: 15
Joined: Thu Jul 12, 2018 11:09 am

I2S driver for ESP32 is not working [IDFGH-5854]

Postby shailesh.korat » Tue Sep 14, 2021 3:35 am

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.

ESP_Alvin
Posts: 195
Joined: Thu May 17, 2018 2:26 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby ESP_Alvin » Tue Sep 14, 2021 7:07 am

Moderator's note: edit the topic title for issue tracking, thanks for reporting.

L-KAYA
Posts: 22
Joined: Thu Aug 12, 2021 3:44 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby L-KAYA » Tue Sep 14, 2021 7:46 am

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

shailesh.korat
Posts: 15
Joined: Thu Jul 12, 2018 11:09 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby shailesh.korat » Tue Sep 14, 2021 7:56 am

Thank you L-KAYA for the replay.

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 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.
Attachments
mclk_signal_48k.PNG
mclk_signal_48k.PNG (51.5 KiB) Viewed 17278 times

L-KAYA
Posts: 22
Joined: Thu Aug 12, 2021 3:44 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby L-KAYA » Tue Sep 14, 2021 9:25 am

Strange, I tested signals on S3 at 96000Hz, here are my results from Oscilloscope, the clock seems not clipped

MCLK
IMG_20210914_165318.jpg
MCLK
IMG_20210914_165318.jpg (2.7 MiB) Viewed 17259 times
BCLK
IMG_20210914_171444.jpg
BCLK
IMG_20210914_171444.jpg (2.77 MiB) Viewed 17259 times
LRCK
IMG_20210914_171424.jpg
LRCK
IMG_20210914_171424.jpg (2.62 MiB) Viewed 17259 times
Last edited by L-KAYA on Tue Sep 14, 2021 9:41 am, edited 2 times in total.

L-KAYA
Posts: 22
Joined: Thu Aug 12, 2021 3:44 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby L-KAYA » Tue Sep 14, 2021 9:32 am

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.
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "freertos/FreeRTOS.h"
  4. #include "freertos/task.h"
  5. #include "driver/i2s.h"
  6. #include "driver/gpio.h"
  7. #include "esp_system.h"
  8. #include "esp_log.h"
  9. #include <math.h>
  10. #include "hal/i2s_hal.h"
  11.  
  12.  
  13. #define SAMPLE_RATE     (96000)
  14. #define BITS_PER_SAMPLE I2S_BITS_PER_SAMPLE_16BIT
  15. // #define BITS_PER_CHAN   I2S_BITS_PER_CHAN_16BIT
  16. #define I2S_BUFF_SIZE   (2560)
  17. #define SLAVE_MODE      0
  18. #define USE_I2S         0
  19.  
  20. static const char *TAG = "i2s_loop";
  21.  
  22. static void i2s_send(void *args)
  23. {
  24.     size_t i2s_bytes_write = 0;
  25.     uint16_t *samples_data = malloc(I2S_BUFF_SIZE * sizeof(uint16_t));
  26.     if (!samples_data) {
  27.         ESP_LOGE(TAG, "No memory for write data buffer");
  28.     }
  29.     // memset(samples_data, 0xba, I2S_BUFF_SIZE);
  30.     for (int i = 0; i < I2S_BUFF_SIZE; i += 4) {
  31.         samples_data[i] = 0x1234;
  32.         samples_data[i + 1] = 0x5678;
  33.         samples_data[i + 2] = 0x9abc;
  34.         samples_data[i + 3] = 0xdef0;
  35.     }
  36.     while (1) {
  37.         // i2s send
  38.         if (i2s_write(USE_I2S, samples_data, I2S_BUFF_SIZE, &i2s_bytes_write, 100) != ESP_OK) {
  39.             printf("i2s write failed.\n");
  40.         } else {
  41.             printf("i2s write success, %d bytes written.\n", i2s_bytes_write);
  42.         }
  43.         vTaskDelay(500 / portTICK_RATE_MS);
  44.     }
  45. }
  46.  
  47. static void i2s_recv(void *args)
  48. {
  49.     uint16_t *read_data = malloc(I2S_BUFF_SIZE);
  50.     if (!read_data) {
  51.         ESP_LOGE(TAG, "No memory for read data buffer");
  52.     }
  53.     size_t i2s_bytes_read = 0;
  54.     while (1) {
  55.         memset(read_data, 0, I2S_BUFF_SIZE);
  56. #if 0
  57. // #if SOC_I2S_NUM > 1
  58.         esp_err_t ret = i2s_read(1, read_data, I2S_BUFF_SIZE, &i2s_bytes_read, 100);
  59. #else
  60.         esp_err_t ret = i2s_read(USE_I2S, read_data, I2S_BUFF_SIZE, &i2s_bytes_read, portMAX_DELAY);
  61. #endif
  62.         if (ret != ESP_OK || i2s_bytes_read == 0) {
  63.             printf("i2s read failed. read status %d, read bytes %d\n", ret, i2s_bytes_read);
  64.         } else {
  65.             printf("\n\ni2s read success, %d bytes read.\n---------------------------------------------------\n", i2s_bytes_read);
  66.             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]);
  67.         }
  68. #if 1
  69.         vTaskDelay(500 / portTICK_RATE_MS);
  70. #else
  71.         i2s_stop(USE_I2S);
  72.         vTaskDelay(5000 / portTICK_RATE_MS);
  73.         i2s_start(USE_I2S);
  74. #endif
  75.  
  76.     }
  77. }
  78.  
  79. void app_main(void)
  80. {
  81.     i2s_config_t i2s0_config = {
  82. #if SLAVE_MODE
  83.         .mode = I2S_MODE_SLAVE | I2S_MODE_TX | I2S_MODE_RX,
  84. #else
  85.         .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX,
  86. #endif
  87.         .sample_rate = SAMPLE_RATE,
  88.         .communication_format = I2S_COMM_FORMAT_STAND_MSB,
  89.         .bits_per_sample = BITS_PER_SAMPLE,
  90.         // .bits_per_chan = I2S_BITS_PER_CHAN_16BIT,
  91.         .channel_format = I2S_CHANNEL_FMT_ALL_LEFT,
  92.         // .channel_format = I2S_CHANNEL_FMT_MULTIPLE,
  93. #if SOC_I2S_SUPPORTS_TDM    // TDM is only available on s3 and c3
  94.         .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1 | I2S_TDM_ACTIVE_CH2 | I2S_TDM_ACTIVE_CH3,
  95.         .total_chan = 4,
  96.         .big_edin = 1,
  97. #endif
  98.         .dma_buf_count = 8,
  99.         .dma_buf_len = 128,
  100.         .use_apll = 0,
  101.         .fixed_mclk = 0,
  102.         // .tx_desc_auto_clear = true,
  103.         // .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1
  104.     };
  105.  
  106.     i2s_pin_config_t i2s0_pin = {
  107.         .mck_io_num = GPIO_NUM_0,
  108.         .bck_io_num = GPIO_NUM_4,
  109.         .ws_io_num = GPIO_NUM_5,
  110.         .data_out_num = GPIO_NUM_18,
  111.         .data_in_num = GPIO_NUM_19
  112.     };
  113.     i2s_driver_install(USE_I2S, &i2s0_config, 0, NULL);
  114.     i2s_set_pin(USE_I2S, &i2s0_pin);
  115.  
  116.     xTaskCreate(i2s_send, "i2s_send", 4096, NULL, 5, NULL);
  117.     xTaskCreate(i2s_recv, "i2s_recv", 4096, NULL, 5, NULL);
  118. }
These are the ouputs
Image2.png
Image2.png (790.79 KiB) Viewed 17223 times

shailesh.korat
Posts: 15
Joined: Thu Jul 12, 2018 11:09 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby shailesh.korat » Thu Sep 16, 2021 2:08 am

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: 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 in one task to capture and store in Queue.

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 in other task to receive and store into flash.

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
		}
	}
Can you let us know what things going wrong here.

Many thanks.
Attachments
data_singal_96k.PNG
data_singal_96k.PNG (65.5 KiB) Viewed 17167 times

L-KAYA
Posts: 22
Joined: Thu Aug 12, 2021 3:44 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby L-KAYA » Thu Sep 16, 2021 2:43 am

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.

shailesh.korat
Posts: 15
Joined: Thu Jul 12, 2018 11:09 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby shailesh.korat » Thu Sep 16, 2021 7:55 am

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.

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");
								}
				        }
	}			        
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.
Attachments
data_singal_96k_without_queue.PNG
data_singal_96k_without_queue.PNG (106.21 KiB) Viewed 17108 times

L-KAYA
Posts: 22
Joined: Thu Aug 12, 2021 3:44 am

Re: I2S driver for ESP32 is not working [IDFGH-5854]

Postby L-KAYA » Thu Sep 16, 2021 8:03 am

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?

Who is online

Users browsing this forum: FrankJensen and 110 guests