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 * 2021-08-10 charlown first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <rthw.h>
14 #include "board.h"
15 #include "drv_hwi2c.h"
16
17 #ifdef BSP_USING_HWI2C
18
19 #define LOG_TAG "drv.hwi2c"
20 #include "drv_log.h"
21
22 #define TIMEOUT 0x0FF
23
24 struct i2c_bus_device
25 {
26 struct rt_i2c_bus_device parent;
27 I2C_TypeDef *periph;
28 };
29
30 #ifdef BSP_USING_HWI2C1
31
32 struct i2c_bus_device i2c_bus1;
33 #endif
34
35 #ifdef BSP_USING_HWI2C2
36
37 struct i2c_bus_device i2c_bus2;
38 #endif
39
ch32f1_i2c_read(I2C_TypeDef * i2c_periph,rt_uint8_t flags,rt_uint16_t slave_address,rt_uint8_t * p_buffer,rt_uint16_t data_byte)40 static int ch32f1_i2c_read(I2C_TypeDef *i2c_periph,
41 rt_uint8_t flags,
42 rt_uint16_t slave_address,
43 rt_uint8_t *p_buffer,
44 rt_uint16_t data_byte)
45 {
46 rt_uint32_t try;
47
48 if (flags & RT_I2C_ADDR_10BIT)
49 {
50 //fixme
51 }
52 else
53 {
54 //7 bit address
55 try = 0;
56 while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY) != RESET)
57 {
58
59 if (try == TIMEOUT)
60 {
61 LOG_E("i2c bus read getflag timeout! \n");
62 return -1;
63 }
64 try++;
65 };
66
67 I2C_GenerateSTART(i2c_periph, ENABLE);
68
69 try = 0;
70 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))
71 {
72
73 if (try == TIMEOUT)
74 {
75 LOG_E("i2c bus read checkevent timeout! \n");
76 return -1;
77 }
78 try++;
79 };
80 I2C_Send7bitAddress(i2c_periph, (slave_address << 1), I2C_Direction_Transmitter);
81
82 try = 0;
83 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
84 {
85
86 if (try == TIMEOUT)
87 {
88 LOG_E("i2c bus read checkevent timeout! \n");
89 return -1;
90 }
91 try++;
92 };
93
94 I2C_GenerateSTART(i2c_periph, ENABLE);
95
96 try = 0;
97 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))
98 {
99
100 if (try == TIMEOUT)
101 {
102 LOG_E("i2c bus read checkevent timeout! \n");
103 return -1;
104 }
105 try++;
106 };
107 I2C_Send7bitAddress(i2c_periph, (slave_address << 1), I2C_Direction_Receiver);
108
109 try = 0;
110 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
111 {
112
113 if (try == TIMEOUT)
114 {
115 LOG_E("i2c bus read checkevent timeout! \n");
116 return -1;
117 }
118 try++;
119 };
120
121 if (data_byte == 1)
122 {
123 try = 0;
124 while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_RXNE) == RESET)
125 {
126
127 if (try == TIMEOUT)
128 {
129 LOG_E("i2c bus read checkevent timeout! \n");
130 return -1;
131 }
132 try++;
133 };
134
135 I2C_AcknowledgeConfig(i2c_periph, DISABLE);
136
137 *p_buffer = I2C_ReceiveData(i2c_periph);
138
139 I2C_GenerateSTOP(i2c_periph, ENABLE);
140 }
141 else
142 {
143
144 try = 0;
145 while (data_byte)
146 {
147
148 if (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_RXNE) == RESET)
149 {
150 *p_buffer = I2C_ReceiveData(i2c_periph);
151
152 p_buffer++;
153 data_byte--;
154 try = 0;
155
156 if (data_byte == 1)
157 {
158 I2C_AcknowledgeConfig(i2c_periph, DISABLE);
159 I2C_GenerateSTOP(i2c_periph, ENABLE);
160 }
161 }
162
163 if (try == TIMEOUT)
164 {
165 LOG_E("i2c bus read checkevent timeout! \n");
166 return -1;
167 }
168
169 try++;
170 }
171 }
172 }
173
174 return 0;
175 }
176
ch32f1_i2c_write(I2C_TypeDef * i2c_periph,rt_uint8_t flags,rt_uint16_t slave_address,rt_uint8_t * p_buffer,rt_uint16_t data_byte)177 static int ch32f1_i2c_write(I2C_TypeDef *i2c_periph,
178 rt_uint8_t flags,
179 rt_uint16_t slave_address,
180 rt_uint8_t *p_buffer,
181 rt_uint16_t data_byte)
182 {
183 rt_uint32_t try;
184
185 if (flags & RT_I2C_ADDR_10BIT)
186 {
187 //fixme
188 }
189 else
190 {
191 //7 bit address
192 try = 0;
193 while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY) != RESET)
194 {
195
196 if (try == TIMEOUT)
197 {
198 LOG_E("i2c bus write getflag timeout! \n");
199 return -1;
200 }
201 try++;
202 };
203
204 I2C_GenerateSTART(i2c_periph, ENABLE);
205
206 try = 0;
207 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))
208 {
209
210 if (try == TIMEOUT)
211 {
212 LOG_E("i2c bus write checkevent timeout! \n");
213 return -1;
214 }
215 try++;
216 };
217 I2C_Send7bitAddress(i2c_periph, (slave_address << 1), I2C_Direction_Transmitter);
218
219 try = 0;
220 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
221 {
222
223 if (try == TIMEOUT)
224 {
225 LOG_E("i2c bus write checkevent timeout! \n");
226 return -1;
227 }
228 try++;
229 };
230
231 I2C_GenerateSTART(i2c_periph, ENABLE);
232
233 try = 0;
234 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))
235 {
236
237 if (try == TIMEOUT)
238 {
239 LOG_E("i2c bus write checkevent timeout! \n");
240 return -1;
241 }
242 try++;
243 };
244 I2C_Send7bitAddress(i2c_periph, (slave_address << 1), I2C_Direction_Transmitter);
245
246 try = 0;
247 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
248 {
249
250 if (try == TIMEOUT)
251 {
252 LOG_E("i2c bus write checkevent timeout! \n");
253 return -1;
254 }
255 try++;
256 };
257
258 try = 0;
259 while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_TXE) == RESET)
260 {
261
262 if (try == TIMEOUT)
263 {
264 LOG_E("i2c bus write checkevent timeout! \n");
265 return -1;
266 }
267 try++;
268 };
269
270 while (data_byte)
271 {
272 I2C_SendData(i2c_periph, *p_buffer);
273 p_buffer++;
274 data_byte--;
275
276 try = 0;
277 while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
278 {
279 if (try == TIMEOUT)
280 {
281 LOG_E("i2c bus write checkevent timeout! \n");
282 return -1;
283 }
284 try++;
285 };
286 }
287
288 I2C_GenerateSTOP(i2c_periph, ENABLE);
289 }
290
291 return 0;
292 }
293
ch32f1_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)294 static rt_ssize_t ch32f1_master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
295 {
296 struct rt_i2c_msg *msg;
297 struct i2c_bus_device *i2c_bus_dev;
298 rt_uint32_t index;
299
300 i2c_bus_dev = (struct i2c_bus_device *)bus;
301
302 for (index = 0; index < num; index++)
303 {
304 msg = &msgs[index];
305 if (msg->flags & RT_I2C_RD)
306 {
307
308 if (ch32f1_i2c_read(i2c_bus_dev->periph, msg->flags, msg->addr, msg->buf, msg->len) != 0)
309 {
310 LOG_E("i2c bus write failed,i2c bus stop!");
311 return 0;
312 }
313 }
314 else
315 {
316
317 if (ch32f1_i2c_write(i2c_bus_dev->periph, msg->flags, msg->addr, msg->buf, msg->len) != 0)
318 {
319 LOG_E("i2c bus write failed,i2c bus stop!");
320 return 0;
321 }
322 }
323 }
324
325 return index;
326 }
327
328 const struct rt_i2c_bus_device_ops ch32f1_i2c_ops = {
329 .master_xfer = ch32f1_master_xfer,
330 .slave_xfer = RT_NULL,
331 .i2c_bus_control = RT_NULL,
332 };
333
rt_hw_i2c_init(void)334 int rt_hw_i2c_init(void)
335 {
336 int result = RT_EOK;
337
338 #ifdef BSP_USING_HWI2C1
339
340 i2c_bus1.periph = I2C1;
341 ch32f1_i2c_clock_and_io_init(i2c_bus1.periph);
342 ch32f1_i2c_config(i2c_bus1.periph);
343
344 i2c_bus1.parent.ops = &ch32f1_i2c_ops;
345 result = rt_i2c_bus_device_register(&i2c_bus1.parent, "hwi2c1");
346 if (result != RT_EOK)
347 {
348 return result;
349 }
350 #endif
351
352 #ifdef BSP_USING_HWI2C2
353
354 i2c_bus2.periph = I2C2;
355 ch32f1_i2c_clock_and_io_init(i2c_bus2.periph);
356 ch32f1_i2c_config(i2c_bus2.periph);
357
358 i2c_bus2.parent.ops = &ch32f1_i2c_ops;
359
360 rt_i2c_bus_device_register(&i2c_bus2.parent, "hwi2c2");
361 if (result != RT_EOK)
362 {
363 return result;
364 }
365 #endif
366
367 return RT_EOK;
368 }
369 INIT_DEVICE_EXPORT(rt_hw_i2c_init);
370
371 #endif /* BSP_USING_HWI2C */
372