test_i2c.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are met:
  5. * 1. Redistributions of source code must retain the above copyright
  6. * notice, this list of conditions and the following disclaimer.
  7. * 2. Redistributions in binary form must reproduce the above copyright
  8. * notice, this list of conditions and the following disclaimer in the
  9. * documentation and/or other materials provided with the distribution.
  10. *
  11. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  12. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  13. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  16. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  17. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  18. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  19. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  21. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  22. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. /*
  26. * Copyright (c) 2006-2025 RT-Thread Development Team
  27. *
  28. * SPDX-License-Identifier: Apache-2.0
  29. */
  30. #include <rtthread.h>
  31. #include <rtdevice.h>
  32. #include <utest.h>
  33. #include <string.h>
  34. #include "drv_i2c.h"
  35. #include "drv_pinctrl.h"
  36. #include "drv_gpio.h"
  37. /*
  38. * 测试K230 I2C的主从机通信,在这里采用I2C0作为测试对象
  39. *
  40. * 硬件平台:
  41. * 测试的硬件平台为庐山派开发板,使用的I2C0引脚是GPIO048(SCL)
  42. * 和GPIO049(SDA)。
  43. *
  44. * 测试说明:
  45. * 1. 测试I2C0主机模式
  46. * 主机模式下,主机向从机发送16字节数据(不包括写读地址),
  47. * 然后再读取回来进行校验,共执行两次,分别是400kHz和1MHz速率。
  48. * 第一次写数据时,带一字节地址,总共写16字节数据,读取15字节数据,
  49. * 第二次写数据时,带一字节地址,总共写17字节数据,读取16字节数据。
  50. * 在两次写数据的过程中,如果开启dma功能,第一次会调用dma进行写,
  51. * 第二次会调用dma进行读。(前提是BSP_USING_I2C_DMA宏被定义,
  52. * 因为pdma要求地址与数据都要4字节对齐(地址的对齐问题会在驱动
  53. * 内部处理),若写/读数据大小非4字节对齐,即使启用了dma功能,
  54. * 实际也是调用的cpu轮询读写,这一点需要应用程序注意并处理)
  55. * 注:使用的从机为AT24C08 EEPROM,设备地址为0x50,
  56. * page size 为 16 字节。
  57. */
  58. #define I2C_NAME "i2c0"
  59. #define TARGET_ADDR 0x50
  60. #define TEST_BUFFER_SIZE 16
  61. #define I2C_SCL_PIN 48
  62. #define I2C_SDA_PIN 49
  63. #define I2C_SCL_PIN_AF IOMUX_FUNC4
  64. #define I2C_SDA_PIN_AF IOMUX_FUNC4
  65. static void test_i2c0_deinit_pin(void)
  66. {
  67. k230_pinctrl_set_function(I2C_SCL_PIN, IOMUX_FUNC1);
  68. k230_pinctrl_set_function(I2C_SDA_PIN, IOMUX_FUNC1);
  69. k230_pinctrl_set_oe(I2C_SCL_PIN, 0);
  70. k230_pinctrl_set_oe(I2C_SDA_PIN, 0);
  71. k230_pinctrl_set_ie(I2C_SCL_PIN, 1);
  72. k230_pinctrl_set_ie(I2C_SDA_PIN, 1);
  73. kd_pin_mode(I2C_SCL_PIN, GPIO_DM_INPUT);
  74. kd_pin_mode(I2C_SDA_PIN, GPIO_DM_INPUT);
  75. }
  76. static void test_i2c0_init_pin(void)
  77. {
  78. k230_pinctrl_set_function(I2C_SCL_PIN, I2C_SCL_PIN_AF); // I2C0_SCL
  79. k230_pinctrl_set_function(I2C_SDA_PIN, I2C_SDA_PIN_AF); // I2C0_SDA
  80. k230_pinctrl_set_oe(I2C_SCL_PIN, 1);
  81. k230_pinctrl_set_oe(I2C_SDA_PIN, 1);
  82. k230_pinctrl_set_ie(I2C_SCL_PIN, 1);
  83. k230_pinctrl_set_ie(I2C_SDA_PIN, 1);
  84. }
  85. static int test_i2c_check_pin(void)
  86. {
  87. test_i2c0_deinit_pin();
  88. if (kd_pin_read(I2C_SCL_PIN) != 1 || kd_pin_read(I2C_SDA_PIN) != 1)
  89. {
  90. LOG_W("i2c bus is not idle, try to recover it.");
  91. k230_pinctrl_set_oe(I2C_SCL_PIN, 1);
  92. kd_pin_mode(I2C_SCL_PIN, GPIO_DM_OUTPUT);
  93. for (rt_uint8_t i = 0; i < 9; i++)
  94. {
  95. kd_pin_write(I2C_SCL_PIN, 0);
  96. rt_hw_us_delay(2);
  97. kd_pin_write(I2C_SCL_PIN, 1);
  98. rt_hw_us_delay(2);
  99. }
  100. k230_pinctrl_set_oe(I2C_SCL_PIN, 0);
  101. kd_pin_mode(I2C_SCL_PIN, GPIO_DM_INPUT);
  102. }
  103. if (kd_pin_read(I2C_SCL_PIN) != 1 || kd_pin_read(I2C_SDA_PIN) != 1)
  104. {
  105. LOG_E("i2c bus recover failed");
  106. return -RT_ERROR;
  107. }
  108. LOG_I("i2c bus(pin: %u, %u) is idle, init i2c bus pin", I2C_SCL_PIN, I2C_SDA_PIN);
  109. test_i2c0_init_pin();
  110. return RT_EOK;
  111. }
  112. static void _test_i2c0_master(rt_uint8_t *buffer_w, rt_uint8_t *buffer_r, rt_uint32_t size, rt_uint32_t speed)
  113. {
  114. rt_err_t ret = RT_EOK;
  115. struct rt_i2c_bus_device *dev;
  116. struct rt_i2c_msg msgs[2];
  117. dev = rt_i2c_bus_device_find(I2C_NAME);
  118. uassert_not_null(dev);
  119. rt_i2c_control(dev, RT_I2C_DEV_CTRL_CLK, (void *)&speed);
  120. msgs[0].addr = TARGET_ADDR;
  121. msgs[0].flags = RT_I2C_WR;
  122. msgs[0].buf = buffer_w;
  123. msgs[0].len = size + 1;
  124. if (rt_i2c_transfer(dev, msgs, 1) != 1)
  125. {
  126. LOG_E("i2c transfer failed");
  127. uassert_true(0);
  128. }
  129. rt_thread_mdelay(10);
  130. msgs[0].addr = TARGET_ADDR;
  131. msgs[0].flags = RT_I2C_WR | RT_I2C_NO_STOP;
  132. msgs[0].buf = &buffer_r[0];
  133. msgs[0].len = 1;
  134. msgs[1].addr = TARGET_ADDR;
  135. msgs[1].flags = RT_I2C_RD | RT_I2C_NO_START;
  136. msgs[1].buf = &buffer_r[1];
  137. msgs[1].len = size;
  138. if (rt_i2c_transfer(dev, msgs, 2) != 2)
  139. {
  140. LOG_E("i2c transfer failed");
  141. uassert_true(0);
  142. }
  143. LOG_I("Read data:\n");
  144. for (rt_uint8_t i = 1; i < size + 1; i++)
  145. {
  146. LOG_I("0x%02X ", buffer_r[i]);
  147. }
  148. uassert_buf_equal(buffer_w + 1, buffer_r + 1, size);
  149. }
  150. static void test_i2c0_master(void)
  151. {
  152. rt_uint8_t buffer_w[TEST_BUFFER_SIZE + 1];
  153. rt_uint8_t buffer_r[TEST_BUFFER_SIZE + 1];
  154. rt_uint32_t size = TEST_BUFFER_SIZE;
  155. rt_uint32_t speed = 400000; // 400kHz
  156. memset(buffer_w + 1, 0xAA, TEST_BUFFER_SIZE);
  157. buffer_w[0] = 0x00; // memory address
  158. memset(buffer_r, 0x00, TEST_BUFFER_SIZE + 1);
  159. /* if BSP_USING_I2C_DMA is enabled, test i2c write with dma */
  160. _test_i2c0_master(buffer_w, buffer_r, size - 1, speed);
  161. speed = 1000000; // 1MHz
  162. memset(buffer_w + 1, 0x55, TEST_BUFFER_SIZE);
  163. buffer_w[0] = 0x00; // memory address
  164. memset(buffer_r, 0x00, TEST_BUFFER_SIZE + 1);
  165. /* if BSP_USING_I2C_DMA is enabled, test i2c read with dma */
  166. _test_i2c0_master(buffer_w, buffer_r, size, speed);
  167. }
  168. static void testcase(void)
  169. {
  170. LOG_I("This is a i2c test case.\n");
  171. UTEST_UNIT_RUN(test_i2c0_master);
  172. }
  173. static rt_err_t utest_tc_init(void)
  174. {
  175. return test_i2c_check_pin();
  176. }
  177. static rt_err_t utest_tc_cleanup(void)
  178. {
  179. LOG_I("i2c bus pin deinit.\n");
  180. test_i2c0_deinit_pin();
  181. return RT_EOK;
  182. }
  183. UTEST_TC_EXPORT(testcase, "bsp.k230.drivers.i2c", utest_tc_init, utest_tc_cleanup, 100);