drv_soft_i2c.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. static void swm_i2c_pin_init(void)
  82. {
  83. rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct swm_soft_i2c_device);
  84. for(rt_size_t i = 0; i < obj_num; i++)
  85. {
  86. swm_i2c_gpio_init(&i2c_obj[i]);
  87. }
  88. }
  89. /**
  90. * This function sets the sda pin.
  91. *
  92. * @param swm config class.
  93. * @param The sda pin state.
  94. */
  95. static void swm_i2c_set_sda(void *data, rt_int32_t state)
  96. {
  97. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)data;
  98. rt_pin_mode(soft_i2c_cfg->sda, PIN_MODE_OUTPUT_OD);
  99. if (state)
  100. {
  101. rt_pin_write(soft_i2c_cfg->sda, PIN_HIGH);
  102. }
  103. else
  104. {
  105. rt_pin_write(soft_i2c_cfg->sda, PIN_LOW);
  106. }
  107. }
  108. /**
  109. * This function sets the scl pin.
  110. *
  111. * @param swm config class.
  112. * @param The scl pin state.
  113. */
  114. static void swm_i2c_set_scl(void *data, rt_int32_t state)
  115. {
  116. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)data;
  117. rt_pin_mode(soft_i2c_cfg->scl, PIN_MODE_OUTPUT_OD);
  118. if (state)
  119. {
  120. rt_pin_write(soft_i2c_cfg->scl, PIN_HIGH);
  121. }
  122. else
  123. {
  124. rt_pin_write(soft_i2c_cfg->scl, PIN_LOW);
  125. }
  126. }
  127. /**
  128. * This function gets the sda pin state.
  129. *
  130. * @param The sda pin state.
  131. */
  132. static rt_int32_t swm_i2c_get_sda(void *data)
  133. {
  134. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)data;
  135. rt_pin_mode(soft_i2c_cfg->sda, PIN_MODE_INPUT_PULLUP);
  136. return rt_pin_read(soft_i2c_cfg->sda);
  137. }
  138. /**
  139. * This function gets the scl pin state.
  140. *
  141. * @param The scl pin state.
  142. */
  143. static rt_int32_t swm_i2c_get_scl(void *data)
  144. {
  145. struct swm_soft_i2c_cfg *soft_i2c_cfg = (struct swm_soft_i2c_cfg *)data;
  146. rt_pin_mode(soft_i2c_cfg->scl, PIN_MODE_INPUT_PULLUP);
  147. return rt_pin_read(soft_i2c_cfg->scl);
  148. }
  149. /**
  150. * The time delay function.
  151. *
  152. * @param microseconds.
  153. */
  154. static void swm_i2c_udelay(rt_uint32_t us)
  155. {
  156. rt_uint32_t ticks;
  157. rt_uint32_t told, tnow, tcnt = 0;
  158. rt_uint32_t reload = SysTick->LOAD;
  159. ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
  160. told = SysTick->VAL;
  161. while (1)
  162. {
  163. tnow = SysTick->VAL;
  164. if (tnow != told)
  165. {
  166. if (tnow < told)
  167. {
  168. tcnt += told - tnow;
  169. }
  170. else
  171. {
  172. tcnt += reload - tnow + told;
  173. }
  174. told = tnow;
  175. if (tcnt >= ticks)
  176. {
  177. break;
  178. }
  179. }
  180. }
  181. }
  182. static const struct rt_i2c_bit_ops swm_i2c_bit_ops =
  183. {
  184. .data = RT_NULL,
  185. .pin_init = swm_i2c_pin_init,
  186. .set_sda = swm_i2c_set_sda,
  187. .set_scl = swm_i2c_set_scl,
  188. .get_sda = swm_i2c_get_sda,
  189. .get_scl = swm_i2c_get_scl,
  190. .udelay = swm_i2c_udelay,
  191. .delay_us = 1,
  192. .timeout = 100,
  193. .i2c_pin_init_flag = RT_FALSE
  194. };
  195. /* I2C initialization function */
  196. int swm_i2c_init(void)
  197. {
  198. rt_err_t result;
  199. for (rt_size_t i = 0; i < sizeof(i2c_obj) / sizeof(struct swm_soft_i2c_device); i++)
  200. {
  201. i2c_obj[i].ops = swm_i2c_bit_ops;
  202. i2c_obj[i].ops.data = (void *)&swm_soft_i2c_cfg[i];
  203. i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops;
  204. result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, swm_soft_i2c_cfg[i].name);
  205. RT_ASSERT(result == RT_EOK);
  206. LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
  207. swm_soft_i2c_cfg[i].name,
  208. swm_soft_i2c_cfg[i].scl,
  209. swm_soft_i2c_cfg[i].sda);
  210. }
  211. return RT_EOK;
  212. }
  213. INIT_DEVICE_EXPORT(swm_i2c_init);
  214. #endif /* BSP_USING_I2C */
  215. #endif /* RT_USING_I2C */