i2s_write losing data due to fail to return update pointer

chadpham75
Posts: 48
Joined: Thu Sep 12, 2019 11:39 am

i2s_write losing data due to fail to return update pointer

Postby chadpham75 » Thu Oct 17, 2019 9:59 pm

Hi all,
I am searching for the explanation/suggestions to debug this problem.
I am using I2S DMA to send out the wave file to the built-in DAC. There is a bug of loosing sound data and I trace back till I saw there data was lost because the same tx buffer got overwritten because the tx->curr_ptr didn't get update.
My I2S DMA running as a task, which will play the exactly the same sound wave

Code: Select all

xTaskCreate(SPEAKER_Run, "example_i2s_adc_dac", 1024 * 2, c, 5, &c->pSpeakerHandle);
And I have 3 different LEDs toggling with different high resolution timers.

Here is my set up for i2s configuration

Code: Select all

static void SPEAKER_I2S_Init(void)
{
	int i2s_num               = I2S_NUM;
	 i2s_config_t i2s_config  = {
		.mode                      = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
		.sample_rate            = 16000,
		.bits_per_sample      = 16,
		.communication_format = I2S_COMM_FORMAT_I2S_MSB,
		.channel_format            = I2S_CHANNEL_FMT_ONLY_RIGHT,
		.intr_alloc_flags             = 0,
		.dma_buf_count             = 2,
		.dma_buf_len                 = 1024,
		.use_apll                        = 1,
	 };

	 //install and start i2s driver
	 i2s_driver_install(i2s_num, &i2s_config, 0, NULL);

	 //init DAC pad
	 i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN); // maps to GPIO25 DAC Channel 1
}
When the DMA data got copy correctly I will see the two current pointers got updated correctly from the call of the i2s_write
I (67066) SPKER: Total Wave File Size:24257
I (67066) I2S: PLL_D2: Req RATE: 16000, real rate: 1004.000, BITS: 16, CLKM: 83, BCK: 60, MCLK: 83.333, SCLK: 32128.000000, diva: 64, divb: 21
I (67066) SPKER: Play len:2048
I (67076) I2S: CURR_PTR: 1073622200
I (67076) I2S: size: 4096, rw_pos: 0, buf_size: 2048, curr_ptr: 1073622200
I (67136) I2S: CURR_PTR: 1073620148
I (67146) I2S: size: 2048, rw_pos: 0, buf_size: 2048, curr_ptr: 1073620148
I (67146) SPKER: offset:2048

However when the sound wave data lost I will see this
I (74566) SPKER: Total Wave File Size:24257
I (74566) I2S: PLL_D2: Req RATE: 16000, real rate: 1004.000, BITS: 16, CLKM: 83, BCK: 60, MCLK: 83.333, SCLK: 32128.000000, diva: 64, divb: 21
I (74566) SPKER: Play len:2048
0I (74576) I2S: CURR_PTR: 1073620148
I (74576) I2S: size: 4096, rw_pos: 0, buf_size: 2048, curr_ptr: 1073620148
I (74636) I2S: CURR_PTR: 1073620148
I (74646) I2S: size: 2048, rw_pos: 0, buf_size: 2048, curr_ptr: 1073620148


Please help or suggest where should I do more investigation are very appreciated.
Thank you so much.

chadpham75
Posts: 48
Joined: Thu Sep 12, 2019 11:39 am

Re: i2s_write losing data due to fail to return update pointer

Postby chadpham75 » Sat Oct 19, 2019 2:51 am

I don't know if we ever got the support for these type of questions. If there is anyone out there has play with this peripheral before, please please send me the suggestion/recommendation or should we use this mcu at all?
I also tried to reach out with ESP but there is no support at all. :roll: :roll: :roll:

costaud
Posts: 55
Joined: Wed Dec 30, 2015 5:09 pm

Re: i2s_write losing data due to fail to return update pointer

Postby costaud » Mon Oct 21, 2019 6:47 am

Sorry for the late reply, but it would take some time to reproduce this issue and debug.
Surely we are working on it.

costaud
Posts: 55
Joined: Wed Dec 30, 2015 5:09 pm

Re: i2s_write losing data due to fail to return update pointer

Postby costaud » Mon Oct 21, 2019 7:01 am

1. Would you please try increasing the dma buf size and number ?

Code: Select all

