test_can.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (c) 2006-2026, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2026-04-20 rcitach first version
  9. */
  10. #include <rtdevice.h>
  11. #include <utest.h>
  12. /*
  13. * S100 CAN utest 说明
  14. *
  15. * 1. 本测试面向当前 rdk/s100 BSP 的 RT-Thread CAN 设备驱动,覆盖设备发现、
  16. * open、配置、模式切换、发送、接收、状态读取和 close 的基础路径。
  17. * 2. 为避免依赖外部 CAN 对端,本测试使用驱动支持的 RT_CAN_MODE_LOOPBACK 内部回环模式。
  18. * 因此测试默认不要求外部收发器回环或两节点组网。
  19. * 3. 测试对象仅包含当前配置中启用的 can5/can6/can7/can8/can9。
  20. * 4. 发送内容使用一帧标准数据帧(11-bit ID,8 字节 payload),接收后逐字段校验:
  21. * - IDE/RTR
  22. * - 标准 ID
  23. * - DLC
  24. * - data[0..7]
  25. * 5. 若需要改成外部总线联调,请把 loopback 模式切回 normal,并去掉本用例的回环假设。
  26. */
  27. static const struct rt_can_msg s100_can_test_msg =
  28. {
  29. .id = 0x123,
  30. .ide = RT_CAN_STDID,
  31. .rtr = RT_CAN_DTR,
  32. .len = 8,
  33. .priv = 0,
  34. .hdr_index = -1,
  35. .rxfifo = 0,
  36. .reserved = 0,
  37. .nonblocking = 0,
  38. .data = {0x55, 0xAA, 0x00, 0xFF, 0x11, 0x22, 0x33, 0x44},
  39. };
  40. struct s100_can_test_port
  41. {
  42. const char *name;
  43. };
  44. #if defined(BSP_USING_CAN5) || defined(BSP_USING_CAN6) || defined(BSP_USING_CAN7) || defined(BSP_USING_CAN8) || defined(BSP_USING_CAN9)
  45. static const struct s100_can_test_port s100_can_test_ports[] =
  46. {
  47. #ifdef BSP_USING_CAN5
  48. { "can5" },
  49. #endif
  50. #ifdef BSP_USING_CAN6
  51. { "can6" },
  52. #endif
  53. #ifdef BSP_USING_CAN7
  54. { "can7" },
  55. #endif
  56. #ifdef BSP_USING_CAN8
  57. { "can8" },
  58. #endif
  59. #ifdef BSP_USING_CAN9
  60. { "can9" },
  61. #endif
  62. };
  63. #define S100_CAN_TEST_PORT_COUNT \
  64. (sizeof(s100_can_test_ports) / sizeof(s100_can_test_ports[0]))
  65. #else
  66. static const struct s100_can_test_port s100_can_test_ports[] =
  67. {
  68. { RT_NULL },
  69. };
  70. #define S100_CAN_TEST_PORT_COUNT 0u
  71. #endif
  72. static void s100_can_prepare_config(struct can_configure *cfg)
  73. {
  74. RT_ASSERT(cfg != RT_NULL);
  75. cfg->baud_rate = CAN1MBaud;
  76. cfg->mode = RT_CAN_MODE_LOOPBACK;
  77. cfg->privmode = RT_CAN_MODE_NOPRIV;
  78. }
  79. static void s100_can_check_port_basic(const char *name)
  80. {
  81. rt_device_t can_dev;
  82. struct can_configure cfg = CANDEFAULTCONFIG;
  83. struct rt_can_status status;
  84. rt_err_t ret;
  85. can_dev = rt_device_find(name);
  86. uassert_not_null(can_dev);
  87. s100_can_prepare_config(&cfg);
  88. ret = rt_device_control(can_dev, RT_DEVICE_CTRL_CONFIG, &cfg);
  89. uassert_int_equal(ret, RT_EOK);
  90. ret = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX);
  91. uassert_int_equal(ret, RT_EOK);
  92. ret = rt_device_control(can_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_LOOPBACK);
  93. uassert_int_equal(ret, RT_EOK);
  94. ret = rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN1MBaud);
  95. uassert_int_equal(ret, RT_EOK);
  96. ret = rt_device_control(can_dev, RT_CAN_CMD_GET_STATUS, &status);
  97. uassert_int_equal(ret, RT_EOK);
  98. ret = rt_device_close(can_dev);
  99. uassert_int_equal(ret, RT_EOK);
  100. }
  101. static void s100_can_check_port_loopback(const char *name)
  102. {
  103. rt_device_t can_dev;
  104. struct can_configure cfg = CANDEFAULTCONFIG;
  105. struct rt_can_msg rx_msg;
  106. rt_err_t ret;
  107. rt_ssize_t wr_len;
  108. rt_ssize_t rd_len;
  109. rt_size_t i;
  110. can_dev = rt_device_find(name);
  111. uassert_not_null(can_dev);
  112. s100_can_prepare_config(&cfg);
  113. ret = rt_device_control(can_dev, RT_DEVICE_CTRL_CONFIG, &cfg);
  114. uassert_int_equal(ret, RT_EOK);
  115. ret = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX);
  116. uassert_int_equal(ret, RT_EOK);
  117. ret = rt_device_control(can_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_LOOPBACK);
  118. uassert_int_equal(ret, RT_EOK);
  119. ret = rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN1MBaud);
  120. uassert_int_equal(ret, RT_EOK);
  121. rt_memset(&rx_msg, 0, sizeof(rx_msg));
  122. rt_kprintf("%s tx can id=0x%03X len=%d\n", name, (unsigned int)s100_can_test_msg.id, (int)s100_can_test_msg.len);
  123. LOG_HEX("can.tx", 16, s100_can_test_msg.data, s100_can_test_msg.len);
  124. wr_len = rt_device_write(can_dev, 0, &s100_can_test_msg, sizeof(s100_can_test_msg));
  125. uassert_int_equal((int)wr_len, (int)sizeof(s100_can_test_msg));
  126. rd_len = rt_device_read(can_dev, 0, &rx_msg, sizeof(rx_msg));
  127. uassert_int_equal((int)rd_len, (int)sizeof(rx_msg));
  128. rt_kprintf("%s rx can id=0x%03X len=%d\n", name, (unsigned int)rx_msg.id, (int)rx_msg.len);
  129. LOG_HEX("can.rx", 16, rx_msg.data, rx_msg.len);
  130. uassert_int_equal((int)rx_msg.ide, (int)s100_can_test_msg.ide);
  131. uassert_int_equal((int)rx_msg.rtr, (int)s100_can_test_msg.rtr);
  132. uassert_int_equal((int)rx_msg.id, (int)s100_can_test_msg.id);
  133. uassert_int_equal((int)rx_msg.len, (int)s100_can_test_msg.len);
  134. for (i = 0; i < s100_can_test_msg.len; i++)
  135. {
  136. rt_kprintf("%s compare[%d]: tx=0x%02X rx=0x%02X\n",
  137. name,
  138. (int)i,
  139. s100_can_test_msg.data[i],
  140. rx_msg.data[i]);
  141. uassert_int_equal((int)rx_msg.data[i], (int)s100_can_test_msg.data[i]);
  142. }
  143. ret = rt_device_close(can_dev);
  144. uassert_int_equal(ret, RT_EOK);
  145. }
  146. static void can_basic_demo(void)
  147. {
  148. rt_size_t i;
  149. if (S100_CAN_TEST_PORT_COUNT == 0)
  150. {
  151. return;
  152. }
  153. for (i = 0; i < S100_CAN_TEST_PORT_COUNT; i++)
  154. {
  155. s100_can_check_port_basic(s100_can_test_ports[i].name);
  156. }
  157. }
  158. static void can_loopback_demo(void)
  159. {
  160. rt_size_t i;
  161. if (S100_CAN_TEST_PORT_COUNT == 0)
  162. {
  163. return;
  164. }
  165. for (i = 0; i < S100_CAN_TEST_PORT_COUNT; i++)
  166. {
  167. s100_can_check_port_loopback(s100_can_test_ports[i].name);
  168. }
  169. }
  170. static void can_testcase(void)
  171. {
  172. UTEST_UNIT_RUN(can_basic_demo);
  173. UTEST_UNIT_RUN(can_loopback_demo);
  174. }
  175. static rt_err_t utest_tc_init(void)
  176. {
  177. return RT_EOK;
  178. }
  179. static rt_err_t utest_tc_cleanup(void)
  180. {
  181. return RT_EOK;
  182. }
  183. UTEST_TC_EXPORT(can_testcase, "rdk.s100.drivers.can", utest_tc_init, utest_tc_cleanup, 20);