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-12-07 wumingzi first version
9 */
10 #include <rtthread.h>
11 #include <rtdevice.h>
12 #define LOG_TAG "drv.i2c"
13 #ifdef RT_USING_I2C
14 #ifdef BSP_USING_SW_I2C
15 #include "rthw.h"
16 #include "rttypes.h"
17 #include <rtdbg.h>
18 #include "driver/gpio.h"
19 #include "drv_sw_i2c.h"
20
21 #if defined(BSP_USING_SW_I2C0)
22 #define SW_I2C0_BUS_CONFIG \
23 { \
24 .scl = BSP_SW_I2C0_SCL_PIN, \
25 .sda = BSP_SW_I2C0_SDA_PIN, \
26 .bus_name = "i2c0", \
27 }
28 #endif
29
30 static const struct esp32c3_soft_i2c_config soft_i2c_config[] =
31 {
32 #if defined(BSP_USING_SW_I2C0)
33 SW_I2C0_BUS_CONFIG,
34 #endif
35 };
36
37 static struct esp32c3_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
38
39 /**
40 * @brief This function initializes the i2c pin.
41 * @param i2c
42 * @retval None
43 */
esp32c3_i2c_gpio_init(struct esp32c3_i2c * i2c)44 static void esp32c3_i2c_gpio_init(struct esp32c3_i2c *i2c)
45 {
46 struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)i2c->ops.data;
47 rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
48 rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
49
50 gpio_set_pull_mode(cfg->sda, GPIO_FLOATING);
51 gpio_set_pull_mode(cfg->scl, GPIO_FLOATING);
52
53 gpio_set_level(cfg->scl, PIN_HIGH);
54 gpio_set_level(cfg->sda, PIN_HIGH);
55 }
56
57 /**
58 * @brief This function sets the sda pin.
59 * @param data, state
60 * @retval None
61 */
esp32c3_set_sda(void * data,rt_int32_t state)62 static void esp32c3_set_sda(void *data, rt_int32_t state)
63 {
64 struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)data;
65 /*rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);*/
66 if (state)
67 {
68 gpio_set_level(cfg->sda, PIN_HIGH);
69 }
70 else
71 {
72 gpio_set_level(cfg->sda, PIN_LOW);
73 }
74 }
75
76 /**
77 * @brief This function sets the scl pin.
78 * @param data, state
79 * @retval None
80 */
esp32c3_set_scl(void * data,rt_int32_t state)81 static void esp32c3_set_scl(void *data, rt_int32_t state)
82 {
83 struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)data;
84 if (state)
85 {
86 gpio_set_level(cfg->scl, PIN_HIGH);
87 }
88 else
89 {
90 gpio_set_level(cfg->scl, PIN_LOW);
91 }
92 }
93
94 /**
95 * @brief This function gets the sda pin state.
96 * @param data
97 * @retval None
98 */
esp32c3_get_sda(void * data)99 static rt_int32_t esp32c3_get_sda(void *data)
100 {
101 struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)data;
102 return gpio_get_level(cfg->sda);
103 }
104
105 /**
106 * @brief This function gets the scl pin state.
107 * @param data
108 * @retval None
109 */
esp32c3_get_scl(void * data)110 static rt_int32_t esp32c3_get_scl(void *data)
111 {
112 struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)data;
113 return gpio_get_level(cfg->scl);
114 }
115
116 /**
117 * @brief The time delay function.
118 * @param us
119 * @retval None
120 */
esp32c3_udelay(rt_uint32_t us)121 static void esp32c3_udelay(rt_uint32_t us)
122 {
123 rt_hw_us_delay(us);
124 }
125
126 /*
127 * if i2c is locked, this function will unlock it
128 *
129 * @param esp32 config class
130 *
131 * @return RT_EOK indicates successful unlock.
132 */
133 /* */
esp32c3_i2c_bus_unlock(const struct esp32c3_soft_i2c_config * cfg)134 static rt_err_t esp32c3_i2c_bus_unlock(const struct esp32c3_soft_i2c_config *cfg)
135 {
136 rt_int32_t i = 0;
137
138 if (PIN_LOW == rt_pin_read(cfg->sda))
139 {
140 /* 输出9个时钟 解锁IIC死锁 */
141 while (i++ < 9)
142 {
143 gpio_set_level(cfg->scl, PIN_HIGH);
144 esp32c3_udelay(100);
145 gpio_set_level(cfg->scl, PIN_LOW);
146 esp32c3_udelay(100);
147 }
148 }
149 if (PIN_LOW == gpio_get_level(cfg->sda))
150 {
151 return -RT_ERROR;
152 }
153 return RT_EOK;
154 }
155
156 static const struct rt_i2c_bit_ops esp32c3_bit_ops_default =
157 {
158 .data = RT_NULL,
159 .set_sda = esp32c3_set_sda,
160 .set_scl = esp32c3_set_scl,
161 .get_sda = esp32c3_get_sda,
162 .get_scl = esp32c3_get_scl,
163 .udelay = esp32c3_udelay,
164 .delay_us = 1,
165 .timeout = 100
166 };
167
rt_sw_i2c_init(void)168 int rt_sw_i2c_init(void)
169 {
170 /* I2C设备数量 */
171 rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct esp32c3_i2c);
172 rt_err_t result;
173 /* 循环初始化 */
174 for (int i = 0; i < obj_num; i++)
175 {
176 /* 注册方法 */
177 i2c_obj[i].ops = esp32c3_bit_ops_default;
178 /* 设备硬件数据 */
179 i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
180 /* 保存设备方法 */
181 i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops;
182
183 esp32c3_i2c_gpio_init(&i2c_obj[i]);
184 result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, soft_i2c_config[i].bus_name);
185 RT_ASSERT(result == RT_EOK);
186
187 esp32c3_i2c_bus_unlock(&soft_i2c_config[i]);
188 LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
189 soft_i2c_config[i].bus_name,
190 soft_i2c_config[i].scl,
191 soft_i2c_config[i].sda);
192 }
193
194 return RT_EOK;
195 }
196 INIT_APP_EXPORT(rt_sw_i2c_init);
197
198 #endif /* BSP_USING_SW_I2C */
199 #endif /* RT_USING_I2C */