1
0

drv_soft_i2c.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-09-13 AisinoChip first implementation.
  9. * 2024-04-23 LZero Modify the I2C framework.
  10. */
  11. #ifdef BSP_USING_SOFT_I2C
  12. #include "drv_soft_i2c.h"
  13. #define DBG_TAG "drv.i2c"
  14. #ifdef DRV_DEBUG
  15. #define DBG_LVL DBG_LOG
  16. #else
  17. #define DBG_LVL DBG_INFO
  18. #endif /* DRV_DEBUG */
  19. static struct acm32_soft_i2c_config soft_i2c_config[] =
  20. {
  21. #ifdef BSP_USING_I2C0
  22. I2C0_BUS_CONFIG,
  23. #endif
  24. };
  25. static struct acm32_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
  26. static void drv_i2c_gpio_init(struct acm32_i2c* i2c)
  27. {
  28. struct acm32_soft_i2c_config* cfg = (struct acm32_soft_i2c_config*)i2c->ops.data;
  29. rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
  30. rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
  31. rt_pin_write(cfg->scl, PIN_HIGH);
  32. rt_pin_write(cfg->sda, PIN_HIGH);
  33. }
  34. static void acm32_i2c_pin_init(void)
  35. {
  36. rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct acm32_i2c);
  37. for(rt_size_t i = 0; i < obj_num; i++)
  38. {
  39. drv_i2c_gpio_init(&i2c_obj[i]);
  40. }
  41. }
  42. static void _set_sda(void *data, rt_int32_t state)
  43. {
  44. struct acm32_soft_i2c_config* cfg = (struct acm32_soft_i2c_config*)data;
  45. if (state)
  46. {
  47. rt_pin_write(cfg->sda, PIN_HIGH);
  48. }
  49. else
  50. {
  51. rt_pin_write(cfg->sda, PIN_LOW);
  52. }
  53. }
  54. static void _set_scl(void *data, rt_int32_t state)
  55. {
  56. struct acm32_soft_i2c_config* cfg = (struct acm32_soft_i2c_config*)data;
  57. if (state)
  58. {
  59. rt_pin_write(cfg->scl, PIN_HIGH);
  60. }
  61. else
  62. {
  63. rt_pin_write(cfg->scl, PIN_LOW);
  64. }
  65. }
  66. static rt_int32_t _get_sda(void *data)
  67. {
  68. struct acm32_soft_i2c_config* cfg = (struct acm32_soft_i2c_config*)data;
  69. return rt_pin_read(cfg->sda);
  70. }
  71. static rt_int32_t _get_scl(void *data)
  72. {
  73. struct acm32_soft_i2c_config* cfg = (struct acm32_soft_i2c_config*)data;
  74. return rt_pin_read(cfg->scl);
  75. }
  76. static void acm32_udelay(rt_uint32_t us)
  77. {
  78. rt_uint32_t ticks;
  79. rt_uint32_t told, tnow, tcnt = 0;
  80. rt_uint32_t reload = SysTick->LOAD;
  81. ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
  82. told = SysTick->VAL;
  83. while (1)
  84. {
  85. tnow = SysTick->VAL;
  86. if (tnow != told)
  87. {
  88. if (tnow < told)
  89. {
  90. tcnt += told - tnow;
  91. }
  92. else
  93. {
  94. tcnt += reload - tnow + told;
  95. }
  96. told = tnow;
  97. if (tcnt >= ticks)
  98. {
  99. break;
  100. }
  101. }
  102. }
  103. }
  104. static const struct rt_i2c_bit_ops acm32_bit_ops_default =
  105. {
  106. .data = RT_NULL,
  107. .pin_init = acm32_i2c_pin_init,
  108. .set_sda = _set_sda,
  109. .set_scl = _set_scl,
  110. .get_sda = _get_sda,
  111. .get_scl = _get_scl,
  112. .udelay = acm32_udelay,
  113. .delay_us = 1,
  114. .timeout = 100,
  115. .i2c_pin_init_flag = RT_FALSE
  116. };
  117. int rt_soft_i2c_init(void)
  118. {
  119. rt_err_t result;
  120. for (rt_size_t i = 0; i < sizeof(i2c_obj) / sizeof(struct acm32_i2c); i++)
  121. {
  122. i2c_obj[i].ops = acm32_bit_ops_default;
  123. i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
  124. i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops;
  125. result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, soft_i2c_config[i].bus_name);
  126. RT_ASSERT(result == RT_EOK);
  127. LOG_D("software simulation %s init done, pin scl: %d, pin sda: %d",
  128. soft_i2c_config[i].bus_name,
  129. soft_i2c_config[i].scl,
  130. soft_i2c_config[i].sda);
  131. }
  132. return RT_EOK;
  133. }
  134. INIT_DEVICE_EXPORT(rt_soft_i2c_init);
  135. #endif /* RT_USING_I2C_BITOPS */