drv_soft_i2c.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023/04/15 chushicheng first version
  9. */
  10. #include "drv_soft_i2c.h"
  11. #include "bflb_gpio.h"
  12. #include "bflb_common.h"
  13. #ifdef RT_USING_I2C
  14. #define DBG_LEVEL DBG_LOG
  15. #include <rtdbg.h>
  16. #define LOG_TAG "DRV.I2C"
  17. #if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2)
  18. #error "Please define at least one BSP_USING_I2Cx"
  19. /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
  20. #endif
  21. // uart1
  22. #ifdef I2C1_SCL_USING_GPIO0
  23. #define BSP_I2C1_SCL_PIN GPIO_PIN_0
  24. #elif defined(I2C1_SCL_USING_GPIO4)
  25. #define BSP_I2C1_SCL_PIN GPIO_PIN_4
  26. #elif defined(I2C1_SCL_USING_GPIO8)
  27. #define BSP_I2C1_SCL_PIN GPIO_PIN_8
  28. #elif defined(I2C1_SCL_USING_GPIO10)
  29. #define BSP_I2C1_SCL_PIN GPIO_PIN_10
  30. #elif defined(I2C1_SCL_USING_GPIO20)
  31. #define BSP_I2C1_SCL_PIN GPIO_PIN_20
  32. #endif
  33. #ifdef I2C1_SDA_USING_GPIO1
  34. #define BSP_I2C1_SDA_PIN GPIO_PIN_1
  35. #elif defined(I2C1_SDA_USING_GPIO3)
  36. #define BSP_I2C1_SDA_PIN GPIO_PIN_3
  37. #elif defined(I2C1_SDA_USING_GPIO7)
  38. #define BSP_I2C1_SDA_PIN GPIO_PIN_7
  39. #elif defined(I2C1_SDA_USING_GPIO11)
  40. #define BSP_I2C1_SDA_PIN GPIO_PIN_11
  41. #elif defined(I2C1_SDA_USING_GPIO21)
  42. #define BSP_I2C1_SDA_PIN GPIO_PIN_21
  43. #endif
  44. static const struct bl_soft_i2c_config soft_i2c_config[] =
  45. {
  46. #ifdef BSP_USING_I2C1
  47. I2C1_BUS_CONFIG,
  48. #endif
  49. };
  50. static struct bl_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
  51. /**
  52. * This function initializes the i2c pin.
  53. *
  54. * @param bl i2c dirver class.
  55. */
  56. static void bl_i2c_gpio_init(struct bl_i2c *i2c)
  57. {
  58. struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)i2c->ops.data;
  59. rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
  60. rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
  61. rt_pin_write(cfg->scl, PIN_HIGH);
  62. rt_pin_write(cfg->sda, PIN_HIGH);
  63. }
  64. /**
  65. * This function sets the sda pin.
  66. *
  67. * @param bl config class.
  68. * @param The sda pin state.
  69. */
  70. static void bl_set_sda(void *data, rt_int32_t state)
  71. {
  72. struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data;
  73. if (state)
  74. {
  75. rt_pin_write(cfg->sda, PIN_HIGH);
  76. }
  77. else
  78. {
  79. rt_pin_write(cfg->sda, PIN_LOW);
  80. }
  81. }
  82. /**
  83. * This function sets the scl pin.
  84. *
  85. * @param bl config class.
  86. * @param The scl pin state.
  87. */
  88. static void bl_set_scl(void *data, rt_int32_t state)
  89. {
  90. struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data;
  91. if (state)
  92. {
  93. rt_pin_write(cfg->scl, PIN_HIGH);
  94. }
  95. else
  96. {
  97. rt_pin_write(cfg->scl, PIN_LOW);
  98. }
  99. }
  100. /**
  101. * This function gets the sda pin state.
  102. *
  103. * @param The sda pin state.
  104. */
  105. static rt_int32_t bl_get_sda(void *data)
  106. {
  107. struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data;
  108. return rt_pin_read(cfg->sda);
  109. }
  110. /**
  111. * This function gets the scl pin state.
  112. *
  113. * @param The scl pin state.
  114. */
  115. static rt_int32_t bl_get_scl(void *data)
  116. {
  117. struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data;
  118. return rt_pin_read(cfg->scl);
  119. }
  120. /**
  121. * The time delay function.
  122. *
  123. * @param microseconds.
  124. */
  125. static void bl_udelay(rt_uint32_t us)
  126. {
  127. arch_delay_us(us);
  128. }
  129. static const struct rt_i2c_bit_ops bl_bit_ops_default =
  130. {
  131. .data = RT_NULL,
  132. .set_sda = bl_set_sda,
  133. .set_scl = bl_set_scl,
  134. .get_sda = bl_get_sda,
  135. .get_scl = bl_get_scl,
  136. .udelay = bl_udelay,
  137. .delay_us = 1,
  138. .timeout = 100
  139. };
  140. /**
  141. * if i2c is locked, this function will unlock it
  142. *
  143. * @param bl config class
  144. *
  145. * @return RT_EOK indicates successful unlock.
  146. */
  147. static rt_err_t bl_i2c_bus_unlock(const struct bl_soft_i2c_config *cfg)
  148. {
  149. rt_int32_t i = 0;
  150. if (PIN_LOW == rt_pin_read(cfg->sda))
  151. {
  152. while (i++ < 9)
  153. {
  154. rt_pin_write(cfg->scl, PIN_HIGH);
  155. bl_udelay(100);
  156. rt_pin_write(cfg->scl, PIN_LOW);
  157. bl_udelay(100);
  158. }
  159. }
  160. if (PIN_LOW == rt_pin_read(cfg->sda))
  161. {
  162. return -RT_ERROR;
  163. }
  164. return RT_EOK;
  165. }
  166. /* I2C initialization function */
  167. int rt_hw_i2c_init(void)
  168. {
  169. rt_err_t result;
  170. for (rt_size_t i = 0; i < sizeof(i2c_obj) / sizeof(struct bl_i2c); i++)
  171. {
  172. i2c_obj[i].ops = bl_bit_ops_default;
  173. i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
  174. i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
  175. bl_i2c_gpio_init(&i2c_obj[i]);
  176. result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);
  177. RT_ASSERT(result == RT_EOK);
  178. bl_i2c_bus_unlock(&soft_i2c_config[i]);
  179. LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
  180. soft_i2c_config[i].bus_name,
  181. soft_i2c_config[i].scl,
  182. soft_i2c_config[i].sda);
  183. }
  184. return RT_EOK;
  185. }
  186. INIT_BOARD_EXPORT(rt_hw_i2c_init);
  187. #endif /* RT_USING_I2C */