I2S_write doesn't resume task fast enough

cammiboi
Posts: 6
Joined: Tue Feb 20, 2018 6:08 am

I2S_write doesn't resume task fast enough

Postby cammiboi » Tue Oct 23, 2018 12:06 am

Hi there,

I am trying to play a .wav file using the ESP32, I have successfully set up the I2S driver to send data to an external codec chip.

My issue however is when I call I2S_write to write the next 1024 bytes of wav data, like this: It doesnt return in time to cleanly write the next 1024 byte sample

Code: Select all

i2s_write(I2S_NUM, (const char *)wavBuffer, 1024, &bytesWritten, portMAX_DELAY);
I am having trouble where when running a different lower priority task that blocks for a significant amount of time, there is glitch in the playback until the other task unblocks. Is it possible to have an interrupt that fires once the i2s_write function returns and is ready to accept more data into the buffer? That way it would interrupt any other task that's blocking?

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: I2S_write doesn't resume task fast enough

Postby ESP_Sprite » Tue Oct 23, 2018 2:38 am

That does not make sense. A lower priority task should always be pre-empted by a higher priority task, so if the task that feeds the I2S driver has a high priority, it should always be un-blocked in time. Are you sure the delay is not somewhere else, e.g. in the code reading in the wav file?

cammiboi
Posts: 6
Joined: Tue Feb 20, 2018 6:08 am

Re: I2S_write doesn't resume task fast enough

Postby cammiboi » Tue Oct 23, 2018 4:08 am

Okay, I may not understand how tasks are blocked/ unblocked fully.

When I don't initialize the lower priority task, the wav player task runs without glitching. However when the other task is running, the wav task glitches.

The lower priority task reads a text file and parses it. The wav task reads 1024 bytes at a time from a wav file into a buffer of 1024 chars and then is written to the I2S buffer using I2S_write. Both tasks use fopen, fread ect with SPIFFS.

I have a question, if the lower priority task takes some time to execute before any calls to a function like vTaskDelay is called, would it block higher priority tasks? For example if the lower priority task had this code:

Code: Select all

void lowPriorityTask(void *parameters)
{
	while(1)
	{
		for(uint32_t i = 0; i < 200000; i++){ }
		vTaskDelay(1000);
	}
}
And the high priority task was:

Code: Select all

void highPriorityTask(void *parameters)
{
// this loops a number of times, each time a new 1024 bytes of wavBuffer is to be written
...
i2s_write(I2S_NUM, (const char *)wavBuffer, 1024, &bytesWritten, portMAX_DELAY);
...
}
Would the high priority task interrupt the for loop while it is running to return from the I2S_write function in the high priority task?

If I understand correctly if you fill up the I2S buffer with I2S_write, the function will wait and return once there is room in the buffer to store more data?

User avatar
fly135
Posts: 606
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: I2S_write doesn't resume task fast enough

Postby fly135 » Tue Oct 23, 2018 5:33 pm

Read the file from another task and fill a queue for the I2S writer task. IOW try to get ahead on the reading whenever you can.

John A

cammiboi
Posts: 6
Joined: Tue Feb 20, 2018 6:08 am

Re: I2S_write doesn't resume task fast enough

Postby cammiboi » Tue Oct 23, 2018 6:22 pm

Okay thank you! Ill try that out.

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: I2S_write doesn't resume task fast enough

Postby ESP_Sprite » Wed Oct 24, 2018 2:26 am

Wrt your priority question: yes, a higher-priority task will always interrupt a low-priority task the moment whatever it was blocking on (e.g. i2s data that is being sent) stops blocking it. My guess is that your issue here may be priority inversion because of mutexes: I don't know the spiffs subsystem well enough, but I can imagine it has a mutex to make sure only one task can do a read/write/... at a time. If this is the case, while your lower-prio task is busy reading, your higher-prio task may be blocked for a small amount of time. If your I2S buffers (you specify the size of those when you initialize I2S) are too small, you can get hickups because of that.

The solution in that case would be to raise the size of the I2S buffers. The more complex solution fly135 mentions would also work, but increasing the i2s buffer size / count is easier and works as well.

User avatar
fly135
Posts: 606
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: I2S_write doesn't resume task fast enough

Postby fly135 » Wed Oct 24, 2018 3:27 pm

ESP_Sprite wrote:The solution in that case would be to raise the size of the I2S buffers. The more complex solution fly135 mentions would also work, but increasing the i2s buffer size / count is easier and works as well.
Yes, my solution is more complex. But if you are designing a much bigger application then the amount of memory available for DMA, multiple tasks and stacks, and other internal ram usage can become critical. If you are designing a comprehensive application that has ext SPI ram then my approach becomes a more serious consideration. If you are simply designing a test app or a small application with no ext ram, then my approach is overly complicated.

Since my work with the ESP32 is in the category of a large app with lots of memory usage I tend to advice people from that perspective.

John A

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: I2S_write doesn't resume task fast enough

Postby ESP_Sprite » Thu Oct 25, 2018 2:21 am

fly135 wrote: Yes, my solution is more complex. But if you are designing a much bigger application then the amount of memory available for DMA, multiple tasks and stacks, and other internal ram usage can become critical.
Ah, I forgot about that detail, as most of my I2S-based things, in contrast to yours, only use internal RAM. I agree, if you use SPI RAM, then increasing the buffer size will deplete your internal RAM and if you have too little of that, it's better to have an external buffer that can be placed in SPI RAM.

cammiboi
Posts: 6
Joined: Tue Feb 20, 2018 6:08 am

Re: I2S_write doesn't resume task fast enough

Postby cammiboi » Thu Oct 25, 2018 7:33 am

The solution in that case would be to raise the size of the I2S buffers.
Thanks for the suggestion ESP_Sprite, I increased .dma_buf_count from 2 to 10 and the problem with skipping on playback is now resolved! That makes sense that another task also using SPIFFS was possibly causing a delay in the read of the wav file, but with the larger buffer it seems to now always be able to read the wav file and keep the buffer filled before the playback reaches the end of the buffer.

fly135 I may use your suggestion if I notice the problem come up again with the increased buffer count.

Thanks for your help :)

Who is online

Users browsing this forum: No registered users and 121 guests