@@ -23,8 +23,8 @@ static const char *TAG = "i2s_multi_dev_test";
2323
2424#define TEST_I2S_FRAME_SIZE (128) // Frame numbers in every writing / reading
2525#define TEST_I2S_ARRAY_LENGTH (1024) // The loop data length for verification
26- #define TEST_I2S_MAX_DATA (128) // The maximum data value in the data buffer
27- #define TEST_I2S_MAX_FAIL_CNT (3) // Max broken packet count
26+ #define TEST_I2S_MAX_DATA (64) // The maximum data value in the data buffer
27+ #define TEST_I2S_MAX_FAIL_CNT (10) // Max broken packet count
2828#define TEST_I2S_FRAME_TIMEOUT_SEC (10.0f) // Timeout seconds of waiting for a correct frame
2929
3030#define TEST_I2S_NUM (I2S_NUM_0) // ESP32-C3 has only I2S0
@@ -39,6 +39,12 @@ static const char *TAG = "i2s_multi_dev_test";
3939#define TEST_I2S_DI_IO (GPIO_NUM_7) // DI and DO gpio will be reversed on slave runner
4040#endif // CONFIG_IDF_TARGET_ESP32H2
4141
42+ #if I2S_LL_DEFAULT_CLK_FREQ < 160000000
43+ #define TEST_SAMPLE_RATE (16000) // I2S source clock is relatively low, test case is not stable when sample rate is 48KHz high
44+ #else
45+ #define TEST_SAMPLE_RATE (48000)
46+ #endif
47+
4248typedef struct {
4349 uint32_t * buffer ;
4450 uint32_t buffer_size ;
@@ -71,27 +77,25 @@ static void test_i2s_tdm_master(uint32_t sample_rate, i2s_data_bit_width_t bit_w
7177 i2s_tdm_config_t i2s_tdm_config = {
7278 .clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG (sample_rate ),
7379 .slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG (bit_width , I2S_SLOT_MODE_STEREO , slot_mask ),
74- .gpio_cfg = TEST_I2S_DEFAULT_GPIO (GPIO_NUM_NC , true),
80+ .gpio_cfg = TEST_I2S_DEFAULT_GPIO (I2S_GPIO_UNUSED , true),
7581 };
76- i2s_tdm_config .clk_cfg .mclk_multiple = I2S_MCLK_MULTIPLE_384 ;
82+ i2s_tdm_config .clk_cfg .mclk_multiple = I2S_MCLK_MULTIPLE_512 ;
7783 TEST_ESP_OK (i2s_channel_init_tdm_mode (i2s_tdm_tx_handle , & i2s_tdm_config ));
7884 TEST_ESP_OK (i2s_channel_init_tdm_mode (i2s_tdm_rx_handle , & i2s_tdm_config ));
7985
8086 uint32_t channel_count = 32 - __builtin_clz (slot_mask );
81- size_t buf_size = channel_count * TEST_I2S_FRAME_SIZE * (bit_width / 8 );
87+ size_t buf_size = channel_count * TEST_I2S_FRAME_SIZE * (bit_width / 8 ) * 2 ;
8288 /* Allocate I2S rx buffer */
8389 ESP_LOGI (TAG , "Allocating I2S TDM master rx buffer, size=%u" , buf_size );
84- uint32_t * rx_buffer = malloc ( buf_size );
90+ uint8_t * rx_buffer = calloc ( 1 , buf_size );
8591 TEST_ASSERT (rx_buffer );
8692 /* Allocate I2S tx buffer */
8793 ESP_LOGI (TAG , "Allocating I2S TDM master tx buffer, size=%u" , buf_size );
88- uint32_t * tx_buffer = malloc ( buf_size );
94+ uint8_t * tx_buffer = calloc ( 1 , buf_size );
8995 TEST_ASSERT (tx_buffer );
9096 /* Fill in the tx buffer */
91- for (uint32_t i = 0 , data_cnt = 0 ; i < buf_size / sizeof (uint32_t ); i ++ ) {
92- tx_buffer [i ] = data_cnt ;
93- data_cnt ++ ;
94- data_cnt %= TEST_I2S_MAX_DATA ;
97+ for (uint32_t i = 0 ; i < buf_size ; i ++ ) {
98+ tx_buffer [i ] = i % TEST_I2S_MAX_DATA ;
9599 }
96100 size_t w_bytes = buf_size ;
97101 while (w_bytes != 0 ) {
@@ -107,22 +111,39 @@ static void test_i2s_tdm_master(uint32_t sample_rate, i2s_data_bit_width_t bit_w
107111 /* Slave is ready, start the writing task */
108112 ESP_LOGI (TAG , "I2S TDM master receive & send start" );
109113 esp_err_t read_ret = ESP_OK ;
110- uint32_t count = 1 ;
114+ uint8_t count = 1 ;
111115 uint8_t fail_cnt = 0 ;
112116 size_t bytes_read = 0 ;
117+ unity_wait_for_signal ("Slave Data Ready" );
118+ // Start to read the data from slave, and retry several times if not success
113119 for (fail_cnt = 0 ; fail_cnt < TEST_I2S_MAX_FAIL_CNT && count < TEST_I2S_MAX_DATA ; fail_cnt ++ ) {
114- if (i2s_channel_read (i2s_tdm_rx_handle , rx_buffer , buf_size , & bytes_read , 1000 ) != ESP_OK ) {
120+ if (fail_cnt > 0 ) {
121+ // Delay a while in case the slave has not finished to prepare the data
122+ vTaskDelay (pdMS_TO_TICKS (50 ));
123+ }
124+ // Try to read the data from slave, continue if failed
125+ read_ret = i2s_channel_read (i2s_tdm_rx_handle , rx_buffer , buf_size , & bytes_read , 1000 );
126+ if (read_ret != ESP_OK ) {
127+ ESP_LOGE (TAG , "master read failed: %s" , esp_err_to_name (read_ret ));
115128 continue ;
116129 }
117- for (int i = 0 ; i < buf_size && count < TEST_I2S_MAX_DATA ; i ++ ) {
130+ // When success to read, check the buffer content whether match what master sent
131+ for (int i = 0 ; i < buf_size ; i ++ ) {
132+ printf ("%" PRIu8 " " , rx_buffer [i ]);
118133 if (rx_buffer [i ] == count ) {
119- count ++ ;
134+ // If the piece of data match, means the communication between slave and master success, break the loop
135+ if (++ count >= TEST_I2S_MAX_DATA ) {
136+ break ;
137+ }
120138 } else if (count != 1 ) {
121- ESP_LOGE (TAG , "Failed at index: %d real: %" PRIu32 " expect: %" PRIu32 , i , rx_buffer [i ], count );
139+ // If the data not fully matched, reset the counter and try again
140+ ESP_LOGE (TAG , "Failed at index: %d real: %" PRIu8 " expect: %" PRIu8 , i , rx_buffer [i ], count );
122141 count = 1 ;
123142 }
124143 }
144+ printf ("\n" );
125145 }
146+ unity_send_signal ("Master Finished" );
126147
127148 ESP_LOGI (TAG , "I2S TDM master stop" );
128149 TEST_ESP_OK (i2s_channel_disable (i2s_tdm_tx_handle ));
@@ -132,7 +153,7 @@ static void test_i2s_tdm_master(uint32_t sample_rate, i2s_data_bit_width_t bit_w
132153 TEST_ESP_OK (i2s_del_channel (i2s_tdm_rx_handle ));
133154 TEST_ESP_OK (i2s_del_channel (i2s_tdm_tx_handle ));
134155 ESP_LOGI (TAG , "I2S TDM master resources freed" );
135- TEST_ASSERT_TRUE_MESSAGE (read_ret == ESP_OK , "Master read timeout " );
156+ TEST_ASSERT_TRUE_MESSAGE (read_ret == ESP_OK , "Master read failed " );
136157 TEST_ASSERT_TRUE_MESSAGE (fail_cnt < TEST_I2S_MAX_FAIL_CNT , "Exceed retry times " );
137158 TEST_ASSERT_EQUAL_UINT32 (TEST_I2S_MAX_DATA , count );
138159}
@@ -143,10 +164,11 @@ static void test_i2s_tdm_slave(uint32_t sample_rate, i2s_data_bit_width_t bit_wi
143164 i2s_chan_handle_t i2s_tdm_rx_handle = NULL ;
144165
145166 /* Create I2S tx and rx channels */
167+ uint32_t desc_num = 4 ;
146168 i2s_chan_config_t i2s_channel_config = {
147169 .id = TEST_I2S_NUM ,
148170 .role = I2S_ROLE_SLAVE ,
149- .dma_desc_num = 4 ,
171+ .dma_desc_num = desc_num ,
150172 .dma_frame_num = TEST_I2S_FRAME_SIZE ,
151173 .auto_clear = false
152174 };
@@ -156,84 +178,113 @@ static void test_i2s_tdm_slave(uint32_t sample_rate, i2s_data_bit_width_t bit_wi
156178 i2s_tdm_config_t i2s_tdm_config = {
157179 .clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG (sample_rate ),
158180 .slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG (bit_width , I2S_SLOT_MODE_STEREO , slot_mask ),
159- .gpio_cfg = TEST_I2S_DEFAULT_GPIO (GPIO_NUM_NC , false),
181+ .gpio_cfg = TEST_I2S_DEFAULT_GPIO (I2S_GPIO_UNUSED , false),
160182 };
161- if (sample_rate >= 96000 ) {
162- i2s_tdm_config .clk_cfg .bclk_div = 12 ;
163- }
164183#if SOC_I2S_SUPPORTS_APLL
165184 i2s_tdm_config .clk_cfg .clk_src = I2S_CLK_SRC_APLL ;
185+ /* APLL clock source can only reach upto 125MHz, and the max BCLK among these cases is 6.144 MHz
186+ The BCLK can only be 10 using APLL clock source, see the reason below
187+ Formula: MAX_BCLK = 48K * 32 * 4 = 6.144 MHz. MAX_BCLK_DIV <= (125 /2) / MAX_BCLK */
188+ i2s_tdm_config .clk_cfg .bclk_div = 10 ;
189+ #else
190+ /* The greater the bclk division is, the greater mclk frequency will be, and the less data latency the slave will have
191+ As the sample rate of the test cases are high, we need a greater BCLK division to reduce the slave data latency,
192+ Otherwise the large data latency will cause the data shifted when receiving on the master side.
193+ However, due to the MCLK limitation(i.e., less or equal than half of the source clock),
194+ the max bclk division is depended on the source clock, sample rate and the bclk ticks in one frame
195+ Formula: MAX_BCLK = 48K * 32 * 4 = 6.144 MHz. MAX_BCLK_DIV <= (160 /2) / MAX_BCLK */
196+ i2s_tdm_config .clk_cfg .bclk_div = 12 ;
166197#endif
167198 TEST_ESP_OK (i2s_channel_init_tdm_mode (i2s_tdm_tx_handle , & i2s_tdm_config ));
168199 TEST_ESP_OK (i2s_channel_init_tdm_mode (i2s_tdm_rx_handle , & i2s_tdm_config ));
169200
170201 /* Allocate I2S rx buffer */
171202 uint32_t channel_count = 32 - __builtin_clz (slot_mask );
172- uint32_t buffer_size = TEST_I2S_FRAME_SIZE * channel_count * (bit_width / 8 );
203+ uint32_t buffer_size = TEST_I2S_FRAME_SIZE * channel_count * (bit_width / 8 ) * 2 ;
173204 ESP_LOGI (TAG , "Allocating I2S TDM slave buffer, size=%" PRIu32 , buffer_size );
174- uint32_t * echo_buffer = malloc ( buffer_size );
205+ uint8_t * echo_buffer = calloc ( 1 , buffer_size );
175206 TEST_ASSERT (echo_buffer );
176207
177208 unity_send_signal ("Slave Ready" );
178209 unity_wait_for_signal ("Master Ready" );
179210 TEST_ESP_OK (i2s_channel_enable (i2s_tdm_rx_handle ));
180- TEST_ESP_OK (i2s_channel_enable (i2s_tdm_tx_handle ));
181211
182212 ESP_LOGI (TAG , "I2S TDM slave receive & send start" );
183- size_t bytes_read = 0 , bytes_written = 0 ;
184- /* Loop until reading or writing failed, which indicates the master has finished and deleted the I2S peripheral */
213+ size_t bytes_read = 0 ;
214+ int read_fail_cnt = 0 ;
215+ bool success_flag = true;
216+ // Continuously read data from master until the first piece of valid data is received
185217 while (true) {
186- if (i2s_channel_read (i2s_tdm_rx_handle , echo_buffer , buffer_size , & bytes_read , 500 ) != ESP_OK ) {
187- break ;
218+ if (i2s_channel_read (i2s_tdm_rx_handle , echo_buffer , buffer_size , & bytes_read , 1000 ) != ESP_OK ) {
219+ vTaskDelay (pdMS_TO_TICKS (50 ));
220+ if (read_fail_cnt ++ >= TEST_I2S_MAX_FAIL_CNT ) {
221+ ESP_LOGE (TAG , "Slave failed to read after %d retries" , (int )TEST_I2S_MAX_FAIL_CNT );
222+ success_flag = false;
223+ goto exit ;
224+ }
188225 }
189- if (i2s_channel_write (i2s_tdm_tx_handle , echo_buffer , buffer_size , & bytes_written , 500 ) != ESP_OK ) {
226+ // When receive valid data, then break the loop and start writing
227+ if (echo_buffer [0 ] || echo_buffer [1 ]) {
190228 break ;
191229 }
192230 }
231+ size_t bytes_written = buffer_size ;
232+ /* Load the data to write */
233+ while (bytes_written ) {
234+ esp_err_t ret = i2s_channel_preload_data (i2s_tdm_tx_handle , echo_buffer , buffer_size , & bytes_written );
235+ printf ("ret %x, bytes_written %d\n" , ret , (int )bytes_written );
236+ }
237+ TEST_ESP_OK (i2s_channel_enable (i2s_tdm_tx_handle ));
238+ vTaskDelay (pdMS_TO_TICKS (100 ));
239+ unity_send_signal ("Slave Data Ready" );
240+ unity_wait_for_signal ("Master Finished" );
241+
242+ TEST_ESP_OK (i2s_channel_disable (i2s_tdm_tx_handle ));
193243
244+ exit :
194245 ESP_LOGI (TAG , "I2S TDM slave receive stop" );
195246 TEST_ESP_OK (i2s_channel_disable (i2s_tdm_rx_handle ));
196- TEST_ESP_OK (i2s_channel_disable (i2s_tdm_tx_handle ));
197247 free (echo_buffer );
198248 TEST_ESP_OK (i2s_del_channel (i2s_tdm_rx_handle ));
199249 TEST_ESP_OK (i2s_del_channel (i2s_tdm_tx_handle ));
200250 ESP_LOGI (TAG , "I2S TDM slave resources freed" );
251+ TEST_ASSERT_TRUE_MESSAGE (success_flag , "Slave failed to read" );
201252}
202253
203254static void test_i2s_tdm_master_48k_32bits_4slots (void )
204255{
205- test_i2s_tdm_master (48000 , I2S_DATA_BIT_WIDTH_32BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
256+ test_i2s_tdm_master (TEST_SAMPLE_RATE , I2S_DATA_BIT_WIDTH_32BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
206257}
207258
208259static void test_i2s_tdm_slave_48k_32bits_4slots (void )
209260{
210- test_i2s_tdm_slave (48000 , I2S_DATA_BIT_WIDTH_32BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
261+ test_i2s_tdm_slave (TEST_SAMPLE_RATE , I2S_DATA_BIT_WIDTH_32BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
211262}
212263
213264TEST_CASE_MULTIPLE_DEVICES ("I2S_TDM_full_duplex_test_in_48k_32bits_4slots" , "[I2S_TDM]" ,
214265 test_i2s_tdm_master_48k_32bits_4slots , test_i2s_tdm_slave_48k_32bits_4slots );
215266
216267static void test_i2s_tdm_master_48k_16bits_4slots (void )
217268{
218- test_i2s_tdm_master (48000 , I2S_DATA_BIT_WIDTH_16BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
269+ test_i2s_tdm_master (TEST_SAMPLE_RATE , I2S_DATA_BIT_WIDTH_16BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
219270}
220271
221272static void test_i2s_tdm_slave_48k_16bits_4slots (void )
222273{
223- test_i2s_tdm_slave (48000 , I2S_DATA_BIT_WIDTH_16BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
274+ test_i2s_tdm_slave (TEST_SAMPLE_RATE , I2S_DATA_BIT_WIDTH_16BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
224275}
225276
226277TEST_CASE_MULTIPLE_DEVICES ("I2S_TDM_full_duplex_test_in_48k_16bits_4slots" , "[I2S_TDM]" ,
227278 test_i2s_tdm_master_48k_16bits_4slots , test_i2s_tdm_slave_48k_16bits_4slots );
228279
229280static void test_i2s_tdm_master_48k_8bits_4slots (void )
230281{
231- test_i2s_tdm_master (48000 , I2S_DATA_BIT_WIDTH_8BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
282+ test_i2s_tdm_master (TEST_SAMPLE_RATE , I2S_DATA_BIT_WIDTH_8BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
232283}
233284
234285static void test_i2s_tdm_slave_48k_8bits_4slots (void )
235286{
236- test_i2s_tdm_slave (48000 , I2S_DATA_BIT_WIDTH_8BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
287+ test_i2s_tdm_slave (TEST_SAMPLE_RATE , I2S_DATA_BIT_WIDTH_8BIT , I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 );
237288}
238289
239290TEST_CASE_MULTIPLE_DEVICES ("I2S_TDM_full_duplex_test_in_48k_8bits_4slots" , "[I2S_TDM]" ,
0 commit comments