dev_soft_i2c.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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-07-30 sp-cai first version
  9. */
  10. #include <rtdevice.h>
  11. #ifdef RT_USING_SOFT_I2C
  12. #if !defined(RT_USING_SOFT_I2C1) && !defined(RT_USING_SOFT_I2C2) &&\
  13. !defined(RT_USING_SOFT_I2C3) && !defined(RT_USING_SOFT_I2C4) &&\
  14. !defined(RT_USING_SOFT_I2C5) && !defined(RT_USING_SOFT_I2C6) &&\
  15. !defined(RT_USING_SOFT_I2C7) && !defined(RT_USING_SOFT_I2C8)
  16. #error "Please define at least one RT_USING_SOFT_I2Cx"
  17. /*
  18. This driver can be disabled at:
  19. menuconfig -> RT-Thread Components -> Device Drivers -> Using I2C device drivers
  20. */
  21. #endif
  22. #define DBG_ENABLE
  23. #define DBG_TAG "I2C_S"
  24. #ifdef RT_I2C_BITOPS_DEBUG
  25. #define DBG_LEVEL DBG_LOG
  26. #endif
  27. #include <rtdbg.h>
  28. /* i2c config class */
  29. struct soft_i2c_config
  30. {
  31. rt_base_t scl_pin;
  32. rt_base_t sda_pin;
  33. const char *bus_name;
  34. rt_uint16_t timing_delay; /* scl and sda line delay */
  35. rt_uint16_t timing_timeout; /* in tick */
  36. };
  37. /* i2c dirver class */
  38. struct rt_soft_i2c
  39. {
  40. struct rt_i2c_bus_device i2c_bus;
  41. struct rt_i2c_bit_ops ops;
  42. };
  43. struct soft_i2c_config i2c_cfg[] =
  44. {
  45. #ifdef RT_USING_SOFT_I2C1
  46. {
  47. .scl_pin = RT_SOFT_I2C1_SCL_PIN,
  48. .sda_pin = RT_SOFT_I2C1_SDA_PIN,
  49. .bus_name = RT_SOFT_I2C1_BUS_NAME,
  50. .timing_delay = RT_SOFT_I2C1_TIMING_DELAY,
  51. .timing_timeout = RT_SOFT_I2C1_TIMING_TIMEOUT,
  52. },
  53. #endif //RT_USING_SOFT_I2C1
  54. #ifdef RT_USING_SOFT_I2C2
  55. {
  56. .scl_pin = RT_SOFT_I2C2_SCL_PIN,
  57. .sda_pin = RT_SOFT_I2C2_SDA_PIN,
  58. .bus_name = RT_SOFT_I2C2_BUS_NAME,
  59. .timing_delay = RT_SOFT_I2C2_TIMING_DELAY,
  60. .timing_timeout = RT_SOFT_I2C2_TIMING_TIMEOUT,
  61. },
  62. #endif //RT_USING_SOFT_I2C2
  63. #ifdef RT_USING_SOFT_I2C3
  64. {
  65. .scl_pin = RT_SOFT_I2C3_SCL_PIN,
  66. .sda_pin = RT_SOFT_I2C3_SDA_PIN,
  67. .bus_name = RT_SOFT_I2C3_BUS_NAME,
  68. .timing_delay = RT_SOFT_I2C3_TIMING_DELAY,
  69. .timing_timeout = RT_SOFT_I2C3_TIMING_TIMEOUT,
  70. },
  71. #endif //RT_USING_SOFT_I2C3
  72. #ifdef RT_USING_SOFT_I2C4
  73. {
  74. .scl_pin = RT_SOFT_I2C4_SCL_PIN,
  75. .sda_pin = RT_SOFT_I2C4_SDA_PIN,
  76. .bus_name = RT_SOFT_I2C4_BUS_NAME,
  77. .timing_delay = RT_SOFT_I2C4_TIMING_DELAY,
  78. .timing_timeout = RT_SOFT_I2C4_TIMING_TIMEOUT,
  79. },
  80. #endif //RT_USING_SOFT_I2C4
  81. #ifdef RT_USING_SOFT_I2C5
  82. {
  83. .scl_pin = RT_SOFT_I2C5_SCL_PIN,
  84. .sda_pin = RT_SOFT_I2C5_SDA_PIN,
  85. .bus_name = RT_SOFT_I2C5_BUS_NAME,
  86. .timing_delay = RT_SOFT_I2C5_TIMING_DELAY,
  87. .timing_timeout = RT_SOFT_I2C5_TIMING_TIMEOUT,
  88. },
  89. #endif //RT_USING_SOFT_I2C5
  90. #ifdef RT_USING_SOFT_I2C6
  91. {
  92. .scl_pin = RT_SOFT_I2C6_SCL_PIN,
  93. .sda_pin = RT_SOFT_I2C6_SDA_PIN,
  94. .bus_name = RT_SOFT_I2C6_BUS_NAME,
  95. .timing_delay = RT_SOFT_I2C6_TIMING_DELAY,
  96. .timing_timeout = RT_SOFT_I2C6_TIMING_TIMEOUT,
  97. },
  98. #endif //RT_USING_SOFT_I2C6
  99. #ifdef RT_USING_SOFT_I2C7
  100. {
  101. .scl_pin = RT_SOFT_I2C7_SCL_PIN,
  102. .sda_pin = RT_SOFT_I2C7_SDA_PIN,
  103. .bus_name = RT_SOFT_I2C7_BUS_NAME,
  104. .timing_delay = RT_SOFT_I2C7_TIMING_DELAY,
  105. .timing_timeout = RT_SOFT_I2C7_TIMING_TIMEOUT,
  106. },
  107. #endif //RT_USING_SOFT_I2C7
  108. #ifdef RT_USING_SOFT_I2C8
  109. {
  110. .scl_pin = RT_SOFT_I2C8_SCL_PIN,
  111. .sda_pin = RT_SOFT_I2C8_SDA_PIN,
  112. .bus_name = RT_SOFT_I2C8_BUS_NAME,
  113. .timing_delay = RT_SOFT_I2C8_TIMING_DELAY,
  114. .timing_timeout = RT_SOFT_I2C8_TIMING_TIMEOUT,
  115. },
  116. #endif //RT_USING_SOFT_I2C8
  117. };
  118. static struct rt_soft_i2c i2c_bus_obj[sizeof(i2c_cfg) / sizeof(i2c_cfg[0])] =
  119. { 0 };
  120. /**
  121. * This function initializes the i2c pin.
  122. * @param i2c config class.
  123. */
  124. static void pin_init(const struct soft_i2c_config *cfg)
  125. {
  126. rt_pin_mode(cfg->scl_pin, PIN_MODE_OUTPUT_OD);
  127. rt_pin_mode(cfg->sda_pin, PIN_MODE_OUTPUT_OD);
  128. rt_pin_write(cfg->scl_pin, PIN_HIGH);
  129. rt_pin_write(cfg->sda_pin, PIN_HIGH);
  130. }
  131. /**
  132. * This function sets the sda pin.
  133. * @param i2c config class.
  134. * @param The sda pin state.
  135. */
  136. static void set_sda(void *cfg, rt_int32_t value)
  137. {
  138. rt_pin_write(((const struct soft_i2c_config*)cfg)->sda_pin, value);
  139. }
  140. /**
  141. * This function sets the scl pin.
  142. * @param i2c config class.
  143. * @param The sda pin state.
  144. */
  145. static void set_scl(void *cfg, rt_int32_t value)
  146. {
  147. rt_pin_write(((const struct soft_i2c_config*)cfg)->scl_pin, value);
  148. }
  149. /**
  150. * This function gets the sda pin state.
  151. * @param i2c config class.
  152. */
  153. static rt_int32_t get_sda(void *cfg)
  154. {
  155. return rt_pin_read(((const struct soft_i2c_config*)cfg)->sda_pin);
  156. }
  157. /**
  158. * This function gets the scl pin state.
  159. * @param i2c config class.
  160. */
  161. static rt_int32_t get_scl(void *cfg)
  162. {
  163. return rt_pin_read(((const struct soft_i2c_config*)cfg)->scl_pin);
  164. }
  165. static const struct rt_i2c_bit_ops soft_i2c_ops =
  166. {
  167. .set_sda = set_sda,
  168. .set_scl = set_scl,
  169. .get_sda = get_sda,
  170. .get_scl = get_scl,
  171. .udelay = rt_hw_us_delay,
  172. };
  173. /**
  174. * if i2c is locked, this function will unlock it
  175. *
  176. * @param i2c config class.
  177. *
  178. * @return RT_EOK indicates successful unlock.
  179. */
  180. static rt_err_t i2c_bus_unlock(const struct soft_i2c_config *cfg)
  181. {
  182. rt_ubase_t i = 0;
  183. if(PIN_LOW == rt_pin_read(cfg->sda_pin))
  184. {
  185. while(i++ < 9)
  186. {
  187. rt_pin_write(cfg->scl_pin, PIN_HIGH);
  188. rt_hw_us_delay(cfg->timing_delay);
  189. rt_pin_write(cfg->scl_pin, PIN_LOW);
  190. rt_hw_us_delay(cfg->timing_delay);
  191. }
  192. }
  193. if(PIN_LOW == rt_pin_read(cfg->sda_pin))
  194. {
  195. return -RT_ERROR;
  196. }
  197. return RT_EOK;
  198. }
  199. /* I2C initialization function */
  200. int rt_soft_i2c_init(void)
  201. {
  202. int err = RT_EOK;
  203. struct rt_soft_i2c *obj;
  204. int i;
  205. for(i = 0; i < sizeof(i2c_bus_obj) / sizeof(i2c_bus_obj[0]); i++)
  206. {
  207. struct soft_i2c_config *cfg = &i2c_cfg[i];
  208. pin_init(cfg);
  209. obj = &i2c_bus_obj[i];
  210. obj->ops = soft_i2c_ops;
  211. obj->ops.data = cfg;
  212. obj->i2c_bus.priv = &obj->ops;
  213. obj->ops.delay_us = cfg->timing_delay;
  214. obj->ops.timeout = cfg->timing_timeout;
  215. if(rt_i2c_bit_add_bus(&obj->i2c_bus, cfg->bus_name) == RT_EOK)
  216. {
  217. i2c_bus_unlock(cfg);
  218. LOG_D("Software simulation %s init done"
  219. ", SCL pin: 0x%02X, SDA pin: 0x%02X"
  220. , cfg->bus_name
  221. , cfg->scl_pin
  222. , cfg->sda_pin
  223. );
  224. }
  225. else
  226. {
  227. err++;
  228. LOG_E("Software simulation %s init fail"
  229. ", SCL pin: 0x%02X, SDA pin: 0x%02X"
  230. , cfg->bus_name
  231. , cfg->scl_pin
  232. , cfg->sda_pin
  233. );
  234. }
  235. }
  236. return err;
  237. }
  238. INIT_PREV_EXPORT(rt_soft_i2c_init);
  239. #endif // RT_USING_SOFT_I2C