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