1 /*
2 * Copyright (c) 2017 comsuisse AG
3 * Copyright (c) 2021 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/kernel.h>
9 #include <zephyr/ztest.h>
10 #include <zephyr/drivers/i2s.h>
11 #include "i2s_api_test.h"
12
13 /* The test cases here are copied from test_i2s_loopback.c and adapted for use
14 * on devices that cannot independently start and stop the RX and TX streams
15 * and require the use of the I2S_DIR_BOTH value for RX/TX transfers.
16 */
17
18 /** @brief Short I2S transfer.
19 *
20 * - START trigger starts both the transmission and reception.
21 * - Sending / receiving a short sequence of data returns success.
22 * - DRAIN trigger empties the transmit queue and stops both streams.
23 */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_short)24 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_short)
25 {
26 if (!dir_both_supported) {
27 TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
28 ztest_test_skip();
29 return;
30 }
31
32 int ret;
33
34 /* Prefill TX queue */
35 ret = tx_block_write(dev_i2s, 0, 0);
36 zassert_equal(ret, TC_PASS);
37 TC_PRINT("%d->OK\n", 1);
38
39 ret = tx_block_write(dev_i2s, 1, 0);
40 zassert_equal(ret, TC_PASS);
41 TC_PRINT("%d->OK\n", 2);
42
43 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
44 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
45
46 ret = rx_block_read(dev_i2s, 0);
47 zassert_equal(ret, TC_PASS);
48 TC_PRINT("%d<-OK\n", 1);
49
50 ret = tx_block_write(dev_i2s, 2, 0);
51 zassert_equal(ret, TC_PASS);
52 TC_PRINT("%d->OK\n", 3);
53
54 /* All data written, drain TX queue and stop both streams. */
55 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
56 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
57
58 ret = rx_block_read(dev_i2s, 1);
59 zassert_equal(ret, TC_PASS);
60 TC_PRINT("%d<-OK\n", 2);
61
62 ret = rx_block_read(dev_i2s, 2);
63 zassert_equal(ret, TC_PASS);
64 TC_PRINT("%d<-OK\n", 3);
65
66 /* TODO: Verify the interface is in READY state when i2s_state_get
67 * function is available.
68 */
69 }
70
71 #define TEST_I2S_TRANSFER_LONG_REPEAT_COUNT 100
72
73 /** @brief Long I2S transfer.
74 *
75 * - START trigger starts both the transmission and reception.
76 * - Sending / receiving a long sequence of data returns success.
77 * - DRAIN trigger empties the transmit queue and stops both streams.
78 */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_long)79 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_long)
80 {
81 if (!dir_both_supported) {
82 TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
83 ztest_test_skip();
84 return;
85 }
86
87 int ret;
88
89 /* Prefill TX queue */
90 ret = tx_block_write(dev_i2s, 0, 0);
91 zassert_equal(ret, TC_PASS);
92
93 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
94 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
95
96 for (int i = 0; i < TEST_I2S_TRANSFER_LONG_REPEAT_COUNT; i++) {
97 ret = tx_block_write(dev_i2s, 0, 0);
98 zassert_equal(ret, TC_PASS);
99
100 ret = rx_block_read(dev_i2s, 0);
101 zassert_equal(ret, TC_PASS);
102 }
103
104 /* All data written, all but one data block read, flush TX queue
105 * and stop both streams.
106 */
107 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
108 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
109
110 ret = rx_block_read(dev_i2s, 0);
111 zassert_equal(ret, TC_PASS);
112
113 /* TODO: Verify the interface is in READY state when i2s_state_get
114 * function is available.
115 */
116 }
117
118 /** @brief Re-start I2S transfer.
119 *
120 * - STOP trigger stops transfer / reception at the end of the current block,
121 * consecutive START trigger restarts transfer / reception with the next data
122 * block.
123 */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_restart)124 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_restart)
125 {
126 if (!dir_both_supported) {
127 TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
128 ztest_test_skip();
129 return;
130 }
131
132 int ret;
133
134 /* Prefill TX queue */
135 ret = tx_block_write(dev_i2s, 0, 0);
136 zassert_equal(ret, TC_PASS);
137 TC_PRINT("%d->OK\n", 1);
138
139 ret = tx_block_write(dev_i2s, 1, 0);
140 zassert_equal(ret, TC_PASS);
141 TC_PRINT("%d->OK\n", 2);
142
143 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
144 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
145
146 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_STOP);
147 zassert_equal(ret, 0, "RX/TX STOP trigger failed");
148
149 ret = rx_block_read(dev_i2s, 0);
150 zassert_equal(ret, TC_PASS);
151 TC_PRINT("%d<-OK\n", 1);
152
153 TC_PRINT("Stop transmission\n");
154
155 /* Keep interface inactive */
156 k_sleep(K_MSEC(1000));
157
158 TC_PRINT("Start transmission\n");
159
160 /* Prefill TX queue */
161 ret = tx_block_write(dev_i2s, 2, 0);
162 zassert_equal(ret, TC_PASS);
163 TC_PRINT("%d->OK\n", 3);
164
165 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
166 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
167
168 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
169 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
170
171 ret = rx_block_read(dev_i2s, 1);
172 zassert_equal(ret, TC_PASS);
173 TC_PRINT("%d<-OK\n", 2);
174
175 ret = rx_block_read(dev_i2s, 2);
176 zassert_equal(ret, TC_PASS);
177 TC_PRINT("%d<-OK\n", 3);
178 }
179
180 /** @brief RX buffer overrun.
181 *
182 * - In case of RX buffer overrun it is possible to read out RX data blocks
183 * that are stored in the RX queue.
184 * - Reading from an empty RX queue when the RX buffer overrun occurred results
185 * in an error.
186 * - Sending PREPARE trigger after the RX buffer overrun occurred changes
187 * the interface state to READY.
188 */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_rx_overrun)189 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_rx_overrun)
190 {
191 if (!dir_both_supported) {
192 TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
193 ztest_test_skip();
194 return;
195 }
196
197 size_t rx_size;
198 int ret;
199 char rx_buf[BLOCK_SIZE];
200
201 /* Prefill TX queue */
202 ret = tx_block_write(dev_i2s, 0, 0);
203 zassert_equal(ret, TC_PASS);
204
205 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
206 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
207
208 for (int i = 0; i < NUM_RX_BLOCKS; i++) {
209 ret = tx_block_write(dev_i2s, 0, 0);
210 zassert_equal(ret, TC_PASS);
211 }
212
213 /* All data written, flush TX queue and stop the transmission */
214 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
215 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
216
217 /* Wait for transmission to finish */
218 k_sleep(K_MSEC(200));
219
220 /* Read one data block, expect success even if RX queue is already in
221 * the error state.
222 */
223 ret = rx_block_read(dev_i2s, 0);
224 zassert_equal(ret, TC_PASS);
225
226 /* Attempt to read more data blocks than are available in the RX queue */
227 for (int i = 0; i < NUM_RX_BLOCKS; i++) {
228 ret = i2s_buf_read(dev_i2s, rx_buf, &rx_size);
229 if (ret != 0) {
230 break;
231 }
232 }
233 zassert_equal(ret, -EIO, "RX overrun error not detected");
234
235 ret = i2s_trigger(dev_i2s, I2S_DIR_RX, I2S_TRIGGER_PREPARE);
236 zassert_equal(ret, 0, "RX PREPARE trigger failed");
237
238 /* Transmit and receive one more data block */
239 ret = tx_block_write(dev_i2s, 0, 0);
240 zassert_equal(ret, TC_PASS);
241 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
242 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
243 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
244 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
245 ret = rx_block_read(dev_i2s, 0);
246 zassert_equal(ret, TC_PASS);
247
248 k_sleep(K_MSEC(200));
249 }
250
251 /** @brief TX buffer underrun.
252 *
253 * - An attempt to write to the TX queue when TX buffer underrun has occurred
254 * results in an error.
255 * - Sending PREPARE trigger after the TX buffer underrun occurred changes
256 * the interface state to READY.
257 */
ZTEST_USER(i2s_dir_both_loopback,test_i2s_dir_both_transfer_tx_underrun)258 ZTEST_USER(i2s_dir_both_loopback, test_i2s_dir_both_transfer_tx_underrun)
259 {
260 if (!dir_both_supported) {
261 TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
262 ztest_test_skip();
263 return;
264 }
265
266 int ret;
267
268 /* Prefill TX queue */
269 ret = tx_block_write(dev_i2s, 0, 0);
270 zassert_equal(ret, TC_PASS);
271
272 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
273 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
274
275 ret = rx_block_read(dev_i2s, 0);
276 zassert_equal(ret, TC_PASS);
277
278 k_sleep(K_MSEC(200));
279
280 /* Write one more TX data block, expect an error */
281 ret = tx_block_write(dev_i2s, 2, -EIO);
282 zassert_equal(ret, TC_PASS);
283
284 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
285 zassert_equal(ret, 0, "RX/TX PREPARE trigger failed");
286
287 k_sleep(K_MSEC(200));
288
289 /* Transmit and receive two more data blocks */
290 ret = tx_block_write(dev_i2s, 1, 0);
291 zassert_equal(ret, TC_PASS);
292 ret = tx_block_write(dev_i2s, 1, 0);
293 zassert_equal(ret, TC_PASS);
294 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
295 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
296 ret = rx_block_read(dev_i2s, 1);
297 zassert_equal(ret, TC_PASS);
298 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
299 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
300 ret = rx_block_read(dev_i2s, 1);
301 zassert_equal(ret, TC_PASS);
302
303 k_sleep(K_MSEC(200));
304 }
305