1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * @addtogroup t_uart_basic
9  * @{
10  * @defgroup t_uart_fifo test_uart_fifo
11  * @brief TestPurpose: verify UART works well in fifo mode
12  * @details
13  * - Test Steps
14  *   - FIFO Output:
15  *      -# Set UART IRQ callback using uart_irq_callback_set().
16  *      -# Enable UART TX IRQ using uart_irq_tx_enable().
17  *      -# Output the prepared data using uart_fifo_fill().
18  *      -# Disable UART TX IRQ using uart_irq_tx_disable().
19  *      -# Compare the number of characters sent out with the
20  *         original data size.
21  *   - FIFO Input:
22  *      -# Set UART IRQ callback using uart_irq_callback_set().
23  *      -# Enable UART RX IRQ using uart_irq_rx_enable().
24  *      -# Wait for data sent to UART console and trigger RX IRQ.
25  *      -# Read data from UART console using uart_fifo_read().
26  *      -# Disable UART TX IRQ using uart_irq_rx_disable().
27  * - Expected Results
28  *   -# When test UART FIFO output, the number of characters actually
29  *      sent out will be equal to the original length of the characters.
30  *   -# When test UART FIFO input, the app will wait for input from UART
31  *      console and exit after receiving one character.
32  * @}
33  */
34 
35 #include "test_uart.h"
36 
37 static volatile bool data_transmitted;
38 static volatile bool data_received;
39 static int char_sent;
40 static const char fifo_data[] = "This is a FIFO test.\r\n";
41 
42 #define DATA_SIZE	(sizeof(fifo_data) - 1)
43 
uart_fifo_callback(const struct device * dev,void * user_data)44 static void uart_fifo_callback(const struct device *dev, void *user_data)
45 {
46 	uint8_t recvData;
47 	static int tx_data_idx;
48 	int ret;
49 
50 	ARG_UNUSED(user_data);
51 
52 	/* Verify uart_irq_update() */
53 	if (!uart_irq_update(dev)) {
54 		TC_PRINT("retval should always be 1\n");
55 		return;
56 	}
57 
58 	/* Verify uart_irq_tx_ready() */
59 	/* Note that TX IRQ may be disabled, but uart_irq_tx_ready() may
60 	 * still return true when ISR is called for another UART interrupt,
61 	 * hence additional check for i < DATA_SIZE.
62 	 */
63 	if (uart_irq_tx_ready(dev) && tx_data_idx < DATA_SIZE) {
64 		/* We arrive here by "tx ready" interrupt, so should always
65 		 * be able to put at least one byte into a FIFO. If not,
66 		 * well, we'll fail test.
67 		 */
68 		ret = uart_fifo_fill(dev, (uint8_t *)&fifo_data[tx_data_idx],
69 				     DATA_SIZE - char_sent);
70 		if (ret > 0) {
71 			data_transmitted = true;
72 			char_sent += ret;
73 			tx_data_idx += ret;
74 		} else {
75 			uart_irq_tx_disable(dev);
76 			return;
77 		}
78 
79 		if (tx_data_idx == DATA_SIZE) {
80 			/* If we transmitted everything, stop IRQ stream,
81 			 * otherwise main app might never run.
82 			 */
83 			uart_irq_tx_disable(dev);
84 		}
85 	}
86 
87 	/* Verify uart_irq_rx_ready() */
88 	if (uart_irq_rx_ready(dev)) {
89 		/* Verify uart_fifo_read() */
90 		uart_fifo_read(dev, &recvData, 1);
91 		TC_PRINT("%c", recvData);
92 
93 		if ((recvData == '\n') || (recvData == '\r')) {
94 			data_received = true;
95 		}
96 	}
97 }
98 
test_fifo_read(void)99 static int test_fifo_read(void)
100 {
101 	const struct device *const uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
102 
103 	if (!device_is_ready(uart_dev)) {
104 		TC_PRINT("UART device not ready\n");
105 		return TC_FAIL;
106 	}
107 
108 	/* Verify uart_irq_callback_set() */
109 	uart_irq_callback_set(uart_dev, uart_fifo_callback);
110 
111 	/* Enable Tx/Rx interrupt before using fifo */
112 	/* Verify uart_irq_rx_enable() */
113 	uart_irq_rx_enable(uart_dev);
114 
115 	TC_PRINT("Please send characters to serial console\n");
116 
117 	data_received = false;
118 	while (data_received == false) {
119 		/* Allow other thread/workqueue to work. */
120 		k_yield();
121 	}
122 
123 	/* Verify uart_irq_rx_disable() */
124 	uart_irq_rx_disable(uart_dev);
125 
126 	return TC_PASS;
127 }
128 
test_fifo_fill(void)129 static int test_fifo_fill(void)
130 {
131 	const struct device *const uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
132 
133 	if (!device_is_ready(uart_dev)) {
134 		TC_PRINT("UART device not ready\n");
135 		return TC_FAIL;
136 	}
137 
138 	char_sent = 0;
139 
140 	/* Verify uart_irq_callback_set() */
141 	uart_irq_callback_set(uart_dev, uart_fifo_callback);
142 
143 	/* Enable Tx/Rx interrupt before using fifo */
144 	/* Verify uart_irq_tx_enable() */
145 	uart_irq_tx_enable(uart_dev);
146 
147 	k_sleep(K_MSEC(500));
148 
149 	/* Verify uart_irq_tx_disable() */
150 	uart_irq_tx_disable(uart_dev);
151 
152 	if (!data_transmitted) {
153 		return TC_FAIL;
154 	}
155 
156 	if (char_sent == DATA_SIZE) {
157 		return TC_PASS;
158 	} else {
159 		return TC_FAIL;
160 	}
161 
162 }
163 
164 #if CONFIG_SHELL
test_uart_fifo_fill(void)165 void test_uart_fifo_fill(void)
166 #else
167 ZTEST(uart_basic_api, test_uart_fifo_fill)
168 #endif
169 {
170 #ifndef CONFIG_UART_INTERRUPT_DRIVEN
171 	ztest_test_skip();
172 #endif
173 	zassert_true(test_fifo_fill() == TC_PASS);
174 }
175 
176 #if CONFIG_SHELL
test_uart_fifo_read(void)177 void test_uart_fifo_read(void)
178 #else
179 ZTEST(uart_basic_api, test_uart_fifo_read)
180 #endif
181 {
182 #ifndef CONFIG_UART_INTERRUPT_DRIVEN
183 	ztest_test_skip();
184 #endif
185 	zassert_true(test_fifo_read() == TC_PASS);
186 }
187