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  * 2022-01-21     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 
ch32f2_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 ch32f2_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 
ch32f2_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 ch32f2_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 
ch32f2_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)294 static rt_ssize_t ch32f2_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 (ch32f2_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 (ch32f2_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 ch32f2_i2c_ops = {
329     .master_xfer = ch32f2_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     ch32f2_i2c_clock_and_io_init(i2c_bus1.periph);
342     ch32f2_i2c_config(i2c_bus1.periph);
343 
344     i2c_bus1.parent.ops = &ch32f2_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     ch32f2_i2c_clock_and_io_init(i2c_bus2.periph);
356     ch32f2_i2c_config(i2c_bus2.periph);
357 
358     i2c_bus2.parent.ops = &ch32f2_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