drv_i2c.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. * 2019-07-15 Magicoe The first version for LPC55S6x
  9. * 2023-02-17 Vandoul Add status to lpc_i2c_bus.
  10. */
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include "board.h"
  14. #include "fsl_iocon.h"
  15. #include "fsl_gpio.h"
  16. #include "fsl_i2c.h"
  17. #include "fsl_i2c_dma.h"
  18. #ifdef RT_USING_I2C
  19. enum
  20. {
  21. #ifdef BSP_USING_I2C4
  22. I2C4_INDEX,
  23. #endif
  24. };
  25. #define i2c_dbg rt_kprintf
  26. struct lpc_i2c_bus
  27. {
  28. struct rt_i2c_bus_device parent;
  29. I2C_Type *I2C;
  30. DMA_Type *DMA;
  31. i2c_master_dma_handle_t i2c_mst_dma_handle;
  32. dma_handle_t dmaHandle;
  33. rt_sem_t sem;
  34. clock_attach_id_t i2c_clock_id;
  35. uint32_t dma_chl;
  36. uint32_t instance;
  37. uint32_t baud;
  38. char *device_name;
  39. uint32_t status;
  40. };
  41. struct lpc_i2c_bus lpc_obj[] =
  42. {
  43. #ifdef BSP_USING_I2C4
  44. {
  45. .I2C = I2C4,
  46. .DMA = DMA0,
  47. .dma_chl = 13,
  48. .device_name = "i2c4",
  49. .baud = 400000U,
  50. .instance = 4U,
  51. .i2c_clock_id = kFRO12M_to_FLEXCOMM4,
  52. },
  53. #endif
  54. };
  55. static void i2c_mst_dma_callback(I2C_Type *base, i2c_master_dma_handle_t *handle, status_t status, void *userData)
  56. {
  57. struct lpc_i2c_bus *lpc_i2c = (struct lpc_i2c_bus*)userData;
  58. lpc_i2c->status = status;
  59. rt_sem_release(lpc_i2c->sem);
  60. }
  61. static rt_ssize_t lpc_i2c_xfer(struct rt_i2c_bus_device *bus,
  62. struct rt_i2c_msg msgs[], rt_uint32_t num)
  63. {
  64. struct rt_i2c_msg *msg;
  65. i2c_master_transfer_t xfer = {0};
  66. rt_uint32_t i;
  67. rt_err_t ret = RT_ERROR;
  68. struct lpc_i2c_bus *lpc_i2c = (struct lpc_i2c_bus *)bus;
  69. for (i = 0; i < num; i++)
  70. {
  71. msg = &msgs[i];
  72. if (msg->flags & RT_I2C_RD)
  73. {
  74. xfer.slaveAddress = msg->addr;
  75. xfer.direction = kI2C_Read;
  76. xfer.subaddress = 0;
  77. xfer.subaddressSize = 0;
  78. xfer.data = msg->buf;
  79. xfer.dataSize = msg->len;
  80. if(i != 0)
  81. xfer.flags = kI2C_TransferRepeatedStartFlag;
  82. else
  83. xfer.flags = kI2C_TransferDefaultFlag;
  84. // if (I2C_MasterTransferBlocking(lpc_i2c->I2C, &xfer) != kStatus_Success)
  85. if(I2C_MasterTransferDMA(lpc_i2c->I2C, &lpc_i2c->i2c_mst_dma_handle, &xfer) != kStatus_Success)
  86. {
  87. i2c_dbg("i2c bus read failed!\n");
  88. return i;
  89. }
  90. rt_sem_take(lpc_i2c->sem, RT_WAITING_FOREVER);
  91. }
  92. else
  93. {
  94. xfer.slaveAddress = msg->addr;
  95. xfer.direction = kI2C_Write;
  96. xfer.subaddress = 0;
  97. xfer.subaddressSize = 0;
  98. xfer.data = msg->buf;
  99. xfer.dataSize = msg->len;
  100. if(i == 0)
  101. xfer.flags = kI2C_TransferNoStopFlag;
  102. else
  103. xfer.flags = kI2C_TransferDefaultFlag;
  104. //if (I2C_MasterTransferBlocking(lpc_i2c->I2C, &xfer) != kStatus_Success)
  105. if(I2C_MasterTransferDMA(lpc_i2c->I2C, &lpc_i2c->i2c_mst_dma_handle, &xfer) != kStatus_Success)
  106. {
  107. i2c_dbg("i2c bus write failed!\n");
  108. return i;
  109. }
  110. rt_sem_take(lpc_i2c->sem, RT_WAITING_FOREVER);
  111. if(lpc_i2c->status != kStatus_Success)
  112. {
  113. break;
  114. }
  115. }
  116. }
  117. ret = i;
  118. return ret;
  119. }
  120. static const struct rt_i2c_bus_device_ops i2c_ops =
  121. {
  122. lpc_i2c_xfer,
  123. RT_NULL,
  124. RT_NULL
  125. };
  126. int rt_hw_i2c_init(void)
  127. {
  128. int i;
  129. i2c_master_config_t masterConfig;
  130. for(i=0; i<ARRAY_SIZE(lpc_obj); i++)
  131. {
  132. CLOCK_AttachClk(lpc_obj[i].i2c_clock_id);
  133. I2C_MasterGetDefaultConfig(&masterConfig);
  134. masterConfig.baudRate_Bps = lpc_obj[i].baud;
  135. /* Initialize the I2C master peripheral */
  136. I2C_MasterInit(lpc_obj[i].I2C, &masterConfig, CLOCK_GetFlexCommClkFreq(lpc_obj[i].instance));
  137. lpc_obj[i].parent.ops = &i2c_ops;
  138. lpc_obj[i].sem = rt_sem_create("sem_i2c", 0, RT_IPC_FLAG_FIFO);
  139. DMA_CreateHandle(&lpc_obj[i].dmaHandle, lpc_obj[i].DMA, lpc_obj[i].dma_chl);
  140. I2C_MasterTransferCreateHandleDMA(lpc_obj[i].I2C, &lpc_obj[i].i2c_mst_dma_handle, i2c_mst_dma_callback, &lpc_obj[i], &lpc_obj[i].dmaHandle);
  141. rt_i2c_bus_device_register(&lpc_obj[i].parent, lpc_obj[i].device_name);
  142. }
  143. return 0;
  144. }
  145. INIT_DEVICE_EXPORT(rt_hw_i2c_init);
  146. #endif /* RT_USING_I2C */