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