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