uart_rxb_txb.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Copyright (c) 2006-2025 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. * 2025-11-13 CYFS Add standardized utest documentation block
  10. */
  11. /**
  12. * Test Case Name: UART Blocking RX & TX Integration Test
  13. *
  14. * Test Objectives:
  15. * - Validate simultaneous blocking receive/transmit operation with sequential integrity checks
  16. * - Verify APIs: rt_device_find, rt_device_control(RT_DEVICE_CTRL_CONFIG / RT_SERIAL_CTRL_SET_RX_TIMEOUT),
  17. * rt_device_open with RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING,
  18. * rt_device_read, rt_device_write, rt_thread_create/startup
  19. *
  20. * Test Scenarios:
  21. * - **Scenario 1 (Length Sweep & Randomized Payloads / tc_uart_api):**
  22. * 1. Reconfigure UART to known buffer sizes (optional DMA ping buffer) and set generous RX timeout.
  23. * 2. Spawn paired producer/consumer threads; sender streams monotonically increasing bytes while receiver validates ordering until quota met.
  24. * 3. Iterate over deterministic payload lengths based on TX buffer, RX buffer, and random samples until `RT_SERIAL_TC_SEND_ITERATIONS` reached.
  25. * 4. Monitor flags for allocation failures or data mismatches; terminate threads once reception quota per iteration satisfied.
  26. *
  27. * Verification Metrics:
  28. * - Each transfer completes with ordered byte sequence and total receive length equals requested count.
  29. * - `uart_result` remains `RT_TRUE`; `uart_over_flag` set per iteration before teardown.
  30. * - Device open/close succeeds across all iterations without lingering handles.
  31. *
  32. * Dependencies:
  33. * - Requires `RT_UTEST_SERIAL_V2` with loopback wiring on `RT_SERIAL_TC_DEVICE_NAME`.
  34. * - Blocking mode support plus optional DMA ping buffer configuration.
  35. * - Thread stack allocations (2 × 1 KB) and send buffers must be available from heap.
  36. *
  37. * Expected Results:
  38. * - Unit test passes without assertions; logs show progressive length coverage.
  39. * - Utest framework prints `[ PASSED ] [ result ] testcase (components.drivers.serial.v2.uart_rxb_txb)`.
  40. */
  41. #include <rtthread.h>
  42. #include "utest.h"
  43. #include <rtdevice.h>
  44. #include <stdlib.h>
  45. #ifdef RT_UTEST_SERIAL_V2
  46. static struct rt_serial_device *serial;
  47. static rt_uint8_t uart_over_flag;
  48. static rt_bool_t uart_result = RT_TRUE;
  49. static rt_err_t uart_find(void)
  50. {
  51. serial = (struct rt_serial_device *)rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
  52. if (serial == RT_NULL)
  53. {
  54. LOG_E("find %s device failed!\n", RT_SERIAL_TC_DEVICE_NAME);
  55. return -RT_ERROR;
  56. }
  57. return RT_EOK;
  58. }
  59. static void uart_send_entry(void *parameter)
  60. {
  61. rt_uint8_t *uart_write_buffer;
  62. rt_uint16_t send_len;
  63. rt_uint32_t i = 0;
  64. send_len = *(rt_uint16_t *)parameter;
  65. /* assign send buffer */
  66. uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len);
  67. if (uart_write_buffer == RT_NULL)
  68. {
  69. LOG_E("Without spare memory for uart dma!");
  70. uart_result = RT_FALSE;
  71. return;
  72. }
  73. rt_memset(uart_write_buffer, 0, send_len);
  74. for (i = 0; i < send_len; i++)
  75. {
  76. uart_write_buffer[i] = (rt_uint8_t)i;
  77. }
  78. /* send buffer */
  79. if (rt_device_write(&serial->parent, 0, uart_write_buffer, send_len) != send_len)
  80. {
  81. LOG_E("device write failed\r\n");
  82. }
  83. rt_free(uart_write_buffer);
  84. }
  85. static void uart_rec_entry(void *parameter)
  86. {
  87. rt_uint16_t rev_len;
  88. rev_len = *(rt_uint16_t *)parameter;
  89. rt_uint8_t *uart_write_buffer;
  90. uart_write_buffer = (rt_uint8_t *)rt_calloc(1, rev_len + 1);
  91. rt_int32_t cnt, i;
  92. rt_uint8_t last_old_data;
  93. rt_bool_t fisrt_flag = RT_TRUE;
  94. rt_uint32_t all_receive_length = 0;
  95. while (1)
  96. {
  97. cnt = rt_device_read(&serial->parent, 0, (void *)uart_write_buffer, rev_len);
  98. if (cnt == 0)
  99. {
  100. continue;
  101. }
  102. if (fisrt_flag != RT_TRUE)
  103. {
  104. if ((rt_uint8_t)(last_old_data + 1) != uart_write_buffer[0])
  105. {
  106. LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, uart_write_buffer[0]);
  107. uart_result = RT_FALSE;
  108. rt_free(uart_write_buffer);
  109. return;
  110. }
  111. }
  112. else
  113. {
  114. fisrt_flag = RT_FALSE;
  115. }
  116. for (i = 0; i < cnt - 1; i++)
  117. {
  118. if ((rt_uint8_t)(uart_write_buffer[i] + 1) != uart_write_buffer[i + 1])
  119. {
  120. LOG_E("Read Different data -> former data: %x, current data: %x.", uart_write_buffer[i], uart_write_buffer[i + 1]);
  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. static rt_err_t uart_api(rt_uint16_t length)
  136. {
  137. rt_thread_t thread_send = RT_NULL;
  138. rt_thread_t thread_recv = RT_NULL;
  139. rt_err_t result = RT_EOK;
  140. uart_over_flag = RT_FALSE;
  141. result = uart_find();
  142. if (result != RT_EOK)
  143. {
  144. return -RT_ERROR;
  145. }
  146. /* Reinitialize */
  147. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  148. config.baud_rate = BAUD_RATE_115200;
  149. config.rx_bufsz = RT_SERIAL_TC_RXBUF_SIZE;
  150. config.tx_bufsz = RT_SERIAL_TC_TXBUF_SIZE;
  151. #ifdef RT_SERIAL_USING_DMA
  152. config.dma_ping_bufsz = RT_SERIAL_TC_RXBUF_SIZE / 2;
  153. #endif
  154. rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
  155. result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
  156. if (result != RT_EOK)
  157. {
  158. LOG_E("Open uart device failed.");
  159. uart_result = RT_FALSE;
  160. return -RT_ERROR;
  161. }
  162. rt_int32_t timeout = 5000;
  163. rt_device_control(&serial->parent, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void *)&timeout);
  164. thread_send = rt_thread_create("uart_send", uart_send_entry, &length, 1024, RT_THREAD_PRIORITY_MAX - 4, 10);
  165. thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &length, 1024, RT_THREAD_PRIORITY_MAX - 5, 10);
  166. if ((thread_send != RT_NULL) && (thread_recv != RT_NULL))
  167. {
  168. rt_thread_startup(thread_send);
  169. rt_thread_startup(thread_recv);
  170. }
  171. else
  172. {
  173. result = -RT_ERROR;
  174. goto __exit;
  175. }
  176. while (1)
  177. {
  178. if (uart_result != RT_TRUE)
  179. {
  180. LOG_E("The test for uart dma is failure.");
  181. result = -RT_ERROR;
  182. goto __exit;
  183. }
  184. if (uart_over_flag == RT_TRUE)
  185. {
  186. goto __exit;
  187. }
  188. /* waiting for test over */
  189. rt_thread_mdelay(5);
  190. }
  191. __exit:
  192. rt_device_close(&serial->parent);
  193. rt_thread_mdelay(5);
  194. uart_over_flag = RT_FALSE;
  195. return result;
  196. }
  197. static void tc_uart_api(void)
  198. {
  199. rt_uint32_t count = 0;
  200. rt_uint16_t num = 0;
  201. rt_uint32_t i = 0;
  202. for (i = 1; i < 10; i++)
  203. {
  204. if (uart_api(RT_SERIAL_TC_TXBUF_SIZE * i + i % 2) == RT_EOK)
  205. 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);
  206. else
  207. {
  208. LOG_E("uart test error");
  209. goto __exit;
  210. }
  211. }
  212. for (i = 1; i < 10; i++)
  213. {
  214. if (uart_api(RT_SERIAL_TC_RXBUF_SIZE * i + i % 2) == RT_EOK)
  215. 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);
  216. else
  217. {
  218. LOG_E("uart test error");
  219. goto __exit;
  220. }
  221. }
  222. srand(rt_tick_get());
  223. while (RT_SERIAL_TC_SEND_ITERATIONS - count)
  224. {
  225. num = (rand() % 1000) + 1;
  226. if (uart_api(num) == RT_EOK)
  227. LOG_I("data_lens [%4d], it is correct to read and write data. [%d] count testing.", num, ++count);
  228. else
  229. {
  230. LOG_E("uart test error");
  231. break;
  232. }
  233. }
  234. __exit:
  235. uassert_true(uart_result == RT_TRUE);
  236. }
  237. static rt_err_t utest_tc_init(void)
  238. {
  239. LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
  240. return RT_EOK;
  241. }
  242. static rt_err_t utest_tc_cleanup(void)
  243. {
  244. uart_result = RT_TRUE;
  245. uart_over_flag = RT_FALSE;
  246. rt_device_t uart_dev = rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
  247. while (rt_device_close(uart_dev) != -RT_ERROR);
  248. return RT_EOK;
  249. }
  250. static void testcase(void)
  251. {
  252. UTEST_UNIT_RUN(tc_uart_api);
  253. }
  254. UTEST_TC_EXPORT(testcase, "components.drivers.serial.v2.uart_rxb_txb", utest_tc_init, utest_tc_cleanup, 30);
  255. #endif /* TC_UART_USING_TC */