1 /*
2 * Copyright (c) 2006-2024 RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-06-16 KyleChan the first version
9 */
10
11 #include <rtthread.h>
12 #include "utest.h"
13 #include <rtdevice.h>
14 #include <stdlib.h>
15
16
17 #ifdef UTEST_SERIAL_TC
18
19 static struct rt_serial_device *serial;
20 static rt_sem_t tx_sem;
21 static rt_sem_t rx_sem;
22 static rt_uint8_t uart_over_flag;
23 static rt_bool_t uart_result = RT_TRUE;
24
uart_find(void)25 static rt_err_t uart_find(void)
26 {
27 serial = (struct rt_serial_device *)rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
28
29 if (serial == RT_NULL)
30 {
31 LOG_E("find %s device failed!\n", RT_SERIAL_TC_DEVICE_NAME);
32 return -RT_ERROR;
33 }
34
35 return RT_EOK;
36 }
37
uart_tx_completion(rt_device_t device,void * buffer)38 static rt_err_t uart_tx_completion(rt_device_t device, void *buffer)
39 {
40 rt_sem_release(tx_sem);
41 return RT_EOK;
42 }
43
uart_rx_indicate(rt_device_t device,rt_size_t size)44 static rt_err_t uart_rx_indicate(rt_device_t device, rt_size_t size)
45 {
46 rt_sem_release(rx_sem);
47 return RT_EOK;
48 }
49
uart_send_entry(void * parameter)50 static void uart_send_entry(void *parameter)
51 {
52 rt_uint8_t *uart_write_buffer;
53 rt_uint16_t send_len, len = 0;
54 rt_err_t result;
55
56 rt_uint32_t i = 0;
57 send_len = *(rt_uint16_t *)parameter;
58 /* assign send buffer */
59 uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len);
60 if (uart_write_buffer == RT_NULL)
61 {
62 LOG_E("Without spare memory for uart dma!");
63 uart_result = RT_FALSE;
64 return;
65 }
66
67 rt_memset(uart_write_buffer, 0, send_len);
68
69 for (i = 0; i < send_len; i++)
70 {
71 uart_write_buffer[i] = (rt_uint8_t)i;
72 }
73 /* send buffer */
74 while (send_len - len)
75 {
76 len += rt_device_write(&serial->parent, 0, uart_write_buffer + len, send_len - len);
77 result = rt_sem_take(tx_sem, RT_WAITING_FOREVER);
78 if (result != RT_EOK)
79 {
80 LOG_E("take sem err in send.");
81 }
82 }
83 rt_free(uart_write_buffer);
84 }
85
uart_rec_entry(void * parameter)86 static void uart_rec_entry(void *parameter)
87 {
88 rt_uint16_t rev_len;
89
90 rev_len = *(rt_uint16_t *)parameter;
91 rt_uint8_t *uart_write_buffer;
92 uart_write_buffer = (rt_uint8_t *)rt_calloc(1, rev_len + 1);
93 rt_int32_t cnt, i;
94 rt_uint8_t last_old_data;
95 rt_bool_t fisrt_flag = RT_TRUE;
96 rt_uint32_t all_receive_length = 0;
97
98 while (1)
99 {
100 rt_err_t result;
101
102 result = rt_sem_take(rx_sem, RT_WAITING_FOREVER);
103 if (result != RT_EOK)
104 {
105 LOG_E("take sem err in recv.");
106 }
107
108 cnt = rt_device_read(&serial->parent, 0, (void *)uart_write_buffer, rev_len);
109 if (cnt == 0)
110 {
111 continue;
112 }
113
114 if (fisrt_flag != RT_TRUE)
115 {
116 if ((rt_uint8_t)(last_old_data + 1) != uart_write_buffer[0])
117 {
118 LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, uart_write_buffer[0]);
119 uart_result = RT_FALSE;
120 rt_free(uart_write_buffer);
121 return;
122 }
123 }
124 else
125 {
126 fisrt_flag = RT_FALSE;
127 }
128
129 for (i = 0; i < cnt - 1; i++)
130 {
131 if ((rt_uint8_t)(uart_write_buffer[i] + 1) != uart_write_buffer[i + 1])
132 {
133 LOG_E("Read Different data -> former data: %x, current data: %x.", uart_write_buffer[i], uart_write_buffer[i + 1]);
134
135 uart_result = RT_FALSE;
136 rt_free(uart_write_buffer);
137 return;
138 }
139 }
140 all_receive_length += cnt;
141 if (all_receive_length >= rev_len)
142 break;
143 else
144 last_old_data = uart_write_buffer[cnt - 1];
145 }
146 rt_free(uart_write_buffer);
147 uart_over_flag = RT_TRUE;
148 }
149
uart_api(rt_uint16_t test_buf)150 static rt_err_t uart_api(rt_uint16_t test_buf)
151 {
152 rt_thread_t thread_send = RT_NULL;
153 rt_thread_t thread_recv = RT_NULL;
154 rt_err_t result = RT_EOK;
155 uart_over_flag = RT_FALSE;
156
157 result = uart_find();
158 if (result != RT_EOK)
159 {
160 return -RT_ERROR;
161 }
162
163 rx_sem = rt_sem_create("rx_sem", 0, RT_IPC_FLAG_PRIO);
164 if (rx_sem == RT_NULL)
165 {
166 LOG_E("Init rx_sem failed.");
167 uart_result = RT_FALSE;
168 return -RT_ERROR;
169 }
170
171 tx_sem = rt_sem_create("tx_sem", 0, RT_IPC_FLAG_PRIO);
172 if (tx_sem == RT_NULL)
173 {
174 LOG_E("Init tx_sem failed.");
175 uart_result = RT_FALSE;
176 return -RT_ERROR;
177 }
178
179 /* reinitialize */
180 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
181 config.baud_rate = BAUD_RATE_115200;
182 config.rx_bufsz = RT_SERIAL_TC_RXBUF_SIZE;
183 config.tx_bufsz = RT_SERIAL_TC_TXBUF_SIZE;
184
185 #ifdef RT_SERIAL_USING_DMA
186 config.dma_ping_bufsz = RT_SERIAL_TC_RXBUF_SIZE / 2;
187 #endif
188 rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
189
190 result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING);
191 if (result != RT_EOK)
192 {
193 LOG_E("Open uart device failed.");
194 uart_result = RT_FALSE;
195 return -RT_ERROR;
196 }
197
198 rt_int32_t timeout = 5000;
199 rt_device_control(&serial->parent, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void *)&timeout);
200
201 /* set receive callback function */
202 result = rt_device_set_tx_complete(&serial->parent, uart_tx_completion);
203 if (result != RT_EOK)
204 {
205 goto __exit;
206 }
207
208 result = rt_device_set_rx_indicate(&serial->parent, uart_rx_indicate);
209 if (result != RT_EOK)
210 {
211 goto __exit;
212 }
213
214 thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 5, 10);
215 thread_send = rt_thread_create("uart_send", uart_send_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 4, 10);
216
217 if (thread_send != RT_NULL && thread_recv != RT_NULL)
218 {
219 rt_thread_startup(thread_recv);
220 rt_thread_startup(thread_send);
221 }
222 else
223 {
224 result = -RT_ERROR;
225 goto __exit;
226 }
227
228 while (1)
229 {
230 if (uart_result != RT_TRUE)
231 {
232 LOG_E("The test for uart dma is failure.");
233 result = -RT_ERROR;
234 goto __exit;
235 }
236 if (uart_over_flag == RT_TRUE)
237 {
238 goto __exit;
239 }
240 /* waiting for test over */
241 rt_thread_mdelay(5);
242 }
243 __exit:
244 if (tx_sem)
245 rt_sem_delete(tx_sem);
246
247 if (rx_sem)
248 rt_sem_delete(rx_sem);
249
250 rt_device_close(&serial->parent);
251 rt_thread_mdelay(5);
252 uart_over_flag = RT_FALSE;
253 return result;
254 }
255
tc_uart_api(void)256 static void tc_uart_api(void)
257 {
258 rt_uint32_t count = 0;
259 rt_uint16_t num = 0;
260 rt_uint32_t i = 0;
261 for (i = 1; i < 10; i++)
262 {
263 if (uart_api(RT_SERIAL_TC_TXBUF_SIZE * i + i % 2) == RT_EOK)
264 LOG_I("data_lens [%4d], it is correct to read and write data. [%d] count testing.", RT_SERIAL_TC_TXBUF_SIZE * i + i % 2, ++count);
265 else
266 {
267 LOG_E("uart test error");
268 goto __exit;
269 }
270 }
271
272 for (i = 1; i < 10; i++)
273 {
274 if (uart_api(RT_SERIAL_TC_RXBUF_SIZE * i + i % 2) == RT_EOK)
275 LOG_I("data_lens [%4d], it is correct to read and write data. [%d] count testing.", RT_SERIAL_TC_RXBUF_SIZE * i + i % 2, ++count);
276 else
277 {
278 LOG_E("uart test error");
279 goto __exit;
280 }
281 }
282
283 srand(rt_tick_get());
284 while (RT_SERIAL_TC_SEND_ITERATIONS - count)
285 {
286 num = (rand() % 1000) + 1;
287 if (uart_api(num) == RT_EOK)
288 LOG_I("data_lens [%4d], it is correct to read and write data. [%d] count testing.", num, ++count);
289 else
290 {
291 LOG_E("uart test error");
292 break;
293 }
294 }
295
296 __exit:
297 uassert_true(uart_result == RT_TRUE);
298 }
299
utest_tc_init(void)300 static rt_err_t utest_tc_init(void)
301 {
302 LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
303 return RT_EOK;
304 }
305
utest_tc_cleanup(void)306 static rt_err_t utest_tc_cleanup(void)
307 {
308 tx_sem = RT_NULL;
309 uart_result = RT_TRUE;
310 uart_over_flag = RT_FALSE;
311 rt_device_t uart_dev = rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
312 while (rt_device_close(uart_dev) != -RT_ERROR);
313 return RT_EOK;
314 }
315
testcase(void)316 static void testcase(void)
317 {
318 UTEST_UNIT_RUN(tc_uart_api);
319 }
320
321 UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxnb_txnb", utest_tc_init, utest_tc_cleanup, 30);
322
323 #endif
324