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