drv_soft_i2c.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (c) 2006-2018, 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. static const struct swm_soft_i2c_cfg soft_i2c_cfg[] =
  30. {
  31. #ifdef BSP_USING_I2C0
  32. I2C0_BUS_CFG,
  33. #endif
  34. #ifdef BSP_USING_I2C1
  35. I2C1_BUS_CFG,
  36. #endif
  37. };
  38. static struct swm_i2c i2c_drv[sizeof(soft_i2c_cfg) / sizeof(soft_i2c_cfg[0])];
  39. /**
  40. * This function initializes the i2c pin.
  41. *
  42. * @param swm i2c dirver class.
  43. */
  44. static void swm_i2c_gpio_init(struct swm_i2c *i2c)
  45. {
  46. struct swm_soft_i2c_cfg *cfg = (struct swm_soft_i2c_cfg *)i2c->ops.data;
  47. rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
  48. rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
  49. rt_pin_write(cfg->scl, PIN_HIGH);
  50. rt_pin_write(cfg->sda, PIN_HIGH);
  51. }
  52. /**
  53. * This function sets the sda pin.
  54. *
  55. * @param swm config class.
  56. * @param The sda pin state.
  57. */
  58. static void swm_set_sda(void *data, rt_int32_t state)
  59. {
  60. struct swm_soft_i2c_cfg *cfg = (struct swm_soft_i2c_cfg *)data;
  61. rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
  62. if (state)
  63. {
  64. rt_pin_write(cfg->sda, PIN_HIGH);
  65. }
  66. else
  67. {
  68. rt_pin_write(cfg->sda, PIN_LOW);
  69. }
  70. }
  71. /**
  72. * This function sets the scl pin.
  73. *
  74. * @param swm config class.
  75. * @param The scl pin state.
  76. */
  77. static void swm_set_scl(void *data, rt_int32_t state)
  78. {
  79. struct swm_soft_i2c_cfg *cfg = (struct swm_soft_i2c_cfg *)data;
  80. rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
  81. if (state)
  82. {
  83. rt_pin_write(cfg->scl, PIN_HIGH);
  84. }
  85. else
  86. {
  87. rt_pin_write(cfg->scl, PIN_LOW);
  88. }
  89. }
  90. /**
  91. * This function gets the sda pin state.
  92. *
  93. * @param The sda pin state.
  94. */
  95. static rt_int32_t swm_get_sda(void *data)
  96. {
  97. struct swm_soft_i2c_cfg *cfg = (struct swm_soft_i2c_cfg *)data;
  98. rt_pin_mode(cfg->sda, PIN_MODE_INPUT_PULLUP);
  99. return rt_pin_read(cfg->sda);
  100. }
  101. /**
  102. * This function gets the scl pin state.
  103. *
  104. * @param The scl pin state.
  105. */
  106. static rt_int32_t swm_get_scl(void *data)
  107. {
  108. struct swm_soft_i2c_cfg *cfg = (struct swm_soft_i2c_cfg *)data;
  109. rt_pin_mode(cfg->scl, PIN_MODE_INPUT_PULLUP);
  110. return rt_pin_read(cfg->scl);
  111. }
  112. /**
  113. * The time delay function.
  114. *
  115. * @param microseconds.
  116. */
  117. static void swm_udelay(rt_uint32_t us)
  118. {
  119. rt_uint32_t ticks;
  120. rt_uint32_t told, tnow, tcnt = 0;
  121. rt_uint32_t reload = SysTick->LOAD;
  122. ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
  123. told = SysTick->VAL;
  124. while (1)
  125. {
  126. tnow = SysTick->VAL;
  127. if (tnow != told)
  128. {
  129. if (tnow < told)
  130. {
  131. tcnt += told - tnow;
  132. }
  133. else
  134. {
  135. tcnt += reload - tnow + told;
  136. }
  137. told = tnow;
  138. if (tcnt >= ticks)
  139. {
  140. break;
  141. }
  142. }
  143. }
  144. }
  145. static const struct rt_i2c_bit_ops swm_bit_ops =
  146. {
  147. .data = RT_NULL,
  148. .set_sda = swm_set_sda,
  149. .set_scl = swm_set_scl,
  150. .get_sda = swm_get_sda,
  151. .get_scl = swm_get_scl,
  152. .udelay = swm_udelay,
  153. .delay_us = 1,
  154. .timeout = 100};
  155. /* I2C initialization function */
  156. int rt_hw_i2c_init(void)
  157. {
  158. rt_err_t result;
  159. for (int i = 0; i < sizeof(i2c_drv) / sizeof(struct swm_i2c); i++)
  160. {
  161. i2c_drv[i].ops = swm_bit_ops;
  162. i2c_drv[i].ops.data = (void *)&soft_i2c_cfg[i];
  163. i2c_drv[i].i2c2_bus.priv = &i2c_drv[i].ops;
  164. swm_i2c_gpio_init(&i2c_drv[i]);
  165. result = rt_i2c_bit_add_bus(&i2c_drv[i].i2c2_bus, soft_i2c_cfg[i].name);
  166. RT_ASSERT(result == RT_EOK);
  167. LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
  168. soft_i2c_cfg[i].name,
  169. soft_i2c_cfg[i].scl,
  170. soft_i2c_cfg[i].sda);
  171. }
  172. return RT_EOK;
  173. }
  174. INIT_DEVICE_EXPORT(rt_hw_i2c_init);
  175. #endif /* BSP_USING_I2C */
  176. #endif /* RT_USING_I2C */