drv_soft_i2c.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. * Copyright (c) 2022, Xiaohua Semiconductor Co., Ltd.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2022-04-28 CDT first version
  10. */
  11. /*******************************************************************************
  12. * Include files
  13. ******************************************************************************/
  14. #include "drv_soft_i2c.h"
  15. #include "board_config.h"
  16. #if defined(RT_USING_I2C)
  17. #if defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) || defined(BSP_USING_I2C3) || \
  18. defined(BSP_USING_I2C4) || defined(BSP_USING_I2C5) || defined(BSP_USING_I2C6)
  19. /*******************************************************************************
  20. * Local type definitions ('typedef')
  21. ******************************************************************************/
  22. /*******************************************************************************
  23. * Local pre-processor symbols/macros ('#define')
  24. ******************************************************************************/
  25. //#define DRV_DEBUG
  26. #define LOG_TAG "drv.i2c"
  27. #include <drv_log.h>
  28. /*******************************************************************************
  29. * Global variable definitions (declared in header file with 'extern')
  30. ******************************************************************************/
  31. /*******************************************************************************
  32. * Local function prototypes ('static')
  33. ******************************************************************************/
  34. /*******************************************************************************
  35. * Local variable definitions ('static')
  36. ******************************************************************************/
  37. static const struct hc32_soft_i2c_config soft_i2c_config[] =
  38. {
  39. #ifdef BSP_USING_I2C1
  40. I2C1_BUS_CONFIG,
  41. #endif
  42. #ifdef BSP_USING_I2C2
  43. I2C2_BUS_CONFIG,
  44. #endif
  45. #ifdef BSP_USING_I2C3
  46. I2C3_BUS_CONFIG,
  47. #endif
  48. #ifdef BSP_USING_I2C4
  49. I2C4_BUS_CONFIG,
  50. #endif
  51. #ifdef BSP_USING_I2C5
  52. I2C5_BUS_CONFIG,
  53. #endif
  54. #ifdef BSP_USING_I2C6
  55. I2C6_BUS_CONFIG,
  56. #endif
  57. };
  58. static struct hc32_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
  59. /*******************************************************************************
  60. * Function implementation - global ('extern') and local ('static')
  61. ******************************************************************************/
  62. /**
  63. * This function initializes the i2c pin.
  64. *
  65. * @param Hc32 i2c dirver class.
  66. */
  67. static void hc32_i2c_gpio_init(struct hc32_i2c *i2c)
  68. {
  69. struct hc32_soft_i2c_config *cfg = (struct hc32_soft_i2c_config *)i2c->ops.data;
  70. rt_pin_mode(cfg->scl_pin, PIN_MODE_OUTPUT_OD);
  71. rt_pin_mode(cfg->sda_pin, PIN_MODE_OUTPUT_OD);
  72. rt_pin_write(cfg->scl_pin, PIN_HIGH);
  73. rt_pin_write(cfg->sda_pin, PIN_HIGH);
  74. }
  75. /**
  76. * This function sets the sda pin.
  77. *
  78. * @param Hc32 config class.
  79. * @param The sda pin state.
  80. */
  81. static void hc32_set_sda(void *data, rt_int32_t state)
  82. {
  83. struct hc32_soft_i2c_config *cfg = (struct hc32_soft_i2c_config *)data;
  84. if (state)
  85. {
  86. rt_pin_write(cfg->sda_pin, PIN_HIGH);
  87. }
  88. else
  89. {
  90. rt_pin_write(cfg->sda_pin, PIN_LOW);
  91. }
  92. }
  93. /**
  94. * This function sets the scl pin.
  95. *
  96. * @param Hc32 config class.
  97. * @param The scl pin state.
  98. */
  99. static void hc32_set_scl(void *data, rt_int32_t state)
  100. {
  101. struct hc32_soft_i2c_config *cfg = (struct hc32_soft_i2c_config *)data;
  102. if (state)
  103. {
  104. rt_pin_write(cfg->scl_pin, PIN_HIGH);
  105. }
  106. else
  107. {
  108. rt_pin_write(cfg->scl_pin, PIN_LOW);
  109. }
  110. }
  111. /**
  112. * This function gets the sda pin state.
  113. *
  114. * @param The sda pin state.
  115. */
  116. static rt_int32_t hc32_get_sda(void *data)
  117. {
  118. struct hc32_soft_i2c_config *cfg = (struct hc32_soft_i2c_config *)data;
  119. return rt_pin_read(cfg->sda_pin);
  120. }
  121. /**
  122. * This function gets the scl pin state.
  123. *
  124. * @param The scl pin state.
  125. */
  126. static rt_int32_t hc32_get_scl(void *data)
  127. {
  128. struct hc32_soft_i2c_config *cfg = (struct hc32_soft_i2c_config *)data;
  129. return rt_pin_read(cfg->scl_pin);
  130. }
  131. /**
  132. * The time delay function.
  133. *
  134. * @param microseconds.
  135. */
  136. static void hc32_udelay(rt_uint32_t us)
  137. {
  138. rt_uint32_t ticks;
  139. rt_uint32_t told, tnow, tcnt = 0;
  140. rt_uint32_t reload = SysTick->LOAD;
  141. ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
  142. told = SysTick->VAL;
  143. while (1)
  144. {
  145. tnow = SysTick->VAL;
  146. if (tnow != told)
  147. {
  148. if (tnow < told)
  149. {
  150. tcnt += told - tnow;
  151. }
  152. else
  153. {
  154. tcnt += reload - tnow + told;
  155. }
  156. told = tnow;
  157. if (tcnt >= ticks)
  158. {
  159. break;
  160. }
  161. }
  162. }
  163. }
  164. static const struct rt_i2c_bit_ops hc32_bit_ops_default =
  165. {
  166. .data = RT_NULL,
  167. .set_sda = hc32_set_sda,
  168. .set_scl = hc32_set_scl,
  169. .get_sda = hc32_get_sda,
  170. .get_scl = hc32_get_scl,
  171. .udelay = hc32_udelay,
  172. .delay_us = 1,
  173. .timeout = 100
  174. };
  175. /**
  176. * if i2c is locked, this function will unlock it
  177. *
  178. * @param hc32 config class
  179. *
  180. * @return RT_EOK indicates successful unlock.
  181. */
  182. static rt_err_t hc32_i2c_bus_unlock(const struct hc32_soft_i2c_config *cfg)
  183. {
  184. rt_uint32_t i = 0;
  185. if (PIN_LOW == rt_pin_read(cfg->sda_pin))
  186. {
  187. while (i++ < 9)
  188. {
  189. rt_pin_write(cfg->scl_pin, PIN_HIGH);
  190. hc32_udelay(100);
  191. rt_pin_write(cfg->scl_pin, PIN_LOW);
  192. hc32_udelay(100);
  193. }
  194. }
  195. if (PIN_LOW == rt_pin_read(cfg->sda_pin))
  196. {
  197. return -RT_ERROR;
  198. }
  199. return RT_EOK;
  200. }
  201. /* I2C initialization function */
  202. int hc32_hw_i2c_init(void)
  203. {
  204. rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct hc32_i2c);
  205. rt_err_t result;
  206. for (int i = 0; i < obj_num; i++)
  207. {
  208. i2c_obj[i].ops = hc32_bit_ops_default;
  209. i2c_obj[i].ops.data = (void *)&soft_i2c_config[i];
  210. i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops;
  211. hc32_i2c_gpio_init(&i2c_obj[i]);
  212. result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, soft_i2c_config[i].bus_name);
  213. RT_ASSERT(result == RT_EOK);
  214. hc32_i2c_bus_unlock(&soft_i2c_config[i]);
  215. }
  216. return RT_EOK;
  217. }
  218. INIT_BOARD_EXPORT(hc32_hw_i2c_init);
  219. #endif
  220. #endif /* RT_USING_I2C */
  221. /*******************************************************************************
  222. * EOF (not truncated)
  223. ******************************************************************************/