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