drv_i2c.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. * 2024-04-08 QT-one first version
  9. */
  10. #include "drv_i2c.h"
  11. #ifdef RT_USING_I2C
  12. #if !defined(BSP_USING_I2C0_HW) && !defined(BSP_USING_I2C1_HW)
  13. #error "Please define at least one BSP_USING_I2Cx_HW"
  14. /* this driver can be disabled at menuconfig RT-Thread Components Device Drivers */
  15. #endif
  16. struct ht32_i2c_config
  17. {
  18. HT_I2C_TypeDef *i2c_x;
  19. const char *i2c_name;
  20. IRQn_Type irq;
  21. };
  22. struct ht32_i2c
  23. {
  24. struct ht32_i2c_config *config;
  25. struct rt_i2c_bus_device i2c_bus;
  26. };
  27. enum
  28. {
  29. #ifdef BSP_USING_I2C0_HW
  30. I2C0_INDEX,
  31. #endif
  32. #ifdef BSP_USING_I2C1_HW
  33. I2C1_INDEX,
  34. #endif
  35. };
  36. static struct ht32_i2c_config i2c_config[] =
  37. {
  38. #ifdef BSP_USING_I2C0_HW
  39. {
  40. .i2c_x = HT_I2C0,
  41. .i2c_name = BSP_USING_I2C0_HW_NAME,
  42. .irq = I2C0_IRQn
  43. },
  44. #endif
  45. #ifdef BSP_USING_I2C1_HW
  46. {
  47. .i2c_x = HT_I2C1,
  48. .i2c_name = BSP_USING_I2C1_HW_NAME,
  49. .irq = I2C1_IRQn
  50. },
  51. #endif
  52. };
  53. static struct ht32_i2c i2cs[sizeof(i2c_config) / sizeof(i2c_config[0])] = {0};
  54. static rt_size_t ht32_i2c_init(struct ht32_i2c *i2c_drv)
  55. {
  56. struct ht32_i2c_config *i2c_config = i2c_drv->config;
  57. CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
  58. #ifdef BSP_USING_I2C0_HW
  59. if (HT_I2C0 == i2c_config->i2c_x)
  60. {
  61. CKCUClock.Bit.I2C0 = 1;
  62. }
  63. #endif
  64. #ifdef BSP_USING_I2C1_HW
  65. if (HT_I2C1 == i2c_config->i2c_x)
  66. {
  67. CKCUClock.Bit.I2C1 = 1;
  68. }
  69. #endif
  70. CKCUClock.Bit.AFIO = 1;
  71. CKCU_PeripClockConfig(CKCUClock, ENABLE);
  72. ht32_hardware_i2c_gpio_init(i2c_config->i2c_x);
  73. I2C_InitTypeDef I2C_InitStructure;
  74. I2C_InitStructure.I2C_GeneralCall = DISABLE;
  75. I2C_InitStructure.I2C_AddressingMode = I2C_ADDRESSING_7BIT;
  76. I2C_InitStructure.I2C_Acknowledge = DISABLE;
  77. I2C_InitStructure.I2C_OwnAddress = 0x00;
  78. I2C_InitStructure.I2C_Speed = 400000;
  79. I2C_InitStructure.I2C_SpeedOffset = 0;
  80. I2C_Init(i2c_config->i2c_x, &I2C_InitStructure);
  81. I2C_Cmd(i2c_config->i2c_x, ENABLE);
  82. return RT_EOK;
  83. }
  84. static int ht32_i2c_read(struct ht32_i2c_config *hi2c,
  85. rt_uint16_t slave_address,
  86. rt_uint8_t *p_buffer,
  87. rt_uint16_t data_byte)
  88. {
  89. uint16_t date_num = 0;
  90. uint8_t data = 0xFF;
  91. /* Determine if the bus is idle */
  92. while (I2C_GetFlagStatus(hi2c->i2c_x, I2C_FLAG_BUSBUSY));
  93. /* Send start bit, slave address and read/write bit */
  94. I2C_TargetAddressConfig(hi2c->i2c_x, slave_address, I2C_MASTER_READ);
  95. while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_SEND_START));
  96. while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_RECEIVER_MODE));
  97. I2C_AckCmd(hi2c->i2c_x, ENABLE);
  98. while (date_num < data_byte)
  99. {
  100. date_num++;
  101. while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_RX_NOT_EMPTY));
  102. data = I2C_ReceiveData(hi2c->i2c_x);
  103. if (date_num == (data_byte - 1))
  104. {
  105. I2C_AckCmd(hi2c->i2c_x, DISABLE);
  106. }
  107. if (p_buffer != RT_NULL)
  108. {
  109. *p_buffer++ = data;
  110. }
  111. }
  112. I2C_GenerateSTOP(hi2c->i2c_x);
  113. while (I2C_ReadRegister(hi2c->i2c_x, I2C_REGISTER_SR) & 0x80000);
  114. return 0;
  115. }
  116. static int ht32_i2c_write(struct ht32_i2c_config *hi2c,
  117. uint16_t slave_address,
  118. uint8_t *p_buffer,
  119. uint16_t data_byte)
  120. {
  121. uint16_t date_num = data_byte;
  122. /* Determine if the bus is idle */
  123. while (I2C_GetFlagStatus(hi2c->i2c_x, I2C_FLAG_BUSBUSY));
  124. /* Send start bit, slave address and read/write bit */
  125. I2C_TargetAddressConfig(hi2c->i2c_x, slave_address, I2C_MASTER_WRITE);
  126. while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_SEND_START));
  127. while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_TRANSMITTER_MODE));
  128. while (date_num--)
  129. {
  130. while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_TX_EMPTY));
  131. I2C_SendData(hi2c->i2c_x, *p_buffer);
  132. p_buffer++;
  133. }
  134. while (!I2C_CheckStatus(hi2c->i2c_x, I2C_MASTER_TX_EMPTY));
  135. I2C_GenerateSTOP(hi2c->i2c_x);
  136. while (I2C_ReadRegister(hi2c->i2c_x, I2C_REGISTER_SR) & 0x80000);
  137. return 0;
  138. }
  139. static rt_ssize_t ht32_master_xfer(struct rt_i2c_bus_device *bus,
  140. struct rt_i2c_msg msgs[],
  141. rt_uint32_t num)
  142. {
  143. struct ht32_i2c *i2c_instance;
  144. struct rt_i2c_msg *msg;
  145. rt_uint32_t i;
  146. i2c_instance = rt_container_of(bus, struct ht32_i2c, i2c_bus);
  147. RT_ASSERT(bus != RT_NULL);
  148. RT_ASSERT(msgs != RT_NULL);
  149. for (i = 0; i < num; i++)
  150. {
  151. msg = &msgs[i];
  152. if (msg->flags & RT_I2C_RD)
  153. {
  154. if (ht32_i2c_read(i2c_instance->config, msg->addr, msg->buf, msg->len) != 0)
  155. {
  156. return i;
  157. }
  158. }
  159. else
  160. {
  161. if (ht32_i2c_write(i2c_instance->config, msg->addr, msg->buf, msg->len) != 0)
  162. {
  163. return i;
  164. }
  165. }
  166. }
  167. return i;
  168. }
  169. static struct rt_i2c_bus_device_ops ht32_i2c_ops =
  170. {
  171. .master_xfer = ht32_master_xfer,
  172. .slave_xfer = RT_NULL,
  173. .i2c_bus_control = RT_NULL
  174. };
  175. int rt_hw_i2c_init(void)
  176. {
  177. int i;
  178. rt_err_t result;
  179. rt_size_t obj_num = sizeof(i2cs) / sizeof(struct ht32_i2c);
  180. for (i = 0; i < obj_num; i++)
  181. {
  182. i2cs[i].config = &i2c_config[i];
  183. i2cs[i].i2c_bus.parent.user_data = (void *)&i2cs[i];
  184. i2cs[i].i2c_bus.ops = &ht32_i2c_ops;
  185. ht32_i2c_init(&i2cs[i]);
  186. result = rt_i2c_bus_device_register(&i2cs[i].i2c_bus, i2cs[i].config->i2c_name);
  187. }
  188. return result;
  189. }
  190. INIT_BOARD_EXPORT(rt_hw_i2c_init);
  191. #endif /* RT_USING_I2C */