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