drv_soft_i2c.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-05-31 ZYH first version
  9. * 2018-12-10 Zohar_Lee format file
  10. * 2020-07-10 lik rewrite
  11. */
  12. #include "drv_soft_i2c.h"
  13. #ifdef RT_USING_I2C
  14. #ifdef BSP_USING_I2C
  15. /***************************************************************
  16. *!!!!!!!!!!!!!!!!!!!!!!!!!!!!NOTICE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  17. *In order to use swm drv_soft_i2c,you need to commented out
  18. line 114 (SDA_H(ops);) and line 167 (SDA_H(ops);) in i2c-bit-ops.c
  19. At the same time, add one line (SDA_L(ops);)after line 154 (SCL_L(ops);)
  20. in i2c-bit-ops.c
  21. ***************************************************************/
  22. //#define DRV_DEBUG
  23. #define LOG_TAG "drv.i2c"
  24. #include <drv_log.h>
  25. #if !defined(BSP_USING_I2C0) && !defined(BSP_USING_I2C1)
  26. #error "Please define at least one BSP_USING_I2Cx"
  27. /* this driver can be disabled at menuconfig ? RT-Thread Components ? Device Drivers */
  28. #endif
  29. #ifdef BSP_USING_I2C0
  30. #define I2C0_BUS_CFG \
  31. { \
  32. .scl = BSP_I2C0_SCL_PIN, \
  33. .sda = BSP_I2C0_SDA_PIN, \
  34. .name = "i2c0", \
  35. }
  36. #endif
  37. #ifdef BSP_USING_I2C1
  38. #define I2C1_BUS_CFG \
  39. { \
  40. .scl = BSP_I2C1_SCL_PIN, \
  41. .sda = BSP_I2C1_SDA_PIN, \
  42. .name = "i2c1", \
  43. }
  44. #endif
  45. /* swm config class */
  46. struct swm_soft_i2c_cfg
  47. {
  48. rt_uint8_t scl;
  49. rt_uint8_t sda;
  50. const char *name;
  51. };
  52. /* swm i2c dirver class */
  53. struct swm_soft_i2c_device
  54. {
  55. struct rt_i2c_bit_ops ops;
  56. struct rt_i2c_bus_device i2c_bus;
  57. };
  58. static const struct swm_soft_i2c_cfg swm_soft_i2c_cfg[] =
  59. {
  60. #ifdef BSP_USING_I2C0
  61. I2C0_BUS_CFG,
  62. #endif
  63. #ifdef BSP_USING_I2C1
  64. I2C1_BUS_CFG,
  65. #endif
  66. };
  67. static struct swm_soft_i2c_device i2c_obj[sizeof(swm_soft_i2c_cfg) / sizeof(swm_soft_i2c_cfg[0])];
  68. /**
  69. * This function initializes the i2c pin.
  70. *
  71. * @param swm i2c dirver class.
  72. */
  73. static void swm_i2c_gpio_init(struct swm_soft_i2c_device *i2c)
  74. {
  75. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)i2c->ops.data;
  76. rt_pin_mode(soft_i2c_cfg->scl, PIN_MODE_OUTPUT_OD);
  77. rt_pin_mode(soft_i2c_cfg->sda, PIN_MODE_OUTPUT_OD);
  78. rt_pin_write(soft_i2c_cfg->scl, PIN_HIGH);
  79. rt_pin_write(soft_i2c_cfg->sda, PIN_HIGH);
  80. }
  81. /**
  82. * This function sets the sda pin.
  83. *
  84. * @param swm config class.
  85. * @param The sda pin state.
  86. */
  87. static void swm_i2c_set_sda(void *data, rt_int32_t state)
  88. {
  89. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)data;
  90. rt_pin_mode(soft_i2c_cfg->sda, PIN_MODE_OUTPUT_OD);
  91. if (state)
  92. {
  93. rt_pin_write(soft_i2c_cfg->sda, PIN_HIGH);
  94. }
  95. else
  96. {
  97. rt_pin_write(soft_i2c_cfg->sda, PIN_LOW);
  98. }
  99. }
  100. /**
  101. * This function sets the scl pin.
  102. *
  103. * @param swm config class.
  104. * @param The scl pin state.
  105. */
  106. static void swm_i2c_set_scl(void *data, rt_int32_t state)
  107. {
  108. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)data;
  109. rt_pin_mode(soft_i2c_cfg->scl, PIN_MODE_OUTPUT_OD);
  110. if (state)
  111. {
  112. rt_pin_write(soft_i2c_cfg->scl, PIN_HIGH);
  113. }
  114. else
  115. {
  116. rt_pin_write(soft_i2c_cfg->scl, PIN_LOW);
  117. }
  118. }
  119. /**
  120. * This function gets the sda pin state.
  121. *
  122. * @param The sda pin state.
  123. */
  124. static rt_int32_t swm_i2c_get_sda(void *data)
  125. {
  126. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)data;
  127. rt_pin_mode(soft_i2c_cfg->sda, PIN_MODE_INPUT_PULLUP);
  128. return rt_pin_read(soft_i2c_cfg->sda);
  129. }
  130. /**
  131. * This function gets the scl pin state.
  132. *
  133. * @param The scl pin state.
  134. */
  135. static rt_int32_t swm_i2c_get_scl(void *data)
  136. {
  137. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)data;
  138. rt_pin_mode(soft_i2c_cfg->scl, PIN_MODE_INPUT_PULLUP);
  139. return rt_pin_read(soft_i2c_cfg->scl);
  140. }
  141. /**
  142. * The time delay function.
  143. *
  144. * @param microseconds.
  145. */
  146. static void swm_i2c_udelay(rt_uint32_t us)
  147. {
  148. rt_uint32_t ticks;
  149. rt_uint32_t told, tnow, tcnt = 0;
  150. rt_uint32_t reload = SysTick->LOAD;
  151. ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
  152. told = SysTick->VAL;
  153. while (1)
  154. {
  155. tnow = SysTick->VAL;
  156. if (tnow != told)
  157. {
  158. if (tnow < told)
  159. {
  160. tcnt += told - tnow;
  161. }
  162. else
  163. {
  164. tcnt += reload - tnow + told;
  165. }
  166. told = tnow;
  167. if (tcnt >= ticks)
  168. {
  169. break;
  170. }
  171. }
  172. }
  173. }
  174. static const struct rt_i2c_bit_ops swm_i2c_bit_ops =
  175. {
  176. .data = RT_NULL,
  177. .set_sda = swm_i2c_set_sda,
  178. .set_scl = swm_i2c_set_scl,
  179. .get_sda = swm_i2c_get_sda,
  180. .get_scl = swm_i2c_get_scl,
  181. .udelay = swm_i2c_udelay,
  182. .delay_us = 1,
  183. .timeout = 100};
  184. /* I2C initialization function */
  185. int swm_i2c_init(void)
  186. {
  187. rt_err_t result;
  188. for (int i = 0; i < sizeof(i2c_obj) / sizeof(struct swm_soft_i2c_device); i++)
  189. {
  190. i2c_obj[i].ops = swm_i2c_bit_ops;
  191. i2c_obj[i].ops.data = (void *)&swm_soft_i2c_cfg[i];
  192. i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops;
  193. swm_i2c_gpio_init(&i2c_obj[i]);
  194. result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, swm_soft_i2c_cfg[i].name);
  195. RT_ASSERT(result == RT_EOK);
  196. LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
  197. swm_soft_i2c_cfg[i].name,
  198. swm_soft_i2c_cfg[i].scl,
  199. swm_soft_i2c_cfg[i].sda);
  200. }
  201. return RT_EOK;
  202. }
  203. INIT_DEVICE_EXPORT(swm_i2c_init);
  204. #endif /* BSP_USING_I2C */
  205. #endif /* RT_USING_I2C */