help needed: possible race condition when i2s devices on different I2S interfaces are coupled by a pipeline
Posted: Tue Mar 25, 2025 5:43 am
My app needs to implement a dsp between a microphone input and a speaker output. A year ago, we sucessfully implemented it using esp-adf and the audiokit v 2.2 board. This board, which is very similar to the lyrat v4.3, uses a single codec for both microphone and speaker, and the board_config assigns them both to I2S_NUM_0. Our app was modeled on the "pipeline_passthru" example app and was very relialble.
This week, I modified this app to work with the lyrat mini v1.2. Unlike the audiokit, this board uses distinct codecs with clock signals attached to different gpio pins. The available board_config (documented as being v1.1 of this board) uses the same gpio pins as the 1.2 board. This board config assigns the output codec to I2S_NUM_0, and the input codec to I2S_NUM_1.
The only modification required for my program was to change its input to use I2S_NUM_1. Here's the one line of code that I modified:
The resulting program is unreliable in an interesting way: Sometimes it starts (and works) correctly, other times it does not. When it doe not, date from the input codec seems to be framed incorrectly.
I then tried the pipeline_passthru example program with this board and the same input config as my app. The program was unreliable in the same way as my app.
I wonder if there's a race condition during initialization when a single pipeline connects different I2S subsystems. If so, would it be circumvented by implementing two distinct pipelines - one for input, the other for output, and then implementing a queue to connect them.
Thanks, Eric
eric@freudenthal.net
This week, I modified this app to work with the lyrat mini v1.2. Unlike the audiokit, this board uses distinct codecs with clock signals attached to different gpio pins. The available board_config (documented as being v1.1 of this board) uses the same gpio pins as the 1.2 board. This board config assigns the output codec to I2S_NUM_0, and the input codec to I2S_NUM_1.
The only modification required for my program was to change its input to use I2S_NUM_1. Here's the one line of code that I modified:
Code: Select all
# ifdef CONFIG_ESP_LYRAT_MINI_V1_1_BOARD
i2s_stream_cfg_t i2s_cfg_read = I2S_STREAM_CFG_DEFAULT_WITH_PARA(I2S_NUM_1, 44100, I2S_DATA_BIT_WIDTH_16BIT, AUDIO_STREAM_READER); //I2S_STREAM_CFG_DEFAULT();
# else
i2s_stream_cfg_t i2s_cfg_read = I2S_STREAM_CFG_DEFAULT();
# endifI then tried the pipeline_passthru example program with this board and the same input config as my app. The program was unreliable in the same way as my app.
I wonder if there's a race condition during initialization when a single pipeline connects different I2S subsystems. If so, would it be circumvented by implementing two distinct pipelines - one for input, the other for output, and then implementing a queue to connect them.
Thanks, Eric
eric@freudenthal.net