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_uint32_t old_tick;
37     rt_tick_t   tick_diff;
38     rt_tick_t   expect_time = send_size * 0.0868;
39 
40     rt_uint8_t  readBuf[16] = {0};
41     rt_uint32_t readSize    = 0;
42     if (send_size >= sizeof(readBuf))
43     {
44         readSize = sizeof(readBuf);
45     }
46     else
47     {
48         readSize = send_size;
49     }
50 
51     /* In interrupt mode, ticks may be inaccurate; compensation should be applied*/
52     if (send_size > 384)
53     {
54         expect_time -= send_size / 384;
55     }
56 
57     old_tick        = rt_tick_get();
58     rt_ssize_t size = rt_device_write(&serial->parent, 0, uart_write_buffer, send_size);
59     if (size != send_size)
60     {
61         LOG_E("size [%4d], send_size [%4d]", size, send_size);
62         return -RT_ERROR;
63     }
64     rt_device_control(&serial->parent, RT_SERIAL_CTRL_TX_FLUSH, RT_NULL);
65     tick_diff = rt_tick_get() - old_tick;
66 
67     if (tick_diff < expect_time || tick_diff > (expect_time + 10))
68     {
69         LOG_E("send_size [%4d], time required for TXB mode transmission to complete [%3d], expect_time [%3d]", send_size, tick_diff, expect_time);
70         return -RT_ERROR;
71     }
72     else
73     {
74         LOG_I("send_size [%4d], time required for TXB mode transmission to complete [%3d], expect_time [%3d]", send_size, tick_diff, expect_time);
75     }
76 
77     /* Resend the data and check for any discrepancies upon reception */
78     if (readSize > 0)
79     {
80         rt_device_control(&serial->parent, RT_SERIAL_CTRL_RX_FLUSH, RT_NULL);
81         rt_device_write(&serial->parent, 0, uart_write_buffer, readSize);
82         rt_device_read(&serial->parent, 0, readBuf, readSize);
83 
84         for (rt_uint32_t i = 0; i < readSize; i++)
85         {
86             if (readBuf[i] != uart_write_buffer[i])
87             {
88                 LOG_E("index: %d, Read Different data -> former data: %x, current data: %x.", i, uart_write_buffer[i], readBuf[i]);
89                 return -RT_ERROR;
90             }
91         }
92     }
93 
94 
95     return RT_EOK;
96 }
97 
uart_api()98 static rt_bool_t uart_api()
99 {
100     rt_err_t result = RT_EOK;
101 
102     result = uart_find();
103     if (result != RT_EOK)
104     {
105         return RT_FALSE;
106     }
107 
108     /* Reinitialize */
109     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
110     config.baud_rate               = BAUD_RATE_115200;
111     config.rx_bufsz                = RT_SERIAL_TC_RXBUF_SIZE;
112     config.tx_bufsz                = RT_SERIAL_TC_TXBUF_SIZE * 5 + 10;
113 #ifdef RT_SERIAL_USING_DMA
114     config.dma_ping_bufsz = RT_SERIAL_TC_RXBUF_SIZE / 2;
115 #endif
116     rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
117 
118     result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
119     if (result != RT_EOK)
120     {
121         LOG_E("Open uart device failed.");
122         return RT_FALSE;
123     }
124 
125     rt_uint8_t *uart_write_buffer;
126     rt_uint32_t i;
127     rt_int32_t  tx_timeout = 10 * 1000;
128     uart_write_buffer      = (rt_uint8_t *)rt_malloc(RT_SERIAL_TC_TXBUF_SIZE * 5 + 10);
129     for (rt_uint32_t count = 0; count < (RT_SERIAL_TC_TXBUF_SIZE * 5 + 10); count++)
130     {
131         uart_write_buffer[count] = count;
132     }
133 
134     rt_device_control(&serial->parent, RT_SERIAL_CTRL_SET_TX_TIMEOUT, (void *)&tx_timeout);
135 
136     srand(rt_tick_get());
137     for (i = 0; i < RT_SERIAL_TC_SEND_ITERATIONS; i++)
138     {
139         if (RT_EOK != test_item(uart_write_buffer, RT_SERIAL_TC_TXBUF_SIZE * (rand() % 6)))
140         {
141             result = -RT_ERROR;
142             goto __exit;
143         }
144         if (RT_EOK != test_item(uart_write_buffer, RT_SERIAL_TC_TXBUF_SIZE * (rand() % 6) + 1))
145         {
146             result = -RT_ERROR;
147             goto __exit;
148         }
149 
150         if (RT_EOK != test_item(uart_write_buffer, rand() % (RT_SERIAL_TC_TXBUF_SIZE * 5)))
151         {
152             result = -RT_ERROR;
153             goto __exit;
154         }
155     }
156 
157 __exit:
158     rt_free(uart_write_buffer);
159     rt_device_close(&serial->parent);
160     rt_thread_mdelay(5);
161     return result == RT_EOK ? RT_TRUE : RT_FALSE;
162 }
163 
tc_uart_api(void)164 static void tc_uart_api(void)
165 {
166     uassert_true(uart_api() == RT_TRUE);
167 }
168 
utest_tc_init(void)169 static rt_err_t utest_tc_init(void)
170 {
171     return RT_EOK;
172 }
173 
utest_tc_cleanup(void)174 static rt_err_t utest_tc_cleanup(void)
175 {
176     rt_device_t uart_dev = rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
177     while (rt_device_close(uart_dev) != -RT_ERROR);
178     return RT_EOK;
179 }
180 
testcase(void)181 static void testcase(void)
182 {
183     UTEST_UNIT_RUN(tc_uart_api);
184 }
185 
186 UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_flush_txb", utest_tc_init, utest_tc_cleanup, 30);
187 
188 #endif /* TC_UART_USING_TC */
189