.dma_buf_count             = 2,
.dma_buf_len                 = 1024,
2. Does this still happen is you disable other tasks or timer interrupts.

chadpham75
Posts: 48
Joined: Thu Sep 12, 2019 11:39 am

Re: i2s_write losing data due to fail to return update pointer

Postby chadpham75 » Mon Oct 21, 2019 11:43 pm

Hi costaud,
I have tried to increase the number of buf_count, but the max of buf_len I think it is more effective, and when I tried to change to 2048 or bigger, I will get the error.
I traced

Code: Select all

esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void* i2s_queue)
{
    esp_err_t err;
    I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
    I2S_CHECK((i2s_config != NULL), "I2S configuration must not NULL", ESP_ERR_INVALID_ARG);
    I2S_CHECK((i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), "I2S buffer count less than 128 and more than 2", ESP_ERR_INVALID_ARG);
    I2S_CHECK((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), "I2S buffer length at most 1024 and more than 8", ESP_ERR_INVALID_ARG);
the code and the IDF is limitted the size of this buf_len to 1024. Do you know if it is recommended or we can expand to more than 1024?
I didn't tried to change the sdk, since I want to keep the library as original.

Yes, if there is only task running the i2S for playing sound, I don't loose data.
It is a combo when I have the timer to drive the LEDs, and the task running at priority 5 and 100ms sleep time, I saw this artifact .

costaud
Posts: 55
Joined: Wed Dec 30, 2015 5:09 pm

Re: i2s_write losing data due to fail to return update pointer

Postby costaud » Tue Oct 22, 2019 6:24 am

chadpham75 wrote:
Mon Oct 21, 2019 11:43 pm
Yes, if there is only task running the i2S for playing sound, I don't loose data.
It is a combo when I have the timer to drive the LEDs, and the task running at priority 5 and 100ms sleep time, I saw this artifact .
Would you provide the smallest test code so that we can reproduce this issue ?
Or, would you provide the code of the timer part?

chadpham75
Posts: 48
Joined: Thu Sep 12, 2019 11:39 am

Re: i2s_write losing data due to fail to return update pointer

Postby chadpham75 » Tue Oct 22, 2019 1:17 pm

I am using PWM to drive 3 set of LEDs (3x RGB) toggle 250ms on/off
The LEDs initialization

Code: Select all

static const ledc_channel_config_t ledc_channel[LEDC_CHANNEL_COUNT] =
{
	{
		.channel    = LEDC_HS_CH0_CHANNEL,
		.duty       = 0,
		.gpio_num   = BLUE1_N,
		.speed_mode = LEDC_HS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_HS_TIMER0
	},
	{
		.channel    = LEDC_HS_CH1_CHANNEL,
		.duty       = 0,
		.gpio_num   = GREEN1_N,
		.speed_mode = LEDC_HS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_HS_TIMER0
	},
	{
		.channel    = LEDC_HS_CH2_CHANNEL,
		.duty       = 0,
		.gpio_num   = RED1_N,
		.speed_mode = LEDC_HS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_HS_TIMER0
	},
	{
		.channel    = LEDC_HS_CH3_CHANNEL,
		.duty       = 0,
		.gpio_num   = BLUE2_N,
		.speed_mode = LEDC_HS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_HS_TIMER0
	},
	{
		.channel    = LEDC_HS_CH4_CHANNEL,
		.duty       = 0,
		.gpio_num   = GREEN2_N,
		.speed_mode = LEDC_HS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_HS_TIMER0
	},
	{
		.channel    = LEDC_HS_CH5_CHANNEL,
		.duty       = 0,
		.gpio_num   = RED2_N,
		.speed_mode = LEDC_HS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_HS_TIMER0
	},
	{
		.channel    = LEDC_HS_CH6_CHANNEL,
		.duty       = 0,
		.gpio_num   = BLUE3_N,
		.speed_mode = LEDC_HS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_HS_TIMER0
	},
	{
		.channel    = LEDC_HS_CH7_CHANNEL,
		.duty       = 0,
		.gpio_num   = GREEN3_N,
		.speed_mode = LEDC_HS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_HS_TIMER0
	},
	{
		.channel    = LEDC_LS_CH0_CHANNEL,
		.duty       = 0,
		.gpio_num   = RED3_N,
		.speed_mode = LEDC_LS_MODE,
		.hpoint     = 0,
		.timer_sel  = LEDC_LS_TIMER0
	},
}; // end ledc_channel_config_t
{
	// Prepare and set configuration of timers that will be used by LED Controller
	ledc_timer_config_t ledc_timer0 =
	{
		.duty_resolution = LEDC_TIMER_13_BIT, // resolution of PWM duty
		.freq_hz = 5000,                      // frequency of PWM signal
		.speed_mode = LEDC_HS_MODE,           // timer mode
		.timer_num = LEDC_HS_TIMER0           // timer index
	};


	// Set configuration of timer0 ~ timer3 for high speed channels
	ledc_timer_config(&ledc_timer0);

	// Prepare and set configuration of timer0 for low speed channels
	ledc_timer_config_t ledc_timer0_LS =
	{
		.duty_resolution = LEDC_TIMER_13_BIT, // resolution of PWM duty
		.freq_hz = 5000,                      // frequency of PWM signal
		.speed_mode = LEDC_LS_MODE,           // timer mode
		.timer_num = LEDC_LS_TIMER0           // timer index
	};


	ledc_timer_config(&ledc_timer0_LS);

	// Set LED Controller with previously prepared configuration
	int ch;
	for (ch = 0; ch < LEDC_CHANNEL_COUNT; ch++)
	{
		ledc_channel_config2(&ledc_channel[ch]);
	}

    // Initialize fade service.
	ledc_fade_func_install(0);
} // end init_PWM()

ESP_houwenxiang
Posts: 118
Joined: Tue Jun 26, 2018 3:09 am

Re: i2s_write losing data due to fail to return update pointer

Postby ESP_houwenxiang » Wed Oct 23, 2019 2:37 am

Hi,
Can you make the I2S task run at a higher priority? At the same time you can increase the `dma_buf_count`.
wookooho

chadpham75
Posts: 48
Joined: Thu Sep 12, 2019 11:39 am

Re: i2s_write losing data due to fail to return update pointer

Postby chadpham75 » Wed Oct 23, 2019 6:46 am

ESP_houwenxiang,
I am running the LEDs using high resolution timer, I couldn't find the information of what is the task priority of this high resolution timer. Do you have any idea?
When I tried to dump out the task priority from the LED's timer call back

Code: Select all

uint32_t wPriority = uxTaskPriorityGetFromISR(NULL);
	ESP_LOGI(TAG, "LED priority:%d", wPriority);
I saw
I (24694) LED: LED priority:22
I (24694) LED: LED priority:22
I (24804) LED: LED priority:22
I (24944) LED: LED priority:22
I (24944) LED: LED priority:22
I (25054) LED: LED priority:22

I tried to raise i2s task to 8 from 5, I still saw the repeated buffer pointer, but when raised to 10 or 23, I didn't see the lost buffer point as original issue, but the sound is till clipping at the beginning. I will use the scope to see if the clipping is actually the losing of data.
1. Can you clarify if 22 is actual high resolution timer task priority?
2. Do I need to raise it to 23?
3. Is there any recommend or instructions to correct way to create signed 16 bit sound wave before I feed them to generate_audio_file.py to create the header file to minimize the noise?
Thank you so much for your helps.

ESP_houwenxiang
Posts: 118
Joined: Tue Jun 26, 2018 3:09 am

Re: i2s_write losing data due to fail to return update pointer

Postby ESP_houwenxiang » Wed Oct 23, 2019 1:40 pm

Hi,
I mean that you can improve the ADC task priority and increase the buffer count:

Code: Select all

    int i2s_num               = I2S_NUM;
	 i2s_config_t i2s_config  = {
		.mode                      = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
		.sample_rate            = 16000,
		.bits_per_sample      = 16,
		.communication_format = I2S_COMM_FORMAT_I2S_MSB,
		.channel_format            = I2S_CHANNEL_FMT_ONLY_RIGHT,
		.intr_alloc_flags             = 0,
		.dma_buf_count             = 4,
		.dma_buf_len                 = 1024,
		.use_apll                        = 1,
	 };

xTaskCreate(SPEAKER_Run, "example_i2s_adc_dac", 1024 * 2, c, 8, &c->pSpeakerHandle);
wookooho

Who is online

Users browsing this forum: Majestic-12 [Bot] and 83 guests