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