uart_timeout_rxb_txb.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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 Blocking Timeout RX/TX Test
  12. *
  13. * Test Objectives:
  14. * - Validate combined blocking receive/transmit timeout behavior for the serial v2 driver
  15. * - Verify APIs: rt_device_find, rt_device_control(RT_SERIAL_CTRL_SET_RX_TIMEOUT / _SET_TX_TIMEOUT / _RX_FLUSH / _TX_FLUSH),
  16. * rt_device_open with RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING, rt_device_read, rt_device_write
  17. *
  18. * Test Scenarios:
  19. * - **Scenario 1 (Timeout Verification / tc_uart_api):**
  20. * 1. Discover and reconfigure the target UART with loopback (TX shorted to RX) and known buffer sizes.
  21. * 2. Spawn concurrent TX and RX worker threads; RX thread configures 100-tick blocking timeout and repeatedly validates measured wait time.
  22. * 3. Switch to TX timeout mode (10 ticks) and push oversized bursts to ensure write calls block for the configured window.
  23. * 4. Monitor status flags to detect allocation failures, timeout violations, or thread termination.
  24. *
  25. * Verification Metrics:
  26. * - RX blocking reads must complete within [100, 101] ticks and return expected lengths across 10 iterations.
  27. * - TX blocking writes must complete within [10, 11] ticks with successful flush between iterations.
  28. * - No allocation or control failures occur; master loop exits with `uart_over_flag == RT_TRUE`.
  29. *
  30. * Dependencies:
  31. * - Requires `RT_UTEST_SERIAL_V2` enabled and a loopbacked UART defined by `RT_SERIAL_TC_DEVICE_NAME`.
  32. * - Serial driver must support blocking mode and timeout controls; optional RX DMA segment size is set via `RT_SERIAL_USING_DMA`.
  33. * - Two 2 KB threads plus dynamic buffers (~RT_SERIAL_TC_RXBUF_SIZE*10) must be allocatable from the heap.
  34. *
  35. * Expected Results:
  36. * - Test completes without assertions, device handles close cleanly, logs show timeout measurements within tolerance.
  37. * - Utest harness prints `[ PASSED ] [ result ] testcase (components.drivers.serial.v2.uart_timeout_rxb_txb)`.
  38. */
  39. #include <rtthread.h>
  40. #include "utest.h"
  41. #include <rtdevice.h>
  42. #include <stdlib.h>
  43. /* */
  44. #ifdef RT_UTEST_SERIAL_V2
  45. static struct rt_serial_device *serial;
  46. static rt_bool_t uart_result = RT_TRUE;
  47. static rt_uint8_t uart_write_flag = RT_TRUE;
  48. static rt_uint8_t uart_over_flag = RT_FALSE;
  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 = RT_NULL;
  62. rt_uint32_t i = 0;
  63. /* assign send buffer */
  64. uart_write_buffer = (rt_uint8_t *)rt_malloc(RT_SERIAL_TC_RXBUF_SIZE);
  65. if (uart_write_buffer == RT_NULL)
  66. {
  67. LOG_E("Without spare memory for uart dma!");
  68. uart_result = RT_FALSE;
  69. return;
  70. }
  71. for (i = 0; i < RT_SERIAL_TC_RXBUF_SIZE; i++)
  72. {
  73. uart_write_buffer[i] = (rt_uint8_t)i;
  74. }
  75. while (1)
  76. {
  77. if (uart_write_flag == RT_FALSE)
  78. break;
  79. rt_device_write(&serial->parent, 0, uart_write_buffer, RT_SERIAL_TC_RXBUF_SIZE / 3);
  80. rt_thread_mdelay(40);
  81. }
  82. rt_free(uart_write_buffer);
  83. }
  84. static void uart_rec_entry(void *parameter)
  85. {
  86. rt_uint8_t *uart_write_buffer;
  87. rt_tick_t old_tick;
  88. rt_tick_t tick_diff;
  89. rt_ssize_t recv_len;
  90. rt_uint32_t i;
  91. rt_int32_t timeout = 0;
  92. uart_write_buffer = (rt_uint8_t *)rt_malloc(RT_SERIAL_TC_RXBUF_SIZE * 10 + 1);
  93. timeout = 100;
  94. rt_device_control(&serial->parent, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void *)&timeout);
  95. uart_write_flag = RT_TRUE;
  96. for (i = 0; i < 10; i++)
  97. {
  98. rt_device_control(&serial->parent, RT_SERIAL_CTRL_RX_FLUSH, RT_NULL);
  99. old_tick = rt_tick_get();
  100. recv_len = rt_device_read(&serial->parent, 0, (void *)uart_write_buffer, RT_SERIAL_TC_RXBUF_SIZE);
  101. tick_diff = rt_tick_get() - old_tick;
  102. if (tick_diff > 100 + 1 || tick_diff < 100)
  103. {
  104. LOG_E("timeout_test: recv_size [%d], RX block time [%d], expect_time [100 - 101]", recv_len, tick_diff);
  105. uart_write_flag = RT_FALSE;
  106. uart_result = RT_FALSE;
  107. rt_free(uart_write_buffer);
  108. rt_thread_mdelay(60);
  109. return;
  110. }
  111. LOG_I("timeout_test: RX block time [%d], expect_time [100 - 101]", tick_diff);
  112. }
  113. uart_write_flag = RT_FALSE;
  114. rt_thread_mdelay(60);
  115. timeout = 10;
  116. rt_device_control(&serial->parent, RT_SERIAL_CTRL_SET_TX_TIMEOUT, (void *)&timeout);
  117. for (i = 0; i < 10; i++)
  118. {
  119. old_tick = rt_tick_get();
  120. recv_len = rt_device_write(&serial->parent, 0, uart_write_buffer, RT_SERIAL_TC_RXBUF_SIZE * 10);
  121. tick_diff = rt_tick_get() - old_tick;
  122. if (tick_diff > 10 + 1 || tick_diff < 10)
  123. {
  124. LOG_E("timeout_test: recv_size [%d], TX block time [%d], expect_time [10 - 11]", recv_len, tick_diff);
  125. uart_result = RT_FALSE;
  126. rt_free(uart_write_buffer);
  127. return;
  128. }
  129. LOG_I("timeout_test: TX block time [%d], expect_time [10 - 11]", tick_diff);
  130. rt_device_control(&serial->parent, RT_SERIAL_CTRL_TX_FLUSH, RT_NULL);
  131. }
  132. rt_free(uart_write_buffer);
  133. uart_over_flag = RT_TRUE;
  134. }
  135. static rt_bool_t uart_api()
  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. result = uart_find();
  141. if (result != RT_EOK)
  142. {
  143. return RT_FALSE;
  144. }
  145. /* Reinitialize */
  146. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  147. config.baud_rate = BAUD_RATE_115200;
  148. config.rx_bufsz = RT_SERIAL_TC_RXBUF_SIZE;
  149. config.tx_bufsz = RT_SERIAL_TC_TXBUF_SIZE;
  150. #ifdef RT_SERIAL_USING_DMA
  151. config.dma_ping_bufsz = RT_SERIAL_TC_RXBUF_SIZE / 2;
  152. #endif
  153. rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
  154. result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
  155. if (result != RT_EOK)
  156. {
  157. LOG_E("Open uart device failed.");
  158. return RT_FALSE;
  159. }
  160. thread_send = rt_thread_create("uart_send", uart_send_entry, NULL, 2048, RT_THREAD_PRIORITY_MAX - 4, 10);
  161. thread_recv = rt_thread_create("uart_recv", uart_rec_entry, NULL, 2048, RT_THREAD_PRIORITY_MAX - 5, 10);
  162. if ((thread_send != RT_NULL) && (thread_recv != RT_NULL))
  163. {
  164. rt_thread_startup(thread_send);
  165. rt_thread_startup(thread_recv);
  166. }
  167. else
  168. {
  169. result = -RT_ERROR;
  170. goto __exit;
  171. }
  172. while (1)
  173. {
  174. if (uart_result != RT_TRUE)
  175. {
  176. LOG_E("The test for uart dma is failure.");
  177. result = -RT_ERROR;
  178. goto __exit;
  179. }
  180. if (uart_over_flag == RT_TRUE)
  181. {
  182. goto __exit;
  183. }
  184. /* waiting for test over */
  185. rt_thread_mdelay(5);
  186. }
  187. __exit:
  188. rt_device_close(&serial->parent);
  189. rt_thread_mdelay(5);
  190. return result == RT_EOK ? RT_TRUE : RT_FALSE;
  191. }
  192. static void tc_uart_api(void)
  193. {
  194. uassert_true(uart_api() == RT_TRUE);
  195. }
  196. static rt_err_t utest_tc_init(void)
  197. {
  198. return RT_EOK;
  199. }
  200. static rt_err_t utest_tc_cleanup(void)
  201. {
  202. uart_result = RT_TRUE;
  203. uart_write_flag = RT_TRUE;
  204. uart_over_flag = RT_FALSE;
  205. rt_device_t uart_dev = rt_device_find(RT_SERIAL_TC_DEVICE_NAME);
  206. while (rt_device_close(uart_dev) != -RT_ERROR);
  207. return RT_EOK;
  208. }
  209. static void testcase(void)
  210. {
  211. UTEST_UNIT_RUN(tc_uart_api);
  212. }
  213. UTEST_TC_EXPORT(testcase, "components.drivers.serial.v2.uart_timeout_rxb_txb", utest_tc_init, utest_tc_cleanup, 30);
  214. #endif /* TC_UART_USING_TC */