drv_i2c.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*****************************************************************************
  2. * Copyright (c) 2019, Nations Technologies Inc.
  3. *
  4. * All rights reserved.
  5. * ****************************************************************************
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * - Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the disclaimer below.
  12. *
  13. * Nations' name may not be used to endorse or promote products derived from
  14. * this software without specific prior written permission.
  15. *
  16. * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  19. * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  21. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  22. * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  23. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  24. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  25. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. * ****************************************************************************/
  27. /**
  28. * @file drv_i2c.c
  29. * @author Nations
  30. * @version v1.0.0
  31. *
  32. * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
  33. */
  34. #include <rthw.h>
  35. #include <rtthread.h>
  36. #include "drv_i2c.h"
  37. #include "board.h"
  38. #ifdef RT_USING_I2C
  39. #include <rtdevice.h>
  40. #define DBG_TAG "drv.I2C"
  41. #ifdef RT_I2C_DEBUG
  42. #define DBG_LVL DBG_LOG
  43. #else
  44. #define DBG_LVL DBG_INFO
  45. #endif
  46. #include <rtdbg.h>
  47. #ifdef RT_USING_I2C_BITOPS
  48. static const struct n32_soft_i2c_config soft_i2c_config[] =
  49. {
  50. #ifdef BSP_USING_I2C1
  51. I2C1_BUS_CONFIG,
  52. #endif
  53. #ifdef BSP_USING_I2C2
  54. I2C2_BUS_CONFIG,
  55. #endif
  56. #ifdef BSP_USING_I2C3
  57. I2C3_BUS_CONFIG,
  58. #endif
  59. #ifdef BSP_USING_I2C4
  60. I2C4_BUS_CONFIG,
  61. #endif
  62. };
  63. static struct n32_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
  64. /**
  65. *\*\name n32_i2c_gpio_init
  66. *\*\fun Initializes the i2c pin.
  67. *\*\param i2c dirver class
  68. *\*\return none
  69. **/
  70. static void n32_i2c_gpio_init(struct n32_i2c *i2c)
  71. {
  72. struct n32_soft_i2c_config* cfg = (struct n32_soft_i2c_config*)i2c->ops.data;
  73. rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
  74. rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
  75. rt_pin_write(cfg->scl, PIN_HIGH);
  76. rt_pin_write(cfg->sda, PIN_HIGH);
  77. }
  78. /**
  79. *\*\name n32_set_sda
  80. *\*\fun sets the sda pin.
  81. *\*\param data config class
  82. *\*\param state sda pin state
  83. *\*\return none
  84. **/
  85. static void n32_set_sda(void *data, rt_int32_t state)
  86. {
  87. struct n32_soft_i2c_config* cfg = (struct n32_soft_i2c_config*)data;
  88. if (state)
  89. {
  90. rt_pin_write(cfg->sda, PIN_HIGH);
  91. }
  92. else
  93. {
  94. rt_pin_write(cfg->sda, PIN_LOW);
  95. }
  96. }
  97. /**
  98. *\*\name n32_set_scl
  99. *\*\fun sets the scl pin.
  100. *\*\param data config class
  101. *\*\param state scl pin state
  102. *\*\return none
  103. **/
  104. static void n32_set_scl(void *data, rt_int32_t state)
  105. {
  106. struct n32_soft_i2c_config* cfg = (struct n32_soft_i2c_config*)data;
  107. if (state)
  108. {
  109. rt_pin_write(cfg->scl, PIN_HIGH);
  110. }
  111. else
  112. {
  113. rt_pin_write(cfg->scl, PIN_LOW);
  114. }
  115. }
  116. /**
  117. *\*\name n32_get_sda
  118. *\*\fun gets the sda pin state.
  119. *\*\param data config class
  120. *\*\return sda pin state
  121. **/
  122. static rt_int32_t n32_get_sda(void *data)
  123. {
  124. struct n32_soft_i2c_config* cfg = (struct n32_soft_i2c_config*)data;
  125. return rt_pin_read(cfg->sda);
  126. }
  127. /**
  128. *\*\name n32_get_scl
  129. *\*\fun gets the scl pin state.
  130. *\*\param data config class
  131. *\*\return scl pin state
  132. **/
  133. static rt_int32_t n32_get_scl(void *data)
  134. {
  135. struct n32_soft_i2c_config* cfg = (struct n32_soft_i2c_config*)data;
  136. return rt_pin_read(cfg->scl);
  137. }
  138. /**
  139. *\*\name n32_udelay
  140. *\*\fun The time delay function.
  141. *\*\param us
  142. *\*\return none
  143. **/
  144. static void n32_udelay(rt_uint32_t us)
  145. {
  146. rt_uint32_t ticks;
  147. rt_uint32_t told, tnow, tcnt = 0;
  148. rt_uint32_t reload = SysTick->LOAD;
  149. ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
  150. told = SysTick->VAL;
  151. while(1)
  152. {
  153. tnow = SysTick->VAL;
  154. if(tnow != told)
  155. {
  156. if(tnow < told)
  157. {
  158. tcnt += told - tnow;
  159. }
  160. else
  161. {
  162. tcnt += reload - tnow + told;
  163. }
  164. told = tnow;
  165. if(tcnt >= ticks)
  166. {
  167. break;
  168. }
  169. }
  170. }
  171. }
  172. static const struct rt_i2c_bit_ops n32_bit_ops_default =
  173. {
  174. .data = RT_NULL,
  175. .set_sda = n32_set_sda,
  176. .set_scl = n32_set_scl,
  177. .get_sda = n32_get_sda,
  178. .get_scl = n32_get_scl,
  179. .udelay = n32_udelay,
  180. .delay_us = 1,
  181. .timeout = 100
  182. };
  183. /**
  184. *\*\name n32_i2c_bus_unlock
  185. *\*\fun If i2c is locked, this function will unlock it.
  186. *\*\param cfg
  187. *\*\return RT_EOK indicates successful unlock
  188. **/
  189. static rt_err_t n32_i2c_bus_unlock(const struct n32_soft_i2c_config *cfg)
  190. {
  191. rt_int32_t i = 0;
  192. if(PIN_LOW == rt_pin_read(cfg->sda))
  193. {
  194. while(i++ < 9)
  195. {
  196. rt_pin_write(cfg->scl, PIN_HIGH);
  197. n32_udelay(100);
  198. rt_pin_write(cfg->scl, PIN_LOW);
  199. n32_udelay(100);
  200. }
  201. }
  202. if(PIN_LOW == rt_pin_read(cfg->sda))
  203. {
  204. return -RT_ERROR;
  205. }
  206. return RT_EOK;
  207. }
  208. #endif /* RT_USING_I2C_BITOPS */
  209. #ifdef RT_USING_HARDWARE_I2C
  210. static uint32_t I2CTimeout = I2CT_LONG_TIMEOUT;
  211. static int rt_i2c_read(rt_uint32_t i2c_periph, rt_uint16_t slave_address, rt_uint8_t* p_buffer, rt_uint16_t data_byte)
  212. {
  213. I2CTimeout = I2CT_LONG_TIMEOUT;
  214. /* wait until I2C bus is idle */
  215. while(I2C_GetFlag((I2C_Module*)i2c_periph, I2C_FLAG_BUSY))
  216. {
  217. if ((I2CTimeout--) == 0)
  218. return 9;
  219. };
  220. I2C_ConfigAck((I2C_Module*)i2c_periph, ENABLE);
  221. /** Send START condition */
  222. I2C_GenerateStart((I2C_Module*)i2c_periph, ENABLE);
  223. I2CTimeout = I2CT_LONG_TIMEOUT;
  224. /* wait until SBSEND bit is set */
  225. while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_MODE_FLAG)) // EV5
  226. {
  227. if ((I2CTimeout--) == 0)
  228. return 10;
  229. };
  230. /* send slave address to I2C bus */
  231. I2C_SendAddr7bit((I2C_Module*)i2c_periph, slave_address, I2C_DIRECTION_RECV);
  232. I2CTimeout = I2CT_LONG_TIMEOUT;
  233. while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_RXMODE_FLAG)) // EV6
  234. {
  235. if ((I2CTimeout--) == 0)
  236. return 6;
  237. };
  238. // /* clear the ADDSEND bit */
  239. // I2C_ClrFlag((I2C_Module*)i2c_periph,I2C_FLAG_ADDRF);
  240. // if(1 == data_byte){
  241. // /* disable acknowledge */
  242. // I2C_ConfigAck((I2C_Module*)i2c_periph,DISABLE);
  243. // /* send a stop condition to I2C bus */
  244. // I2C_GenerateStop(I2C1, ENABLE);
  245. // }
  246. /* while there is data to be read */
  247. while(data_byte)
  248. {
  249. /* wait until the RBNE bit is set and clear it */
  250. if(I2C_GetFlag((I2C_Module*)i2c_periph, I2C_FLAG_RXDATNE))
  251. {
  252. /* read a byte*/
  253. *p_buffer = I2C_RecvData((I2C_Module*)i2c_periph);
  254. /* point to the next location where the byte read will be saved */
  255. p_buffer++;
  256. /* decrement the read bytes counter */
  257. data_byte--;
  258. if(1 == data_byte)
  259. {
  260. /* disable acknowledge */
  261. I2C_ConfigAck((I2C_Module*)i2c_periph, DISABLE);
  262. /* send a stop condition to I2C bus */
  263. I2C_GenerateStop((I2C_Module*)i2c_periph, ENABLE);
  264. }
  265. }
  266. }
  267. /* wait until the stop condition is finished */
  268. while(I2C_GetFlag((I2C_Module*)i2c_periph, I2C_FLAG_STOPF))
  269. {
  270. if ((I2CTimeout--) == 0)
  271. return 7;
  272. };
  273. /* enable acknowledge */
  274. I2C_ConfigAck((I2C_Module*)i2c_periph, ENABLE);
  275. I2C_ConfigNackLocation((I2C_Module*)i2c_periph,I2C_NACK_POS_CURRENT);
  276. return 0;
  277. }
  278. static int rt_i2c_write(rt_uint32_t i2c_periph, uint16_t slave_address, uint8_t* p_buffer, uint16_t data_byte)
  279. {
  280. uint8_t* sendBufferPtr = p_buffer;
  281. I2CTimeout = I2CT_LONG_TIMEOUT;
  282. while (I2C_GetFlag((I2C_Module*)i2c_periph, I2C_FLAG_BUSY))
  283. {
  284. if ((I2CTimeout--) == 0)
  285. return 4;
  286. };
  287. I2C_ConfigAck((I2C_Module*)i2c_periph, ENABLE);
  288. I2C_GenerateStart((I2C_Module*)i2c_periph, ENABLE);
  289. I2CTimeout = I2CT_LONG_TIMEOUT;
  290. while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_MODE_FLAG)) // EV5
  291. {
  292. if ((I2CTimeout--) == 0)
  293. return 5;
  294. };
  295. I2C_SendAddr7bit((I2C_Module*)i2c_periph, slave_address, I2C_DIRECTION_SEND);
  296. I2CTimeout = I2CT_LONG_TIMEOUT;
  297. while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_TXMODE_FLAG)) // EV6
  298. {
  299. if ((I2CTimeout--) == 0)
  300. return 6;
  301. };
  302. // send data
  303. while (data_byte-- > 0)
  304. {
  305. I2C_SendData((I2C_Module*)i2c_periph, *sendBufferPtr++);
  306. I2CTimeout = I2CT_LONG_TIMEOUT;
  307. while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_DATA_SENDING)) // EV8
  308. {
  309. if ((I2CTimeout--) == 0)
  310. return 7;
  311. };
  312. };
  313. I2CTimeout = I2CT_LONG_TIMEOUT;
  314. while (!I2C_CheckEvent((I2C_Module*)i2c_periph, I2C_EVT_MASTER_DATA_SENDED)) // EV8-2
  315. {
  316. if ((I2CTimeout--) == 0)
  317. return 8;
  318. };
  319. I2C_GenerateStop((I2C_Module*)i2c_periph, ENABLE);
  320. return 0;
  321. }
  322. static rt_size_t rt_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
  323. {
  324. struct rt_i2c_msg *msg;
  325. rt_uint32_t i;
  326. rt_err_t ret = RT_ERROR;
  327. struct rt_i2c_bus *rt_i2c = (struct rt_i2c_bus *)bus;
  328. for (i = 0; i < num; i++)
  329. {
  330. msg = &msgs[i];
  331. if (msg->flags & RT_I2C_RD)
  332. {
  333. if (rt_i2c_read(rt_i2c->i2c_periph, msg->addr, msg->buf, msg->len) != 0)
  334. {
  335. LOG_E("i2c bus write failed,i2c bus stop!");
  336. goto out;
  337. }
  338. }
  339. else
  340. {
  341. if (rt_i2c_write(rt_i2c->i2c_periph, msg->addr, msg->buf, msg->len) != 0)
  342. {
  343. LOG_E("i2c bus write failed,i2c bus stop!");
  344. goto out;
  345. }
  346. }
  347. }
  348. ret = i;
  349. return ret;
  350. out:
  351. LOG_E("send stop condition\n");
  352. return ret;
  353. }
  354. static const struct rt_i2c_bus_device_ops i2c_ops =
  355. {
  356. rt_i2c_xfer,
  357. RT_NULL,
  358. RT_NULL
  359. };
  360. #endif /* RT_USING_HARDWARE_I2C */
  361. int rt_hw_i2c_init(void)
  362. {
  363. #ifdef RT_USING_I2C_BITOPS
  364. rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct n32_i2c);
  365. rt_err_t result;
  366. for(int i = 0; i < obj_num; i++)
  367. {
  368. i2c_obj[i].ops = n32_bit_ops_default;
  369. i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
  370. i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
  371. n32_i2c_gpio_init(&i2c_obj[i]);
  372. result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);
  373. RT_ASSERT(result == RT_EOK);
  374. n32_i2c_bus_unlock(&soft_i2c_config[i]);
  375. rt_kprintf("software simulation %s init done, pin scl: %d, pin sda %d",
  376. soft_i2c_config[i].bus_name,
  377. soft_i2c_config[i].scl,
  378. soft_i2c_config[i].sda);
  379. }
  380. #endif /* RT_USING_I2C_BITOPS */
  381. #ifdef RT_USING_HARDWARE_I2C
  382. #ifdef BSP_USING_I2C1
  383. #define I2C1_SPEED 400000
  384. static struct rt_i2c_bus i2c_bus1;
  385. I2C_InitType I2C_InitStructure;
  386. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
  387. GPIO_ConfigPinRemap(GPIO_RMP_I2C1, ENABLE);
  388. /* connect PB8 to I2C1_SCL, PB9 to I2C1_SDA */
  389. GPIOInit(GPIOB, GPIO_Mode_AF_OD, GPIO_Speed_50MHz, GPIO_PIN_8 | GPIO_PIN_9);
  390. /* enable I2C clock */
  391. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
  392. I2C_DeInit(I2C1);
  393. I2C_InitStructure.BusMode = I2C_BUSMODE_I2C;
  394. I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
  395. I2C_InitStructure.OwnAddr1 = 0xff;
  396. I2C_InitStructure.AckEnable = I2C_ACKEN;
  397. I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT;
  398. I2C_InitStructure.ClkSpeed = I2C1_SPEED; // 400000 400K
  399. I2C_Init(I2C1, &I2C_InitStructure);
  400. rt_memset((void *)&i2c_bus1, 0, sizeof(struct rt_i2c_bus));
  401. i2c_bus1.parent.ops = &i2c_ops;
  402. i2c_bus1.i2c_periph = (rt_uint32_t)I2C1;
  403. rt_i2c_bus_device_register(&i2c_bus1.parent, "i2c1");
  404. #endif
  405. #ifdef BSP_USING_I2C2
  406. #define I2C2_SPEED 100000
  407. static struct rt_i2c_bus i2c_bus2;
  408. I2C_InitType I2C_InitStructure;
  409. /* enable I2C clock */
  410. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C2, ENABLE);
  411. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
  412. /* connect PB10 to I2C2_SCL, PB11 to I2C2_SDA */
  413. GPIOInit(GPIOB, GPIO_Mode_AF_OD, GPIO_Speed_50MHz, GPIO_PIN_10 | GPIO_PIN_11);
  414. I2C_DeInit(I2C2);
  415. I2C_InitStructure.BusMode = I2C_BUSMODE_I2C;
  416. I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
  417. I2C_InitStructure.OwnAddr1 = 0xff;
  418. I2C_InitStructure.AckEnable = I2C_ACKEN;
  419. I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT;
  420. I2C_InitStructure.ClkSpeed = I2C2_SPEED; // 100000 100K
  421. I2C_Init(I2C2, &I2C_InitStructure);
  422. rt_memset((void *)&i2c_bus2, 0, sizeof(struct rt_i2c_bus));
  423. i2c_bus2.parent.ops = &i2c_ops;
  424. i2c_bus2.i2c_periph = (rt_uint32_t)I2C2;
  425. rt_i2c_bus_device_register(&i2c_bus2.parent, "i2c2");
  426. #endif
  427. #ifdef BSP_USING_I2C3
  428. #define I2C3_SPEED 100000
  429. static struct rt_i2c_bus i2c_bus3;
  430. I2C_InitType I2C_InitStructure;
  431. /* enable I2C clock */
  432. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_I2C3, ENABLE);
  433. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
  434. /* connect PC0 to I2C3_SCL, PC1 to I2C3_SDA */
  435. GPIOInit(GPIOC, GPIO_Mode_AF_OD, GPIO_Speed_50MHz, GPIO_PIN_0 | GPIO_PIN_1);
  436. I2C_DeInit(I2C3);
  437. I2C_InitStructure.BusMode = I2C_BUSMODE_I2C;
  438. I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
  439. I2C_InitStructure.OwnAddr1 = 0xff;
  440. I2C_InitStructure.AckEnable = I2C_ACKEN;
  441. I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT;
  442. I2C_InitStructure.ClkSpeed = I2C3_SPEED; // 100000 100K
  443. I2C_Init(I2C3, &I2C_InitStructure);
  444. rt_memset((void *)&i2c_bus3, 0, sizeof(struct rt_i2c_bus));
  445. i2c_bus3.parent.ops = &i2c_ops;
  446. i2c_bus3.i2c_periph = (rt_uint32_t)I2C3;
  447. rt_i2c_bus_device_register(&i2c_bus3.parent, "i2c3");
  448. #endif
  449. #ifdef BSP_USING_I2C4
  450. #define I2C4_SPEED 100000
  451. static struct rt_i2c_bus i2c_bus4;
  452. I2C_InitType I2C_InitStructure;
  453. /* enable I2C clock */
  454. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_I2C4, ENABLE);
  455. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
  456. /* connect PC6 to I2C4_SCL, PC7 to I2C4_SDA */
  457. GPIOInit(GPIOC, GPIO_Mode_AF_OD, GPIO_Speed_50MHz, GPIO_PIN_6 | GPIO_PIN_7);
  458. I2C_DeInit(I2C4);
  459. I2C_InitStructure.BusMode = I2C_BUSMODE_I2C;
  460. I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
  461. I2C_InitStructure.OwnAddr1 = 0xff;
  462. I2C_InitStructure.AckEnable = I2C_ACKEN;
  463. I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT;
  464. I2C_InitStructure.ClkSpeed = I2C4_SPEED; // 100000 100K
  465. I2C_Init(I2C4, &I2C_InitStructure);
  466. rt_memset((void *)&i2c_bus4, 0, sizeof(struct rt_i2c_bus));
  467. i2c_bus4.parent.ops = &i2c_ops;
  468. i2c_bus4.i2c_periph = (rt_uint32_t)I2C4;
  469. rt_i2c_bus_device_register(&i2c_bus4.parent, "i2c4");
  470. #endif
  471. #endif /* RT_USING_HARDWARE_I2C */
  472. return RT_EOK;
  473. }
  474. INIT_DEVICE_EXPORT(rt_hw_i2c_init);
  475. #endif
  476. /* end of i2c driver */