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