1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @addtogroup t_driver_uart
9  * @{
10  * @defgroup t_uart_elementary test_uart_elementary
11  * @}
12  */
13 
14 #include <zephyr/drivers/uart.h>
15 #include <zephyr/pm/device_runtime.h>
16 #include <zephyr/ztest.h>
17 
18 #if DT_NODE_EXISTS(DT_NODELABEL(dut))
19 #define UART_NODE DT_NODELABEL(dut)
20 #else
21 #define UART_NODE DT_CHOSEN(zephyr_console)
22 #endif
23 
24 #if DT_NODE_EXISTS(DT_NODELABEL(dut_aux))
25 #define UART_NODE_AUX DT_NODELABEL(dut_aux)
26 #else
27 #define UART_NODE_AUX DT_CHOSEN(zephyr_console)
28 #endif
29 
30 #define SLEEP_TIME_US 1000
31 #define TEST_BUFFER_LEN 10
32 
33 #define UART_BAUDRATE DT_PROP_OR(UART_NODE, current_speed, 115200)
34 
35 static const struct device *const uart_dev = DEVICE_DT_GET(UART_NODE);
36 
37 const uint8_t test_pattern[TEST_BUFFER_LEN] = { 0x11, 0x12, 0x13, 0x14, 0x15,
38 						0x16, 0x17, 0x18, 0x19, 0x20 };
39 static uint8_t test_buffer[TEST_BUFFER_LEN];
40 static volatile uint8_t uart_error_counter;
41 
42 #if defined(CONFIG_DUAL_UART_TEST)
43 static const struct device *const uart_dev_aux = DEVICE_DT_GET(UART_NODE_AUX);
44 static uint8_t test_buffer_aux[TEST_BUFFER_LEN];
45 static volatile uint8_t aux_uart_error;
46 static volatile uint8_t aux_uart_error_counter;
47 #endif
48 
49 /*
50  * ISR for UART TX action
51  */
uart_tx_interrupt_service(const struct device * dev,int * tx_byte_offset)52 static void uart_tx_interrupt_service(const struct device *dev, int *tx_byte_offset)
53 {
54 	uint8_t bytes_sent = 0;
55 	uint8_t *tx_data_pointer = (uint8_t *)(test_pattern + *tx_byte_offset);
56 
57 	if (*tx_byte_offset < TEST_BUFFER_LEN) {
58 		bytes_sent = uart_fifo_fill(dev, tx_data_pointer, 1);
59 		*tx_byte_offset += bytes_sent;
60 	} else {
61 		*tx_byte_offset = 0;
62 		uart_irq_tx_disable(dev);
63 	}
64 }
65 
66 /*
67  * ISR for UART RX action
68  */
uart_rx_interrupt_service(const struct device * dev,uint8_t * receive_buffer_pointer,int * rx_byte_offset)69 static void uart_rx_interrupt_service(const struct device *dev, uint8_t *receive_buffer_pointer,
70 				      int *rx_byte_offset)
71 {
72 	int rx_data_length = 0;
73 
74 	do {
75 		rx_data_length = uart_fifo_read(dev, receive_buffer_pointer + *rx_byte_offset,
76 						TEST_BUFFER_LEN);
77 		*rx_byte_offset += rx_data_length;
78 	} while (rx_data_length);
79 }
80 
81 /*
82  * Callback function for MAIN UART interrupt based transmission test
83  */
interrupt_driven_uart_callback_main_uart(const struct device * dev,void * user_data)84 static void interrupt_driven_uart_callback_main_uart(const struct device *dev, void *user_data)
85 {
86 	int err;
87 	static int tx_byte_offset;
88 	static int rx_byte_offset;
89 
90 	uart_irq_update(dev);
91 	err = uart_err_check(dev);
92 	if (err != 0) {
93 		uart_error_counter++;
94 	}
95 	while (uart_irq_is_pending(dev)) {
96 		if (uart_irq_rx_ready(dev)) {
97 			uart_rx_interrupt_service(dev, (uint8_t *)user_data, &rx_byte_offset);
98 		}
99 		if (uart_irq_tx_ready(dev)) {
100 			uart_tx_interrupt_service(dev, &tx_byte_offset);
101 		}
102 	}
103 }
104 
105 #if defined(CONFIG_DUAL_UART_TEST)
106 /*
107  * Callback function for AUX UART interrupt based transmission test
108  */
interrupt_driven_uart_callback_aux_uart(const struct device * dev,void * user_data)109 static void interrupt_driven_uart_callback_aux_uart(const struct device *dev, void *user_data)
110 {
111 	int err;
112 	static int tx_byte_offset_aux;
113 	static int rx_byte_offset_aux;
114 
115 	uart_irq_update(dev);
116 	err = uart_err_check(dev);
117 	if (err != 0) {
118 		aux_uart_error_counter++;
119 	}
120 	while (uart_irq_is_pending(dev)) {
121 		if (uart_irq_rx_ready(dev)) {
122 			uart_rx_interrupt_service(dev, (uint8_t *)user_data, &rx_byte_offset_aux);
123 		}
124 		if (uart_irq_tx_ready(dev)) {
125 			uart_tx_interrupt_service(dev, &tx_byte_offset_aux);
126 		}
127 	}
128 }
129 #endif /* CONFIG_DUAL_UART_TEST */
130 
131 /*
132  * Test UART proper configuration call
133  */
ZTEST(uart_elementary,test_uart_proper_configuration)134 ZTEST(uart_elementary, test_uart_proper_configuration)
135 {
136 	Z_TEST_SKIP_IFDEF(CONFIG_DUAL_UART_TEST);
137 
138 	int err;
139 	struct uart_config test_expected_uart_config;
140 	struct uart_config test_uart_config = { .baudrate = UART_BAUDRATE,
141 						.parity = UART_CFG_PARITY_NONE,
142 						.stop_bits = UART_CFG_STOP_BITS_1,
143 						.data_bits = UART_CFG_DATA_BITS_8,
144 						.flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS };
145 
146 	err = uart_configure(uart_dev, &test_uart_config);
147 	zassert_equal(err, 0, "'uart_configure' api call - unexpected error: %d", err);
148 
149 	err = uart_config_get(uart_dev, &test_expected_uart_config);
150 	zassert_equal(err, 0, "'uart_config_get' api call - unexpected error raised : %d", err);
151 
152 	zassert_equal(test_uart_config.baudrate, test_expected_uart_config.baudrate,
153 		      "Set and actual UART config baudrate mismatch: %d != %d",
154 		      test_uart_config.baudrate, test_expected_uart_config.baudrate);
155 
156 	zassert_equal(test_uart_config.parity, test_expected_uart_config.parity,
157 		      "Set and actual UART config parity mismatch: %d != %d",
158 		      test_uart_config.parity, test_expected_uart_config.parity);
159 
160 	zassert_equal(test_uart_config.stop_bits, test_expected_uart_config.stop_bits,
161 		      "Set and actual UART config stop_bits mismatch: %d != %d",
162 		      test_uart_config.stop_bits, test_expected_uart_config.stop_bits);
163 
164 	zassert_equal(test_uart_config.data_bits, test_expected_uart_config.data_bits,
165 		      "Set and actual UART config data_bits mismatch: %d != %d",
166 		      test_uart_config.data_bits, test_expected_uart_config.data_bits);
167 
168 	zassert_equal(test_uart_config.flow_ctrl, test_expected_uart_config.flow_ctrl,
169 		      "Set and actual UART config flow_ctrl mismatch: %d != %d",
170 		      test_uart_config.flow_ctrl, test_expected_uart_config.flow_ctrl);
171 }
172 
173 /*
174  * Test UART improper configuration call
175  */
ZTEST(uart_elementary,test_uart_improper_configuration)176 ZTEST(uart_elementary, test_uart_improper_configuration)
177 {
178 	Z_TEST_SKIP_IFDEF(CONFIG_DUAL_UART_TEST);
179 
180 	int err;
181 	struct uart_config test_uart_config = { .baudrate = UART_BAUDRATE,
182 						.parity = 7,
183 						.stop_bits = UART_CFG_STOP_BITS_1,
184 						.data_bits = UART_CFG_DATA_BITS_8,
185 						.flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS };
186 
187 	err = uart_configure(uart_dev, &test_uart_config);
188 	zassert_not_equal(
189 		err, 0,
190 		"'uart_configure' with incorrect configuration havent't raised an error, err=%d",
191 		err);
192 }
193 
194 #if !defined(CONFIG_DUAL_UART_TEST)
195 /*
196  * Test UART basic interrupt based transmission (with loopback)
197  */
ZTEST(uart_elementary,test_uart_basic_transmission)198 ZTEST(uart_elementary, test_uart_basic_transmission)
199 {
200 	int err;
201 	struct uart_config test_uart_config = { .baudrate = UART_BAUDRATE,
202 						.parity = UART_CFG_PARITY_ODD,
203 						.stop_bits = UART_CFG_STOP_BITS_1,
204 						.data_bits = UART_CFG_DATA_BITS_8,
205 						.flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS };
206 
207 	err = uart_configure(uart_dev, &test_uart_config);
208 	zassert_equal(err, 0, "Unexpected error when configuring UART0: %d", err);
209 
210 	err = uart_irq_callback_set(uart_dev, interrupt_driven_uart_callback_main_uart);
211 	zassert_equal(err, 0, "Unexpected error when setting callback %d", err);
212 	err = uart_irq_callback_user_data_set(uart_dev, interrupt_driven_uart_callback_main_uart,
213 					      (void *)test_buffer);
214 	zassert_equal(err, 0, "Unexpected error when setting user data for callback %d", err);
215 	uart_irq_err_enable(uart_dev);
216 	uart_irq_rx_enable(uart_dev);
217 	uart_irq_tx_enable(uart_dev);
218 
219 	/* wait for the tramission to finish (no polling is intentional) */
220 	k_sleep(K_USEC(100 * SLEEP_TIME_US));
221 
222 	uart_irq_tx_disable(uart_dev);
223 	uart_irq_rx_disable(uart_dev);
224 	uart_irq_err_disable(uart_dev);
225 	for (int index = 0; index < TEST_BUFFER_LEN; index++) {
226 		zassert_equal(test_buffer[index], test_pattern[index],
227 			      "Received data byte %d does not match pattern 0x%x != 0x%x", index,
228 			      test_buffer[index], test_pattern[index]);
229 	}
230 }
231 #else
232 /*
233  * Test UART interrupt based transmission between two ports
234  */
ZTEST(uart_elementary,test_uart_dual_port_transmission)235 ZTEST(uart_elementary, test_uart_dual_port_transmission)
236 {
237 	int err;
238 	struct uart_config test_uart_config = { .baudrate = UART_BAUDRATE,
239 						.parity = UART_CFG_PARITY_EVEN,
240 						.stop_bits = UART_CFG_STOP_BITS_2,
241 						.data_bits = UART_CFG_DATA_BITS_8,
242 						.flow_ctrl = UART_CFG_FLOW_CTRL_NONE };
243 
244 #if defined(CONFIG_SETUP_MISMATCH_TEST)
245 	struct uart_config test_uart_config_aux = { .baudrate = CONFIG_UART_BAUDRATE_MISMATCH,
246 						    .parity = UART_CFG_PARITY_EVEN,
247 						    .stop_bits = UART_CFG_STOP_BITS_2,
248 						    .data_bits = UART_CFG_DATA_BITS_8,
249 						    .flow_ctrl = UART_CFG_FLOW_CTRL_NONE };
250 #endif
251 	err = uart_configure(uart_dev, &test_uart_config);
252 	zassert_equal(err, 0, "Unexpected error when configuring UART0: %d", err);
253 
254 #if defined(CONFIG_SETUP_MISMATCH_TEST)
255 	err = uart_configure(uart_dev_aux, &test_uart_config_aux);
256 #else
257 	err = uart_configure(uart_dev_aux, &test_uart_config);
258 #endif
259 
260 	zassert_equal(err, 0, "Unexpected error when configuring UART1: %d", err);
261 
262 	err = uart_irq_callback_set(uart_dev, interrupt_driven_uart_callback_main_uart);
263 	zassert_equal(err, 0, "Unexpected error when setting callback for UART0 %d", err);
264 	err = uart_irq_callback_user_data_set(uart_dev, interrupt_driven_uart_callback_main_uart,
265 					      (void *)test_buffer);
266 	zassert_equal(err, 0, "Unexpected error when setting user data for UART0 callback %d", err);
267 
268 	err = uart_irq_callback_set(uart_dev_aux, interrupt_driven_uart_callback_aux_uart);
269 	zassert_equal(err, 0, "Unexpected error when setting callback for UART1 %d", err);
270 	err = uart_irq_callback_user_data_set(uart_dev_aux, interrupt_driven_uart_callback_aux_uart,
271 					      (void *)test_buffer_aux);
272 	zassert_equal(err, 0, "Unexpected error when setting user data for UART1 callback %d", err);
273 
274 	if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
275 		int usage = pm_device_runtime_usage(uart_dev);
276 		int usage_aux = pm_device_runtime_usage(uart_dev_aux);
277 
278 		zassert_equal(usage, 0);
279 		zassert_equal(usage_aux, 0);
280 		pm_device_runtime_get(uart_dev);
281 		pm_device_runtime_get(uart_dev_aux);
282 	}
283 
284 	uart_irq_err_enable(uart_dev);
285 	uart_irq_err_enable(uart_dev_aux);
286 
287 	uart_irq_rx_enable(uart_dev);
288 	uart_irq_rx_enable(uart_dev_aux);
289 
290 	uart_irq_tx_enable(uart_dev);
291 	uart_irq_tx_enable(uart_dev_aux);
292 
293 	/* wait for the tramission to finish (no polling is intentional) */
294 	k_sleep(K_USEC(100 * SLEEP_TIME_US));
295 
296 	uart_irq_tx_disable(uart_dev);
297 	uart_irq_tx_disable(uart_dev_aux);
298 	uart_irq_rx_disable(uart_dev);
299 	uart_irq_rx_disable(uart_dev_aux);
300 	uart_irq_err_disable(uart_dev);
301 	uart_irq_err_disable(uart_dev_aux);
302 
303 	if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
304 		pm_device_runtime_put(uart_dev);
305 		pm_device_runtime_put(uart_dev_aux);
306 
307 		int usage = pm_device_runtime_usage(uart_dev);
308 		int usage_aux = pm_device_runtime_usage(uart_dev_aux);
309 
310 		zassert_equal(usage, 0);
311 		zassert_equal(usage_aux, 0);
312 	}
313 
314 #if defined(CONFIG_SETUP_MISMATCH_TEST)
315 	TC_PRINT("Mismatched configuration test\n");
316 	zassert_not_equal(uart_error_counter + aux_uart_error_counter, 0,
317 			  "UART configuration mismatch error not detected");
318 
319 #else
320 	for (int index = 0; index < TEST_BUFFER_LEN; index++) {
321 		zassert_equal(test_buffer[index], test_pattern[index],
322 			      "UART0 received data byte %d does not match pattern 0x%x != 0x%x",
323 			      index, test_buffer[index], test_pattern[index]);
324 		zassert_equal(test_buffer_aux[index], test_pattern[index],
325 			      "UART1 received data byte %d does not match pattern 0x%x != 0x%x",
326 			      index, test_buffer_aux[index], test_pattern[index]);
327 	}
328 #endif /* CONFIG_SETUP_MISMATCH_TEST */
329 }
330 #endif /* CONFIG_DUAL_UART_TEST */
331 
332 /*
333  * Test setup
334  */
test_setup(void)335 void *test_setup(void)
336 {
337 	zassert_true(device_is_ready(uart_dev), "UART0 device is not ready");
338 #if defined(CONFIG_DUAL_UART_TEST)
339 	zassert_true(device_is_ready(uart_dev_aux), "UART1 device is not ready");
340 #endif
341 
342 	return NULL;
343 }
344 
345 ZTEST_SUITE(uart_elementary, NULL, test_setup, NULL, NULL, NULL);
346