drv_hw_i2c.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. *2023-03-28 Zxy first version
  9. */
  10. #ifdef RT_USING_I2C
  11. #include "drv_hw_i2c.h"
  12. #include "driver/i2c.h"//bsp/ESP32_C3/packages/ESP-IDF-latest/components/driver/include/driver/i2c.h
  13. #include "hal/i2c_types.h"//bsp/ESP32_C3/packages/ESP-IDF-latest/tools/mocks/hal/include/hal/i2c_types.h
  14. #include "esp_err.h"
  15. //#include "portmacro.h"//bsp/ESP32_C3/packages/FreeRTOS_Wrapper-latest/FreeRTOS/portable/rt-thread/portmacro.h
  16. struct esp32_i2c
  17. {
  18. struct rt_i2c_bus_device bus;
  19. i2c_config_t *base;
  20. char *device_name;
  21. };
  22. // #if defined(BSP_USING_I2C0)
  23. static struct esp32_i2c i2c0 = {0};
  24. // #endif
  25. static rt_size_t _master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
  26. {
  27. i2c_cmd_handle_t cmd;//创建流程
  28. rt_size_t ret = (0);
  29. rt_uint32_t index = 0;
  30. // struct esp32_i2c *esp32_i2c = RT_NULL;
  31. struct rt_i2c_msg *msg = RT_NULL;
  32. i2c_rw_t direction;//w-0 r-1
  33. esp_err_t result = ESP_OK;
  34. RT_ASSERT(bus != RT_NULL);
  35. // esp32_i2c = (struct esp32_i2c *)bus;
  36. for(index = 0; index < num; index++)
  37. {
  38. msg = &msgs[index];
  39. direction = ((msg->flags & RT_I2C_RD) ? I2C_MASTER_READ : I2C_MASTER_WRITE);
  40. if (!(msg->flags & RT_I2C_NO_START))
  41. {
  42. /* Start condition and slave address. */
  43. cmd = i2c_cmd_link_create();//创建流程
  44. i2c_master_start(cmd);//启动流程录入
  45. result = i2c_master_write_byte(cmd, msg->addr << 1 | WRITE_BIT, ACK_CHECK_EN);//发送起始信号和从设备地址
  46. i2c_master_stop(cmd);//流程录入完毕
  47. ret = i2c_master_cmd_begin(I2C_NUMBER(0), cmd, 1000 / portTICK_PERIOD_MS);//执行流程
  48. i2c_cmd_link_delete(cmd);//删除流程任务
  49. if (ret != ESP_OK) return ret;
  50. }
  51. if (result == ESP_OK)
  52. {
  53. if (direction == I2C_MASTER_WRITE)
  54. {
  55. /* Transmit data. */
  56. cmd = i2c_cmd_link_create();//创建流程
  57. i2c_master_start(cmd);//启动流程录入
  58. result = i2c_master_write_byte(cmd, msg->buf, ACK_CHECK_EN);
  59. i2c_master_stop(cmd);//流程录入完毕
  60. ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);//执行流程
  61. i2c_cmd_link_delete(cmd);//删除流程任务
  62. }
  63. else
  64. {
  65. /* Receive Data. */
  66. cmd = i2c_cmd_link_create();//创建流程
  67. i2c_master_start(cmd);//启动流程录入
  68. result = i2c_master_read_byte(cmd, msg->buf, ACK_VAL);
  69. i2c_master_stop(cmd);//流程录入完毕
  70. ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);//执行流程
  71. i2c_cmd_link_delete(cmd);//删除流程任务
  72. }
  73. }
  74. }
  75. if (result == ESP_OK)
  76. {
  77. ret = index;
  78. }
  79. return ret;
  80. }
  81. static rt_size_t _slave_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
  82. {
  83. return -RT_ENOSYS;
  84. }
  85. static rt_err_t _i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t cmd, rt_uint32_t arg)
  86. {
  87. return -RT_EINVAL;
  88. }
  89. static const struct rt_i2c_bus_device_ops i2c_ops =
  90. {
  91. _master_xfer,
  92. _slave_xfer,
  93. _i2c_bus_control,
  94. };
  95. int rt_hw_i2c_init(void)
  96. {
  97. i2c0.base = &i2c0;
  98. i2c0.device_name = "i2c0";
  99. i2c0.bus.ops = &i2c_ops;
  100. int i2c_master_port = I2C_MASTER_NUM;//iic0
  101. i2c_config_t conf = {
  102. .mode = I2C_MODE_MASTER,
  103. .sda_io_num = I2C_MASTER_SDA_IO,
  104. .sda_pullup_en = GPIO_PULLUP_ENABLE,
  105. .scl_io_num = I2C_MASTER_SCL_IO,
  106. .scl_pullup_en = GPIO_PULLUP_ENABLE,
  107. .master.clk_speed = 100000,
  108. // .clk_flags = 0, /*!< Optional, you can use I2C_SCLK_SRC_FLAG_* flags to choose i2c source clock here. */
  109. };
  110. i2c_param_config(i2c_master_port, &conf);//配置完成
  111. i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);// I2C 设备的初始化
  112. rt_i2c_bus_device_register(&i2c0.bus, i2c0.device_name);
  113. return RT_EOK;
  114. }
  115. INIT_BOARD_EXPORT(rt_hw_i2c_init);
  116. #endif /* RT_USING_I2C */