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