uart_flush_rx.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. * 2025-11-13 CYFS Add standardized utest documentation block
  9. */
  10. /**
  11. * Test Case Name: UART RX Buffer Flush Test
  12. *
  13. * Test Objectives:
  14. * - Verify RX flush control clears buffered data and preserves integrity of subsequent transfers
  15. * - Confirm APIs: rt_device_find, rt_device_control(RT_DEVICE_CTRL_CONFIG / RT_SERIAL_CTRL_RX_FLUSH),
  16. * rt_device_open with RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING,
  17. * rt_device_read, rt_device_write
  18. *
  19. * Test Scenarios:
  20. * - **Scenario 1 (Flush Validation / tc_uart_api):**
  21. * 1. Configure UART buffers and allocate test pattern spanning multiple RX buffer lengths.
  22. * 2. Send payload, consume a single byte, invoke RX flush, and ensure next read returns no residual data.
  23. * 3. Resend partial payloads of varying sizes to confirm data after flush matches original pattern.
  24. *
  25. * Verification Metrics:
  26. * - Initial read after flush returns zero bytes; subsequent reads match transmitted data byte-for-byte.
  27. * - All iterations across deterministic and random lengths complete with RT_EOK.
  28. *
  29. * Dependencies:
  30. * - Requires `RT_UTEST_SERIAL_V2`, loopback wiring, and RX flush support on `RT_SERIAL_TC_DEVICE_NAME`.
  31. * - Optional DMA ping buffer configuration honored when `RT_SERIAL_USING_DMA` enabled.
  32. *
  33. * Expected Results:
  34. * - No assertions triggered; logs show flush operations with payload sizes.
  35. * - Utest harness prints `[ PASSED ] [ result ] testcase (components.drivers.serial.v2.uart_flush_rx)`.
  36. */
  37. #include <rtthread.h>
  38. #include "utest.h"
  39. #include <rtdevice.h>
  40. #include <stdlib.h>
  41. #ifdef RT_UTEST_SERIAL_V2
  42. static struct rt_serial_device *serial;
  43. static rt_err_t uart_find(void)
  44. {
  45. serial = (struct rt_serial_device *)rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
  46. if (serial == RT_NULL)
  47. {
  48. LOG_E("find %s device failed!\n", RT_SERIAL_TC_DEVICE_NAME);
  49. return -RT_ERROR;
  50. }
  51. return RT_EOK;
  52. }
  53. static rt_err_t test_item(rt_uint8_t *uart_write_buffer, rt_uint32_t send_size)
  54. {
  55. rt_uint8_t readBuf[16] = {0};
  56. rt_uint32_t readSize = 0;
  57. if (send_size >= sizeof(readBuf))
  58. {
  59. readSize = sizeof(readBuf);
  60. }
  61. else
  62. {
  63. readSize = send_size;
  64. }
  65. rt_ssize_t size = rt_device_write(&serial->parent, 0, uart_write_buffer, send_size);
  66. if (size != send_size)
  67. {
  68. LOG_E("size [%4d], send_size [%4d]", size, send_size);
  69. return -RT_ERROR;
  70. }
  71. rt_thread_mdelay(send_size * 0.0868 + 5);
  72. if (1 != rt_device_read(&serial->parent, 0, uart_write_buffer, 1))
  73. {
  74. LOG_E("read failed.");
  75. return -RT_ERROR;
  76. }
  77. rt_device_control(&serial->parent, RT_SERIAL_CTRL_RX_FLUSH, RT_NULL);
  78. if (0 != rt_device_read(&serial->parent, 0, uart_write_buffer, 1))
  79. {
  80. LOG_E("read failed.");
  81. return -RT_ERROR;
  82. }
  83. /* Resend the data and check for any discrepancies upon reception */
  84. if (readSize > 0)
  85. {
  86. rt_device_write(&serial->parent, 0, uart_write_buffer, readSize);
  87. rt_thread_mdelay(readSize * 0.0868 + 5);
  88. rt_device_read(&serial->parent, 0, readBuf, readSize);
  89. for (rt_uint32_t i = 0; i < readSize; i++)
  90. {
  91. if (readBuf[i] != uart_write_buffer[i])
  92. {
  93. LOG_E("index: %d, Read Different data -> former data: %x, current data: %x.", i, uart_write_buffer[i], readBuf[i]);
  94. return -RT_ERROR;
  95. }
  96. }
  97. }
  98. LOG_I("flush rx send_size [%4d]", send_size);
  99. return RT_EOK;
  100. }
  101. static rt_bool_t uart_api()
  102. {
  103. rt_err_t result = RT_EOK;
  104. result = uart_find();
  105. if (result != RT_EOK)
  106. {
  107. return RT_FALSE;
  108. }
  109. /* Reinitialize */
  110. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  111. config.baud_rate = BAUD_RATE_115200;
  112. config.rx_bufsz = RT_SERIAL_TC_RXBUF_SIZE;
  113. config.tx_bufsz = RT_SERIAL_TC_TXBUF_SIZE;
  114. #ifdef RT_SERIAL_USING_DMA
  115. config.dma_ping_bufsz = RT_SERIAL_TC_RXBUF_SIZE / 2;
  116. #endif
  117. rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
  118. result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_NON_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. rt_uint8_t *uart_write_buffer;
  125. rt_uint32_t i;
  126. uart_write_buffer = (rt_uint8_t *)rt_malloc(RT_SERIAL_TC_RXBUF_SIZE * 5 + 1);
  127. for (rt_uint32_t count = 0; count < (RT_SERIAL_TC_RXBUF_SIZE * 5 + 1); count++)
  128. {
  129. uart_write_buffer[count] = count;
  130. }
  131. srand(rt_tick_get());
  132. for (i = 0; i < RT_SERIAL_TC_SEND_ITERATIONS; i++)
  133. {
  134. if (RT_EOK != test_item(uart_write_buffer, RT_SERIAL_TC_RXBUF_SIZE + RT_SERIAL_TC_RXBUF_SIZE * (rand() % 5)))
  135. {
  136. LOG_E("test_item failed.");
  137. result = -RT_ERROR;
  138. goto __exit;
  139. }
  140. if (RT_EOK != test_item(uart_write_buffer, rand() % (RT_SERIAL_TC_RXBUF_SIZE * 5)))
  141. {
  142. LOG_E("test_item failed.");
  143. result = -RT_ERROR;
  144. goto __exit;
  145. }
  146. }
  147. __exit:
  148. rt_free(uart_write_buffer);
  149. rt_device_close(&serial->parent);
  150. rt_thread_mdelay(5);
  151. return result == RT_EOK ? RT_TRUE : RT_FALSE;
  152. }
  153. static void tc_uart_api(void)
  154. {
  155. uassert_true(uart_api() == RT_TRUE);
  156. }
  157. static rt_err_t utest_tc_init(void)
  158. {
  159. LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
  160. return RT_EOK;
  161. }
  162. static rt_err_t utest_tc_cleanup(void)
  163. {
  164. rt_device_t uart_dev = rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
  165. while (rt_device_close(uart_dev) != -RT_ERROR);
  166. return RT_EOK;
  167. }
  168. static void testcase(void)
  169. {
  170. UTEST_UNIT_RUN(tc_uart_api);
  171. }
  172. UTEST_TC_EXPORT(testcase, "components.drivers.serial.v2.uart_flush_rx", utest_tc_init, utest_tc_cleanup, 30);
  173. #endif /* TC_UART_USING_TC */