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_states.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 #define TEST_I2S_STATE_RUNNING_NEG_REPEAT_COUNT 5
19
20 /** @brief Verify all failure cases in RUNNING state.
21 *
22 * - Sending START, PREPARE trigger in RUNNING state returns failure.
23 */
ZTEST_USER(i2s_dir_both_states,test_i2s_dir_both_state_running_neg)24 ZTEST_USER(i2s_dir_both_states, test_i2s_dir_both_state_running_neg)
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
38 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
39 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
40
41 for (int i = 0; i < TEST_I2S_STATE_RUNNING_NEG_REPEAT_COUNT; i++) {
42 ret = tx_block_write(dev_i2s, 0, 0);
43 zassert_equal(ret, TC_PASS);
44
45 ret = rx_block_read(dev_i2s, 0);
46 zassert_equal(ret, TC_PASS);
47
48 /* Send invalid triggers, expect failure */
49 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
50 zassert_equal(ret, -EIO);
51 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
52 zassert_equal(ret, -EIO);
53 }
54
55 /* All data written, drain TX queue and stop both streams. */
56 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
57 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
58
59 ret = rx_block_read(dev_i2s, 0);
60 zassert_equal(ret, TC_PASS);
61 }
62
63 /** @brief Verify all failure cases in STOPPING state.
64 *
65 * - Sending START, STOP, DRAIN, PREPARE trigger in STOPPING state returns
66 * failure.
67 */
ZTEST_USER(i2s_dir_both_states,test_i2s_dir_both_state_stopping_neg)68 ZTEST_USER(i2s_dir_both_states, test_i2s_dir_both_state_stopping_neg)
69 {
70 if (!dir_both_supported) {
71 TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
72 ztest_test_skip();
73 return;
74 }
75
76 int ret;
77
78 /* Prefill TX queue */
79 ret = tx_block_write(dev_i2s, 0, 0);
80 zassert_equal(ret, TC_PASS);
81
82 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
83 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
84
85 ret = tx_block_write(dev_i2s, 0, 0);
86 zassert_equal(ret, TC_PASS);
87
88 ret = rx_block_read(dev_i2s, 0);
89 zassert_equal(ret, TC_PASS);
90
91 /* All data written, all but one data block read, flush TX queue and
92 * stop both streams.
93 */
94 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
95 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
96
97 /* Send invalid triggers, expect failure */
98 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
99 zassert_equal(ret, -EIO);
100 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_STOP);
101 zassert_equal(ret, -EIO);
102 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
103 zassert_equal(ret, -EIO);
104 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
105 zassert_equal(ret, -EIO);
106
107 ret = rx_block_read(dev_i2s, 0);
108 zassert_equal(ret, TC_PASS);
109
110 /* This is incase the RX channel is stuck in STOPPING state.
111 * Clear out the state before running the next test.
112 */
113 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DROP);
114 zassert_equal(ret, 0, "RX/TX DROP trigger failed");
115 }
116
117 /** @brief Verify all failure cases in ERROR state.
118 *
119 * - Sending START, STOP, DRAIN trigger in ERROR state returns failure.
120 */
ZTEST_USER(i2s_dir_both_states,test_i2s_dir_both_state_error_neg)121 ZTEST_USER(i2s_dir_both_states, test_i2s_dir_both_state_error_neg)
122 {
123 if (!dir_both_supported) {
124 TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
125 ztest_test_skip();
126 return;
127 }
128
129 size_t rx_size;
130 int ret;
131 char rx_buf[BLOCK_SIZE];
132
133 /* Prefill TX queue */
134 ret = tx_block_write(dev_i2s, 0, 0);
135 zassert_equal(ret, TC_PASS);
136
137 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
138 zassert_equal(ret, 0, "RX/TX START trigger failed\n");
139
140 for (int i = 0; i < NUM_RX_BLOCKS; i++) {
141 ret = tx_block_write(dev_i2s, 0, 0);
142 zassert_equal(ret, TC_PASS);
143 }
144
145 /* Wait for transmission to finish */
146 k_sleep(K_MSEC(200));
147
148 /* Read one data block, expect success even if RX queue is already in
149 * the error state.
150 */
151 ret = rx_block_read(dev_i2s, 0);
152 zassert_equal(ret, TC_PASS);
153
154 /* Attempt to read more data blocks than are available in the RX queue */
155 for (int i = 0; i < NUM_RX_BLOCKS; i++) {
156 ret = i2s_buf_read(dev_i2s, rx_buf, &rx_size);
157 if (ret != 0) {
158 break;
159 }
160 }
161 zassert_equal(ret, -EIO, "RX overrun error not detected");
162
163 /* Write one more TX data block, expect an error */
164 ret = tx_block_write(dev_i2s, 2, -EIO);
165 zassert_equal(ret, TC_PASS);
166
167 /* Send invalid triggers, expect failure */
168 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
169 zassert_equal(ret, -EIO);
170 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_STOP);
171 zassert_equal(ret, -EIO);
172 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
173 zassert_equal(ret, -EIO);
174
175 /* Recover from ERROR state */
176 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
177 zassert_equal(ret, 0, "RX/TX PREPARE trigger failed");
178
179 /* Transmit and receive one more data block */
180 ret = tx_block_write(dev_i2s, 0, 0);
181 zassert_equal(ret, TC_PASS);
182 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START);
183 zassert_equal(ret, 0, "RX/TX START trigger failed");
184 ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
185 zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
186 ret = rx_block_read(dev_i2s, 0);
187 zassert_equal(ret, TC_PASS);
188
189 k_sleep(K_MSEC(200));
190 }
191