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