1 /*
2  * Copyright 2024 Basalte bv
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  */
7 
8 #define DT_DRV_COMPAT uart_dummy
9 
10 #include <zephyr/device.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/drivers/uart.h>
13 #include <zephyr/drivers/uart_emul.h>
14 #include <zephyr/drivers/serial/uart_emul.h>
15 #include <zephyr/drivers/emul_stub_device.h>
16 #include <zephyr/ztest.h>
17 
18 #define UART_DUMMY_NODE        DT_NODELABEL(dummy)
19 #define EMUL_UART_NODE         DT_PARENT(UART_DUMMY_NODE)
20 #define EMUL_UART_RX_FIFO_SIZE DT_PROP(EMUL_UART_NODE, rx_fifo_size)
21 #define EMUL_UART_TX_FIFO_SIZE DT_PROP(EMUL_UART_NODE, tx_fifo_size)
22 
23 /*
24  * Leave one byte left in tx to avoid filling it completely which will block the UART
25  * tx ready IRQ event.
26  */
27 #define SAMPLE_DATA_SIZE MIN(EMUL_UART_RX_FIFO_SIZE, EMUL_UART_TX_FIFO_SIZE) - 1
28 
29 struct uart_emul_device_fixture {
30 	const struct device *dev;
31 	uint8_t sample_data[SAMPLE_DATA_SIZE];
32 	uint8_t rx_content[SAMPLE_DATA_SIZE];
33 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
34 	struct k_sem tx_done_sem;
35 	struct k_sem rx_done_sem;
36 	size_t tx_remaining;
37 	size_t rx_remaining;
38 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
39 #ifdef CONFIG_UART_ASYNC_API
40 	struct k_event async_events;
41 #endif /* CONFIG_UART_ASYNC_API */
42 };
43 
uart_emul_device_setup(void)44 static void *uart_emul_device_setup(void)
45 {
46 	static struct uart_emul_device_fixture fixture = {.dev = DEVICE_DT_GET(EMUL_UART_NODE)};
47 
48 	for (size_t i = 0; i < SAMPLE_DATA_SIZE; i++) {
49 		fixture.sample_data[i] = i;
50 	}
51 
52 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
53 	k_sem_init(&fixture.tx_done_sem, 0, 1);
54 	k_sem_init(&fixture.rx_done_sem, 0, 1);
55 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
56 
57 #ifdef CONFIG_UART_ASYNC_API
58 	k_event_init(&fixture.async_events);
59 #endif /* CONFIG_UART_ASYNC_API */
60 
61 	zassert_not_null(fixture.dev);
62 	return &fixture;
63 }
64 
uart_emul_device_before(void * f)65 static void uart_emul_device_before(void *f)
66 {
67 	struct uart_emul_device_fixture *fixture = f;
68 
69 	uart_emul_flush_rx_data(fixture->dev);
70 	uart_emul_flush_tx_data(fixture->dev);
71 
72 	uart_err_check(fixture->dev);
73 
74 	memset(fixture->rx_content, 0, sizeof(fixture->rx_content));
75 
76 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
77 	uart_irq_tx_disable(fixture->dev);
78 	uart_irq_rx_disable(fixture->dev);
79 
80 	k_sem_reset(&fixture->tx_done_sem);
81 	k_sem_reset(&fixture->rx_done_sem);
82 
83 	fixture->tx_remaining = SAMPLE_DATA_SIZE;
84 	fixture->rx_remaining = SAMPLE_DATA_SIZE;
85 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
86 
87 #ifdef CONFIG_UART_ASYNC_API
88 	uart_tx_abort(fixture->dev);
89 	uart_rx_disable(fixture->dev);
90 
91 	k_event_set(&fixture->async_events, 0);
92 #endif /* CONFIG_UART_ASYNC_API */
93 }
94 
ZTEST_F(uart_emul_device,test_polling)95 ZTEST_F(uart_emul_device, test_polling)
96 {
97 	uint32_t len;
98 	uint8_t byte;
99 	int ret;
100 
101 	for (size_t i = 0; i < SAMPLE_DATA_SIZE; ++i) {
102 		uart_poll_out(fixture->dev, i);
103 	}
104 
105 	len = uart_emul_get_tx_data(fixture->dev, NULL, UINT32_MAX);
106 	zassert_equal(len, 0, "TX buffer should be empty");
107 
108 	for (size_t i = 0; i < SAMPLE_DATA_SIZE; ++i) {
109 		ret = uart_poll_in(fixture->dev, &byte);
110 		zassert_equal(ret, 0);
111 		zassert_equal(byte, i);
112 	}
113 
114 	ret = uart_poll_in(fixture->dev, &byte);
115 	zassert_equal(ret, -1, "RX buffer should be empty");
116 }
117 
118 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_emul_device_isr_handle_tx_ready(struct uart_emul_device_fixture * fixture)119 static void uart_emul_device_isr_handle_tx_ready(struct uart_emul_device_fixture *fixture)
120 {
121 	uint32_t sample_data_it;
122 	int ret;
123 
124 	if (fixture->tx_remaining) {
125 		sample_data_it = sizeof(fixture->sample_data) - fixture->tx_remaining;
126 		ret = uart_fifo_fill(fixture->dev, &fixture->sample_data[sample_data_it],
127 				     fixture->tx_remaining);
128 		fixture->tx_remaining -= (size_t)ret;
129 	}
130 
131 	if (fixture->tx_remaining == 0) {
132 		uart_irq_tx_disable(fixture->dev);
133 		k_sem_give(&fixture->tx_done_sem);
134 	}
135 }
136 
uart_emul_device_isr_handle_rx_ready(struct uart_emul_device_fixture * fixture)137 static void uart_emul_device_isr_handle_rx_ready(struct uart_emul_device_fixture *fixture)
138 {
139 	uint32_t rx_content_it;
140 	int ret;
141 
142 	if (fixture->rx_remaining) {
143 		rx_content_it = sizeof(fixture->rx_content) - fixture->rx_remaining;
144 		ret = uart_fifo_read(fixture->dev, &fixture->rx_content[rx_content_it],
145 				     fixture->rx_remaining);
146 		fixture->rx_remaining -= (size_t)ret;
147 	}
148 
149 	if (fixture->rx_remaining == 0) {
150 		k_sem_give(&fixture->rx_done_sem);
151 	}
152 }
153 
uart_emul_device_isr(const struct device * dev,void * user_data)154 static void uart_emul_device_isr(const struct device *dev, void *user_data)
155 {
156 	struct uart_emul_device_fixture *fixture = user_data;
157 
158 	while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
159 		if (uart_irq_tx_ready(fixture->dev)) {
160 			uart_emul_device_isr_handle_tx_ready(fixture);
161 		}
162 		if (uart_irq_rx_ready(fixture->dev)) {
163 			uart_emul_device_isr_handle_rx_ready(fixture);
164 		}
165 	}
166 }
167 
ZTEST_F(uart_emul_device,test_irq)168 ZTEST_F(uart_emul_device, test_irq)
169 {
170 	size_t tx_len;
171 	int rc;
172 
173 	uart_irq_callback_user_data_set(fixture->dev, uart_emul_device_isr, fixture);
174 	/* enabling the rx irq will call the callback, if set */
175 	uart_irq_rx_enable(fixture->dev);
176 	/* enabling the tx irq will call the callback, if set */
177 	uart_irq_tx_enable(fixture->dev);
178 
179 	/* Wait for all data to be received in full */
180 	zassert_ok(k_sem_take(&fixture->tx_done_sem, K_SECONDS(1)),
181 		   "Timeout waiting for UART TX ISR");
182 
183 	tx_len = uart_emul_get_tx_data(fixture->dev, NULL, SAMPLE_DATA_SIZE);
184 	zassert_equal(tx_len, 0, "TX buffer should be empty");
185 
186 	zassert_ok(k_sem_take(&fixture->rx_done_sem, K_SECONDS(1)),
187 		   "Timeout waiting for UART RX ISR");
188 	zassert_mem_equal(fixture->rx_content, fixture->sample_data, SAMPLE_DATA_SIZE);
189 
190 	/* No more data in RX buffer */
191 	rc = uart_poll_in(fixture->dev, &fixture->rx_content[0]);
192 	zassert_equal(rc, -1, "RX buffer should be empty");
193 
194 	uart_irq_rx_disable(fixture->dev);
195 }
196 #endif
197 
198 #ifdef CONFIG_UART_ASYNC_API
uart_emul_callback(const struct device * dev,struct uart_event * evt,void * user_data)199 static void uart_emul_callback(const struct device *dev, struct uart_event *evt, void *user_data)
200 {
201 	struct uart_emul_device_fixture *fixture = user_data;
202 
203 	zassert_not_null(evt);
204 	k_event_post(&fixture->async_events, ((uint32_t)1 << evt->type));
205 
206 	switch (evt->type) {
207 	case UART_TX_DONE:
208 		zassert_equal(evt->data.tx.len, sizeof(fixture->sample_data));
209 		zassert_equal(evt->data.tx.buf, fixture->sample_data);
210 		break;
211 	case UART_RX_RDY:
212 		zassert_equal(evt->data.rx.len, sizeof(fixture->sample_data));
213 		zassert_mem_equal(&evt->data.rx.buf[evt->data.rx.offset], fixture->sample_data,
214 				  sizeof(fixture->sample_data));
215 		break;
216 	case UART_RX_BUF_RELEASED:
217 		zassert_equal(evt->data.rx_buf.buf, fixture->rx_content);
218 		break;
219 	case UART_TX_ABORTED:
220 	case UART_RX_BUF_REQUEST:
221 	case UART_RX_DISABLED:
222 	case UART_RX_STOPPED:
223 		break;
224 	}
225 }
226 
uart_emul_device_wait_for_event(struct uart_emul_device_fixture * fixture,enum uart_event_type event)227 static bool uart_emul_device_wait_for_event(struct uart_emul_device_fixture *fixture,
228 					    enum uart_event_type event)
229 {
230 	return k_event_wait(&fixture->async_events, ((uint32_t)1 << event), false, K_SECONDS(1)) !=
231 	       0;
232 }
233 
ZTEST_F(uart_emul_device,test_async)234 ZTEST_F(uart_emul_device, test_async)
235 {
236 	size_t tx_len;
237 
238 	uart_emul_set_release_buffer_on_timeout(fixture->dev, true);
239 
240 	zassert_ok(uart_callback_set(fixture->dev, uart_emul_callback, fixture));
241 	zassert_ok(uart_tx(fixture->dev, fixture->sample_data, sizeof(fixture->sample_data),
242 			   SYS_FOREVER_US));
243 	zassert_ok(uart_rx_enable(fixture->dev, fixture->rx_content, sizeof(fixture->rx_content),
244 				  SYS_FOREVER_US));
245 
246 	/* Wait for all data to be received in full */
247 	zexpect_true(uart_emul_device_wait_for_event(fixture, UART_TX_DONE),
248 		     "UART_TX_DONE event expected");
249 
250 	tx_len = uart_emul_get_tx_data(fixture->dev, NULL, SAMPLE_DATA_SIZE);
251 	zassert_equal(tx_len, 0, "TX buffer should be empty");
252 
253 	zexpect_true(uart_emul_device_wait_for_event(fixture, UART_RX_BUF_REQUEST),
254 		     "UART_RX_BUF_REQUEST event expected");
255 	zexpect_true(uart_emul_device_wait_for_event(fixture, UART_RX_RDY),
256 		     "UART_RX_RDY event expected");
257 	zassert_mem_equal(fixture->rx_content, fixture->sample_data, SAMPLE_DATA_SIZE);
258 	zexpect_true(uart_emul_device_wait_for_event(fixture, UART_RX_BUF_RELEASED),
259 		     "UART_RX_BUF_RELEASED event expected");
260 	zexpect_true(uart_emul_device_wait_for_event(fixture, UART_RX_DISABLED),
261 		     "UART_RX_DISABLED event expected");
262 }
263 #endif /* CONFIG_UART_ASYNC_API */
264 
265 ZTEST_SUITE(uart_emul_device, NULL, uart_emul_device_setup, uart_emul_device_before, NULL, NULL);
266 
267 /* Driver details */
268 
269 /* Our dummy device echoes all data received */
uart_dummy_emul_tx_ready(const struct device * dev,size_t size,const struct emul * target)270 static void uart_dummy_emul_tx_ready(const struct device *dev, size_t size,
271 				     const struct emul *target)
272 {
273 	uint32_t ret;
274 	uint8_t byte;
275 
276 	zassert_equal(target->bus_type, EMUL_BUS_TYPE_UART, "UART bus required");
277 
278 	for (size_t i = 0; i < size; ++i) {
279 		ret = uart_emul_get_tx_data(dev, &byte, 1);
280 		zassert_equal(ret, 1);
281 
282 		ret = uart_emul_put_rx_data(dev, &byte, 1);
283 		zassert_equal(ret, 1);
284 	}
285 }
286 
287 static const struct uart_emul_device_api dummy_api = {
288 	.tx_data_ready = uart_dummy_emul_tx_ready,
289 };
290 
uart_dummy_emul_init(const struct emul * target,const struct device * parent)291 static int uart_dummy_emul_init(const struct emul *target, const struct device *parent)
292 {
293 	ARG_UNUSED(target);
294 	ARG_UNUSED(parent);
295 
296 	return 0;
297 }
298 
299 #define UART_DUMMY_DEFINE(inst)                                                                    \
300 	EMUL_DT_INST_DEFINE(inst, uart_dummy_emul_init, NULL, NULL, &dummy_api, NULL)
301 
302 /* Define both device and emulated driver */
303 DT_INST_FOREACH_STATUS_OKAY(EMUL_STUB_DEVICE)
304 DT_INST_FOREACH_STATUS_OKAY(UART_DUMMY_DEFINE)
305