1 /*
2  * Copyright (c) 2023 Fabian Blatz
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/uart.h>
9 #include <zephyr/drivers/serial/uart_emul.h>
10 #include <zephyr/ztest.h>
11 
12 #define EMUL_UART_NODE	       DT_NODELABEL(euart0)
13 #define EMUL_UART_RX_FIFO_SIZE DT_PROP(EMUL_UART_NODE, rx_fifo_size)
14 #define EMUL_UART_TX_FIFO_SIZE DT_PROP(EMUL_UART_NODE, tx_fifo_size)
15 
16 /*
17  * Leave one byte left in tx to avoid filling it completely which will block the UART
18  * tx ready IRQ event.
19  */
20 #define SAMPLE_DATA_SIZE       MIN(EMUL_UART_RX_FIFO_SIZE, EMUL_UART_TX_FIFO_SIZE) - 1
21 
22 struct uart_emul_fixture {
23 	const struct device *dev;
24 	uint8_t sample_data[SAMPLE_DATA_SIZE];
25 	uint8_t tx_content[SAMPLE_DATA_SIZE];
26 	uint8_t rx_content[SAMPLE_DATA_SIZE];
27 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
28 	struct k_sem tx_done_sem;
29 	struct k_sem rx_done_sem;
30 	size_t tx_remaining;
31 	size_t rx_remaining;
32 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
33 #ifdef CONFIG_UART_ASYNC_API
34 	struct k_event async_events;
35 #endif /* CONFIG_UART_ASYNC_API */
36 };
37 
uart_emul_setup(void)38 static void *uart_emul_setup(void)
39 {
40 	static struct uart_emul_fixture fixture = {.dev = DEVICE_DT_GET(EMUL_UART_NODE)};
41 
42 	for (size_t i = 0; i < SAMPLE_DATA_SIZE; i++) {
43 		fixture.sample_data[i] = i;
44 	}
45 
46 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
47 	k_sem_init(&fixture.tx_done_sem, 0, 1);
48 	k_sem_init(&fixture.rx_done_sem, 0, 1);
49 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
50 
51 #ifdef CONFIG_UART_ASYNC_API
52 	k_event_init(&fixture.async_events);
53 #endif /* CONFIG_UART_ASYNC_API */
54 
55 	zassert_not_null(fixture.dev);
56 	return &fixture;
57 }
58 
uart_emul_before(void * f)59 static void uart_emul_before(void *f)
60 {
61 	struct uart_emul_fixture *fixture = f;
62 
63 	uart_emul_flush_rx_data(fixture->dev);
64 	uart_emul_flush_tx_data(fixture->dev);
65 
66 	uart_err_check(fixture->dev);
67 
68 	memset(fixture->tx_content, 0, sizeof(fixture->tx_content));
69 	memset(fixture->rx_content, 0, sizeof(fixture->rx_content));
70 
71 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
72 	uart_irq_tx_disable(fixture->dev);
73 	uart_irq_rx_disable(fixture->dev);
74 
75 	k_sem_reset(&fixture->tx_done_sem);
76 	k_sem_reset(&fixture->rx_done_sem);
77 
78 	fixture->tx_remaining = SAMPLE_DATA_SIZE;
79 	fixture->rx_remaining = SAMPLE_DATA_SIZE;
80 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
81 
82 #ifdef CONFIG_UART_ASYNC_API
83 	uart_tx_abort(fixture->dev);
84 	uart_rx_disable(fixture->dev);
85 
86 	k_event_set(&fixture->async_events, 0);
87 #endif /* CONFIG_UART_ASYNC_API */
88 }
89 
ZTEST_F(uart_emul,test_polling_out)90 ZTEST_F(uart_emul, test_polling_out)
91 {
92 	uint8_t tx_content[SAMPLE_DATA_SIZE] = {0};
93 	size_t tx_len;
94 
95 	for (size_t i = 0; i < SAMPLE_DATA_SIZE; i++) {
96 		uart_poll_out(fixture->dev, fixture->sample_data[i]);
97 	}
98 
99 	tx_len = uart_emul_get_tx_data(fixture->dev, tx_content, sizeof(tx_content));
100 	zassert_equal(tx_len, SAMPLE_DATA_SIZE, "TX buffer length does not match");
101 	zassert_mem_equal(tx_content, fixture->sample_data, SAMPLE_DATA_SIZE);
102 
103 	/* No more data in TX buffer */
104 	tx_len = uart_emul_get_tx_data(fixture->dev, tx_content, sizeof(tx_content));
105 	zassert_equal(tx_len, 0, "TX buffer should be empty");
106 }
107 
ZTEST_F(uart_emul,test_polling_in)108 ZTEST_F(uart_emul, test_polling_in)
109 {
110 	int rc;
111 
112 	uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE);
113 
114 	for (size_t i = 0; i < SAMPLE_DATA_SIZE; i++) {
115 		rc = uart_poll_in(fixture->dev, &fixture->rx_content[i]);
116 		zassert_equal(rc, 0, "RX buffer should contain data");
117 	}
118 	zassert_mem_equal(fixture->rx_content, fixture->sample_data, SAMPLE_DATA_SIZE);
119 
120 	/* No more data in RX buffer */
121 	rc = uart_poll_in(fixture->dev, &fixture->rx_content[0]);
122 	zassert_equal(rc, -1, "RX buffer should be empty");
123 }
124 
ZTEST_F(uart_emul,test_errors)125 ZTEST_F(uart_emul, test_errors)
126 {
127 	int errors;
128 
129 	uart_emul_set_errors(fixture->dev, (UART_ERROR_PARITY | UART_ERROR_FRAMING));
130 	errors = uart_err_check(fixture->dev);
131 	zassert_equal(errors, (UART_ERROR_PARITY | UART_ERROR_FRAMING), "UART errors do not match");
132 
133 	/* uart_err_check should also clear existing errors */
134 	errors = uart_err_check(fixture->dev);
135 	zassert_equal(errors, 0, "Should be no errors");
136 
137 	/* overflowing rx buffer should produce an overrun error */
138 	uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE);
139 	errors = uart_err_check(fixture->dev);
140 	zassert_equal(errors, 0, "Should be no errors");
141 	uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE);
142 	errors = uart_err_check(fixture->dev);
143 	zassert_equal(errors, UART_ERROR_OVERRUN, "UART errors do not match");
144 }
145 
146 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_emul_isr_handle_tx_ready(struct uart_emul_fixture * fixture)147 static void uart_emul_isr_handle_tx_ready(struct uart_emul_fixture *fixture)
148 {
149 	uint32_t sample_data_it;
150 	int ret;
151 
152 	if (fixture->tx_remaining) {
153 		sample_data_it = sizeof(fixture->sample_data) - fixture->tx_remaining;
154 		ret = uart_fifo_fill(fixture->dev, &fixture->sample_data[sample_data_it],
155 				     fixture->tx_remaining);
156 		fixture->tx_remaining -= (size_t)ret;
157 	}
158 
159 	if (fixture->tx_remaining == 0) {
160 		uart_irq_tx_disable(fixture->dev);
161 		k_sem_give(&fixture->tx_done_sem);
162 	}
163 }
164 
uart_emul_isr_handle_rx_ready(struct uart_emul_fixture * fixture)165 static void uart_emul_isr_handle_rx_ready(struct uart_emul_fixture *fixture)
166 {
167 	uint32_t rx_content_it;
168 	int ret;
169 
170 	if (fixture->rx_remaining) {
171 		rx_content_it = sizeof(fixture->rx_content) - fixture->rx_remaining;
172 		ret = uart_fifo_read(fixture->dev, &fixture->rx_content[rx_content_it],
173 				     fixture->rx_remaining);
174 		fixture->rx_remaining -= (size_t)ret;
175 	}
176 
177 	if (fixture->rx_remaining == 0) {
178 		k_sem_give(&fixture->rx_done_sem);
179 	}
180 }
181 
uart_emul_isr(const struct device * dev,void * user_data)182 static void uart_emul_isr(const struct device *dev, void *user_data)
183 {
184 	struct uart_emul_fixture *fixture = user_data;
185 
186 	while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
187 		if (uart_irq_tx_ready(fixture->dev)) {
188 			uart_emul_isr_handle_tx_ready(fixture);
189 		}
190 		if (uart_irq_rx_ready(fixture->dev)) {
191 			uart_emul_isr_handle_rx_ready(fixture);
192 		}
193 	}
194 }
195 
ZTEST_F(uart_emul,test_irq_tx)196 ZTEST_F(uart_emul, test_irq_tx)
197 {
198 	size_t tx_len;
199 
200 	uart_irq_callback_user_data_set(fixture->dev, uart_emul_isr, fixture);
201 	/* enabling the tx irq will call the callback, if set */
202 	uart_irq_tx_enable(fixture->dev);
203 	/* Wait for all data to be received in full */
204 	zassert_equal(k_sem_take(&fixture->tx_done_sem, K_SECONDS(1)), 0,
205 		      "Timeout waiting for UART ISR");
206 
207 	tx_len = uart_emul_get_tx_data(fixture->dev, fixture->tx_content, SAMPLE_DATA_SIZE);
208 	zassert_equal(tx_len, SAMPLE_DATA_SIZE, "TX buffer length does not match");
209 	zassert_mem_equal(fixture->tx_content, fixture->sample_data, SAMPLE_DATA_SIZE);
210 
211 	/* No more data in TX buffer */
212 	tx_len = uart_emul_get_tx_data(fixture->dev, fixture->tx_content,
213 				       sizeof(fixture->tx_content));
214 	zassert_equal(tx_len, 0, "TX buffer should be empty");
215 }
216 
ZTEST_F(uart_emul,test_irq_rx)217 ZTEST_F(uart_emul, test_irq_rx)
218 {
219 	int rc;
220 
221 	uart_irq_callback_user_data_set(fixture->dev, uart_emul_isr, fixture);
222 	uart_irq_rx_enable(fixture->dev);
223 
224 	/* putting rx data will call the irq callback, if enabled */
225 	uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE);
226 
227 	/* Wait for all data to be received in full */
228 	zassert_equal(k_sem_take(&fixture->rx_done_sem, K_SECONDS(1)), 0,
229 		      "Timeout waiting for UART ISR");
230 
231 	zassert_mem_equal(fixture->rx_content, fixture->sample_data, SAMPLE_DATA_SIZE);
232 
233 	/* No more data in RX buffer */
234 	rc = uart_poll_in(fixture->dev, &fixture->rx_content[0]);
235 	zassert_equal(rc, -1, "RX buffer should be empty");
236 
237 	uart_irq_rx_disable(fixture->dev);
238 }
239 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
240 
241 #ifdef CONFIG_UART_ASYNC_API
uart_emul_callback(const struct device * dev,struct uart_event * evt,void * user_data)242 static void uart_emul_callback(const struct device *dev, struct uart_event *evt, void *user_data)
243 {
244 	struct uart_emul_fixture *fixture = user_data;
245 
246 	zassert_not_null(evt);
247 	k_event_post(&fixture->async_events, ((uint32_t)1 << evt->type));
248 
249 	switch (evt->type) {
250 	case UART_TX_DONE:
251 		zassert_equal(evt->data.tx.len, sizeof(fixture->sample_data));
252 		zassert_equal(evt->data.tx.buf, fixture->sample_data);
253 		break;
254 	case UART_RX_RDY:
255 		zassert_equal(evt->data.rx.len, sizeof(fixture->sample_data));
256 		zassert_mem_equal(&evt->data.rx.buf[evt->data.rx.offset], fixture->sample_data,
257 				  sizeof(fixture->sample_data));
258 		break;
259 	case UART_RX_BUF_RELEASED:
260 		zassert_equal(evt->data.rx_buf.buf, fixture->rx_content);
261 		break;
262 	case UART_TX_ABORTED:
263 	case UART_RX_BUF_REQUEST:
264 	case UART_RX_DISABLED:
265 	case UART_RX_STOPPED:
266 		break;
267 	}
268 }
269 
uart_emul_wait_for_event(struct uart_emul_fixture * fixture,enum uart_event_type event)270 bool uart_emul_wait_for_event(struct uart_emul_fixture *fixture, enum uart_event_type event)
271 {
272 	return k_event_wait(&fixture->async_events, ((uint32_t)1 << event), false, K_SECONDS(1)) !=
273 	       0;
274 }
275 
ZTEST_F(uart_emul,test_async_tx)276 ZTEST_F(uart_emul, test_async_tx)
277 {
278 	size_t tx_len;
279 
280 	uart_emul_set_release_buffer_on_timeout(fixture->dev, true);
281 
282 	zassert_equal(uart_callback_set(fixture->dev, uart_emul_callback, fixture), 0);
283 	zassert_equal(uart_tx(fixture->dev, fixture->sample_data, sizeof(fixture->sample_data),
284 			      SYS_FOREVER_US),
285 		      0);
286 
287 	/* Wait for all data to be received in full */
288 	zexpect_true(uart_emul_wait_for_event(fixture, UART_TX_DONE),
289 		     "UART_TX_DONE event expected");
290 
291 	tx_len = uart_emul_get_tx_data(fixture->dev, fixture->tx_content, SAMPLE_DATA_SIZE);
292 	zassert_equal(tx_len, SAMPLE_DATA_SIZE, "TX buffer length does not match");
293 	zassert_mem_equal(fixture->tx_content, fixture->sample_data, SAMPLE_DATA_SIZE);
294 
295 	/* No more data in TX buffer */
296 	tx_len = uart_emul_get_tx_data(fixture->dev, fixture->tx_content,
297 				       sizeof(fixture->tx_content));
298 	zassert_equal(tx_len, 0, "TX buffer should be empty");
299 }
300 
ZTEST_F(uart_emul,test_async_rx)301 ZTEST_F(uart_emul, test_async_rx)
302 {
303 	zassert_equal(uart_callback_set(fixture->dev, uart_emul_callback, fixture), 0);
304 	zassert_equal(uart_rx_enable(fixture->dev, fixture->rx_content, sizeof(fixture->rx_content),
305 				     SYS_FOREVER_US),
306 		      0);
307 	uart_emul_put_rx_data(fixture->dev, fixture->sample_data, SAMPLE_DATA_SIZE);
308 	zexpect_true(uart_emul_wait_for_event(fixture, UART_RX_BUF_REQUEST),
309 		     "UART_RX_BUF_REQUEST event expected");
310 	zexpect_true(uart_emul_wait_for_event(fixture, UART_RX_RDY), "UART_RX_RDY event expected");
311 	zassert_mem_equal(fixture->rx_content, fixture->sample_data, SAMPLE_DATA_SIZE);
312 	zexpect_true(uart_emul_wait_for_event(fixture, UART_RX_BUF_RELEASED),
313 		     "UART_RX_BUF_RELEASED event expected");
314 	zexpect_true(uart_emul_wait_for_event(fixture, UART_RX_DISABLED),
315 		     "UART_RX_DISABLED event expected");
316 }
317 
uart_emul_callback_rx_timeout(const struct device * dev,struct uart_event * evt,void * user_data)318 static void uart_emul_callback_rx_timeout(const struct device *dev, struct uart_event *evt,
319 					  void *user_data)
320 {
321 	struct uart_emul_fixture *fixture = user_data;
322 
323 	zassert_not_null(evt);
324 	k_event_post(&fixture->async_events, ((uint32_t)1 << evt->type));
325 }
326 
ZTEST_F(uart_emul,test_async_rx_buffer_release)327 ZTEST_F(uart_emul, test_async_rx_buffer_release)
328 {
329 	zassert_equal(uart_callback_set(fixture->dev, uart_emul_callback_rx_timeout, fixture), 0);
330 
331 	uint8_t rx_buffer[16];
332 	uint8_t rx_data[5];
333 
334 	memset(rx_data, 1, sizeof(rx_data));
335 
336 	zassert_equal(
337 		uart_rx_enable(fixture->dev, rx_buffer, sizeof(rx_buffer), 100 * USEC_PER_MSEC), 0);
338 
339 	uart_emul_set_release_buffer_on_timeout(fixture->dev, false);
340 	uart_emul_put_rx_data(fixture->dev, rx_data, sizeof(rx_data));
341 	zexpect_false(uart_emul_wait_for_event(fixture, UART_RX_BUF_RELEASED),
342 		      "UART_RX_BUF_RELEASED event not expected");
343 	zexpect_true(uart_emul_wait_for_event(fixture, UART_RX_RDY));
344 
345 	k_event_set(&fixture->async_events, 0);
346 
347 	uart_emul_set_release_buffer_on_timeout(fixture->dev, true);
348 	uart_emul_put_rx_data(fixture->dev, rx_data, sizeof(rx_data));
349 	zexpect_true(uart_emul_wait_for_event(fixture, UART_RX_BUF_RELEASED),
350 		     "UART_RX_BUF_RELEASED event expected");
351 	zexpect_true(uart_emul_wait_for_event(fixture, UART_RX_RDY));
352 	zexpect_true(uart_emul_wait_for_event(fixture, UART_RX_DISABLED),
353 		     "UART_RX_DISABLED event expected");
354 }
355 #endif /* CONFIG_UART_ASYNC_API */
356 
357 ZTEST_SUITE(uart_emul, NULL, uart_emul_setup, uart_emul_before, NULL, NULL);
358