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