uart_posix_nonblock.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. * 2021-06-16 KyleChan the first version
  9. */
  10. #include <rtthread.h>
  11. #include "utest.h"
  12. #include <rtdevice.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <termios.h>
  17. #include <fcntl.h>
  18. #include <unistd.h>
  19. #ifdef UTEST_SERIAL_TC
  20. static int32_t serial_fd;
  21. static rt_err_t uart_find(void)
  22. {
  23. serial_fd = open(RT_SERIAL_POSIX_TC_DEVICE_NAME, O_RDWR);
  24. if (serial_fd == -1)
  25. {
  26. LOG_E("find %s device failed!\n", RT_SERIAL_TC_DEVICE_NAME);
  27. return -RT_ERROR;
  28. }
  29. return RT_EOK;
  30. }
  31. static rt_err_t configureSerial(int fd, int baud)
  32. {
  33. int32_t result = 0;
  34. struct termios options;
  35. result = tcgetattr(fd, &options); // 获取当前端口的属性
  36. if (result == -1)
  37. return -RT_ERROR;
  38. // 设置波特率
  39. result = cfsetispeed(&options, baud); // 设置输入波特率
  40. if (result == -1)
  41. return -RT_ERROR;
  42. result = cfsetospeed(&options, baud); // 设置输出波特率
  43. if (result == -1)
  44. return -RT_ERROR;
  45. // 设置数据位
  46. options.c_cflag &= ~PARENB; // 清除校验位,无校验
  47. options.c_cflag &= ~CSTOPB; // 仅一个停止位
  48. options.c_cflag &= ~CSIZE; // 清除掩码
  49. options.c_cflag |= CS8; // 8位数据
  50. // 设置无流控
  51. options.c_cflag &= ~CRTSCTS; // 不使用硬件流控制
  52. options.c_iflag &= ~(IXON | IXOFF | IXANY); // 不使用软件流控制
  53. // 使能接收器和发送器
  54. options.c_cflag |= CLOCAL | CREAD;
  55. // 设置行终止符
  56. options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  57. // 应用属性
  58. result = tcsetattr(fd, TCSANOW, &options);
  59. if (result == -1)
  60. return -RT_ERROR;
  61. return RT_EOK;
  62. }
  63. static rt_err_t uart_api()
  64. {
  65. rt_err_t result = RT_EOK;
  66. rt_uint8_t *uart_write_buffer;
  67. rt_int32_t cnt, i, send_size;
  68. int flags = 0;
  69. result = uart_find();
  70. if (result != RT_EOK)
  71. {
  72. return -RT_ERROR;
  73. }
  74. result = configureSerial(serial_fd, B115200);
  75. if (result == -1)
  76. {
  77. goto __exit;
  78. }
  79. flags = fcntl(serial_fd, F_GETFL, 0);
  80. if (flags == -1)
  81. {
  82. goto __exit;
  83. }
  84. result = fcntl(serial_fd, F_SETFL, flags | O_NONBLOCK);
  85. if (result == -1)
  86. {
  87. goto __exit;
  88. }
  89. uart_write_buffer = (rt_uint8_t *)rt_malloc(sizeof(rt_uint8_t) * 100);
  90. for (i = 0; i < RT_SERIAL_TC_SEND_ITERATIONS; i++)
  91. {
  92. send_size = 1;
  93. cnt = write(serial_fd, uart_write_buffer, send_size);
  94. if (cnt != send_size)
  95. {
  96. result = -RT_ERROR;
  97. goto __exit;
  98. }
  99. rt_thread_mdelay(2);
  100. cnt = read(serial_fd, (void *)uart_write_buffer, send_size);
  101. if (cnt != send_size)
  102. {
  103. result = -RT_ERROR;
  104. goto __exit;
  105. }
  106. send_size = rand() % 30 + 1;
  107. cnt = write(serial_fd, uart_write_buffer, send_size);
  108. if (cnt != send_size)
  109. {
  110. LOG_E("uart write failed %d %d", cnt, send_size);
  111. result = -RT_ERROR;
  112. goto __exit;
  113. }
  114. rt_thread_mdelay(send_size * 0.0868 + 5);
  115. cnt = read(serial_fd, (void *)uart_write_buffer, send_size + 1);
  116. if (cnt != send_size)
  117. {
  118. LOG_E("uart read failed %d %d", cnt, send_size);
  119. result = -RT_ERROR;
  120. goto __exit;
  121. }
  122. }
  123. __exit:
  124. rt_thread_mdelay(5);
  125. if (uart_write_buffer)
  126. rt_free(uart_write_buffer);
  127. close(serial_fd);
  128. return result == RT_EOK ? RT_TRUE : RT_FALSE;
  129. }
  130. static void tc_uart_api(void)
  131. {
  132. uassert_true(uart_api() == RT_TRUE);
  133. }
  134. static rt_err_t utest_tc_init(void)
  135. {
  136. LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
  137. return RT_EOK;
  138. }
  139. static rt_err_t utest_tc_cleanup(void)
  140. {
  141. close(serial_fd);
  142. return RT_EOK;
  143. }
  144. static void testcase(void)
  145. {
  146. UTEST_UNIT_RUN(tc_uart_api);
  147. }
  148. UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_posix_nonblock", utest_tc_init, utest_tc_cleanup, 30);
  149. #endif /* TC_UART_USING_TC */