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 
uart_find(void)21 static rt_err_t uart_find(void)
22 {
23     serial = (struct rt_serial_device *)rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
24 
25     if (serial == RT_NULL)
26     {
27         LOG_E("find %s device failed!\n", RT_SERIAL_TC_DEVICE_NAME);
28         return -RT_ERROR;
29     }
30 
31     return RT_EOK;
32 }
33 
test_item(rt_uint8_t * uart_write_buffer,rt_uint32_t send_size)34 static rt_err_t test_item(rt_uint8_t *uart_write_buffer, rt_uint32_t send_size)
35 {
36     rt_uint8_t  readBuf[16] = {0};
37     rt_uint32_t readSize    = 0;
38     if (send_size >= sizeof(readBuf))
39     {
40         readSize = sizeof(readBuf);
41     }
42     else
43     {
44         readSize = send_size;
45     }
46 
47     rt_ssize_t size = rt_device_write(&serial->parent, 0, uart_write_buffer, send_size);
48     if (size != send_size)
49     {
50         LOG_E("size [%4d], send_size [%4d]", size, send_size);
51         return -RT_ERROR;
52     }
53     rt_thread_mdelay(send_size * 0.0868 + 5);
54     if (1 != rt_device_read(&serial->parent, 0, uart_write_buffer, 1))
55     {
56         LOG_E("read failed.");
57         return -RT_ERROR;
58     }
59 
60     rt_device_control(&serial->parent, RT_SERIAL_CTRL_RX_FLUSH, RT_NULL);
61     if (0 != rt_device_read(&serial->parent, 0, uart_write_buffer, 1))
62     {
63         LOG_E("read failed.");
64         return -RT_ERROR;
65     }
66 
67     /* Resend the data and check for any discrepancies upon reception */
68     if (readSize > 0)
69     {
70         rt_device_write(&serial->parent, 0, uart_write_buffer, readSize);
71         rt_thread_mdelay(readSize * 0.0868 + 5);
72         rt_device_read(&serial->parent, 0, readBuf, readSize);
73 
74         for (rt_uint32_t i = 0; i < readSize; i++)
75         {
76             if (readBuf[i] != uart_write_buffer[i])
77             {
78                 LOG_E("index: %d, Read Different data -> former data: %x, current data: %x.", i, uart_write_buffer[i], readBuf[i]);
79                 return -RT_ERROR;
80             }
81         }
82     }
83 
84     LOG_I("flush rx send_size [%4d]", send_size);
85 
86     return RT_EOK;
87 }
88 
uart_api()89 static rt_bool_t uart_api()
90 {
91     rt_err_t result = RT_EOK;
92 
93     result = uart_find();
94     if (result != RT_EOK)
95     {
96         return RT_FALSE;
97     }
98 
99     /* Reinitialize */
100     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
101     config.baud_rate               = BAUD_RATE_115200;
102     config.rx_bufsz                = RT_SERIAL_TC_RXBUF_SIZE;
103     config.tx_bufsz                = RT_SERIAL_TC_TXBUF_SIZE;
104 #ifdef RT_SERIAL_USING_DMA
105     config.dma_ping_bufsz = RT_SERIAL_TC_RXBUF_SIZE / 2;
106 #endif
107     rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
108 
109     result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
110     if (result != RT_EOK)
111     {
112         LOG_E("Open uart device failed.");
113         return RT_FALSE;
114     }
115 
116     rt_uint8_t *uart_write_buffer;
117     rt_uint32_t i;
118     uart_write_buffer = (rt_uint8_t *)rt_malloc(RT_SERIAL_TC_RXBUF_SIZE * 5 + 1);
119     for (rt_uint32_t count = 0; count < (RT_SERIAL_TC_RXBUF_SIZE * 5 + 1); count++)
120     {
121         uart_write_buffer[count] = count;
122     }
123 
124     srand(rt_tick_get());
125     for (i = 0; i < RT_SERIAL_TC_SEND_ITERATIONS; i++)
126     {
127         if (RT_EOK != test_item(uart_write_buffer, RT_SERIAL_TC_RXBUF_SIZE + RT_SERIAL_TC_RXBUF_SIZE * (rand() % 5)))
128         {
129             LOG_E("test_item failed.");
130             result = -RT_ERROR;
131             goto __exit;
132         }
133 
134         if (RT_EOK != test_item(uart_write_buffer, rand() % (RT_SERIAL_TC_RXBUF_SIZE * 5)))
135         {
136             LOG_E("test_item failed.");
137             result = -RT_ERROR;
138             goto __exit;
139         }
140     }
141 
142 __exit:
143     rt_free(uart_write_buffer);
144     rt_device_close(&serial->parent);
145     rt_thread_mdelay(5);
146     return result == RT_EOK ? RT_TRUE : RT_FALSE;
147 }
148 
tc_uart_api(void)149 static void tc_uart_api(void)
150 {
151     uassert_true(uart_api() == RT_TRUE);
152 }
153 
utest_tc_init(void)154 static rt_err_t utest_tc_init(void)
155 {
156     LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
157     return RT_EOK;
158 }
159 
utest_tc_cleanup(void)160 static rt_err_t utest_tc_cleanup(void)
161 {
162     rt_device_t uart_dev = rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
163     while (rt_device_close(uart_dev) != -RT_ERROR);
164     return RT_EOK;
165 }
166 
testcase(void)167 static void testcase(void)
168 {
169     UTEST_UNIT_RUN(tc_uart_api);
170 }
171 
172 UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_flush_rx", utest_tc_init, utest_tc_cleanup, 30);
173 
174 #endif /* TC_UART_USING_TC */
175