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-4-1       IceBear003   the first version
9  */
10 
11 #include "board.h"
12 #include "drv_i2c.h"
13 
14 #ifdef BSP_USING_HWI2C
15 
16 #define LOG_TAG "drv.hwi2c"
17 #include "drv_log.h"
18 
19 #if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2)
20 #error "Please define at least one BSP_USING_I2Cx"
21 /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
22 #endif
23 
24 #define TIMEOUT 0xFF
25 
26 #ifdef BSP_USING_I2C1
27 struct i2c_bus_device i2c_bus1;
28 #endif
29 #ifdef BSP_USING_I2C2
30 struct i2c_bus_device i2c_bus2;
31 #endif
32 
i2c_read(I2C_TypeDef * i2c_periph,rt_uint16_t addr,rt_uint8_t flags,rt_uint16_t len,rt_uint8_t * buf)33 static int i2c_read(I2C_TypeDef *i2c_periph,
34                          rt_uint16_t addr,
35                          rt_uint8_t flags,
36                          rt_uint16_t len,
37                          rt_uint8_t *buf)
38 {
39     rt_uint16_t try = 0;
40     while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY))
41         if (try++ >= TIMEOUT) return -1;
42 
43     I2C_GenerateSTART(i2c_periph, ENABLE);
44 
45     try = 0;
46     while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))                       //EVT5
47         if (try++ >= TIMEOUT) return -1;
48 
49     if(flags & RT_I2C_ADDR_10BIT)   //10-bit address mode
50     {
51         rt_uint8_t frame_head = 0xF0 + (addr >> 8) << 1;                                    //11110XX0
52         I2C_SendData(i2c_periph, frame_head);                                               //FrameHead
53 
54         try = 0;
55         while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_ADDRESS10))                //EVT9
56             if (try++ >= TIMEOUT) return -1;
57 
58         I2C_SendData(i2c_periph,0xff & addr);
59 
60         try = 0;
61         while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))     //EVT6
62             if (try++ >= TIMEOUT) return -1;
63 
64         I2C_GenerateSTART(i2c_periph, ENABLE);                                              //Sr
65 
66         try = 0;
67         while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))                   //EVT5
68             if (try++ >= TIMEOUT) return -1;
69 
70         I2C_SendData(i2c_periph,frame_head);                                                //Resend FrameHead
71     }
72     else
73     {
74         I2C_Send7bitAddress(i2c_periph, addr << 1, I2C_Direction_Receiver);
75     }
76 
77     try = 0;
78     while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))            //EVT6
79         if (try++ >= TIMEOUT) return -1;
80 
81     while(len-- > 0)
82     {
83 
84         try = 0;
85         while (!I2C_GetFlagStatus(i2c_periph, I2C_FLAG_RXNE))                               //Got ACK For the Last Byte
86             if (try++ >= TIMEOUT) return -1;
87 
88         *(buf++)=I2C_ReceiveData(i2c_periph);
89     }
90 
91     I2C_GenerateSTOP(i2c_periph, ENABLE);
92 }
93 
i2c_write(I2C_TypeDef * i2c_periph,rt_uint16_t addr,rt_uint8_t flags,rt_uint8_t * buf,rt_uint16_t len)94 static int i2c_write(I2C_TypeDef *i2c_periph,
95                             rt_uint16_t addr,
96                             rt_uint8_t flags,
97                             rt_uint8_t *buf,
98                             rt_uint16_t len)
99 {
100     rt_uint16_t try = 0;
101     while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY))
102         if (try++ >= TIMEOUT) return -1;
103 
104     I2C_GenerateSTART(i2c_periph, ENABLE);
105 
106     try = 0;
107     while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT))                       //EVT5
108         if (try++ >= TIMEOUT) return -1;
109 
110     if(flags & RT_I2C_ADDR_10BIT)   //10-bit address mode
111     {
112         I2C_SendData(i2c_periph,0xF0 + (addr >> 8) << 1);                                   //FrameHead 11110XX0
113 
114         try = 0;
115         while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_ADDRESS10))                //EVT9
116             if (try++ >= TIMEOUT) return -1;
117 
118         I2C_SendData(i2c_periph,0xff & addr);
119     }
120     else    //7-bit address mode
121     {
122         I2C_Send7bitAddress(i2c_periph, addr << 1, I2C_Direction_Transmitter);
123     }
124 
125     try = 0;
126     while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))         //EVT6
127         if (try++ >= TIMEOUT) return -1;
128 
129     //Missing Evt8_1 (No definition)
130 
131     while(len-- > 0)
132     {
133         try = 0;
134         while (!I2C_GetFlagStatus(i2c_periph, I2C_FLAG_TXE))                                //Got ACK For the Last Byte
135             if (try++ >= TIMEOUT) return -1;
136 
137         I2C_SendData(i2c_periph,*(buf++));
138     }
139 
140     try = 0;
141     while(!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_BYTE_TRANSMITTING))                  //Last byte sent successfully
142         if (try++ >= TIMEOUT) return -1;
143 
144     I2C_GenerateSTOP(i2c_periph, ENABLE);
145 }
146 
i2c_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)147 rt_size_t i2c_master_xfer(struct rt_i2c_bus_device *bus,
148                             struct rt_i2c_msg msgs[],
149                                     rt_uint32_t num)
150 {
151     struct rt_i2c_msg *msg;
152     struct i2c_bus_device *i2c_bus_dev;
153     rt_uint32_t index;
154 
155     i2c_bus_dev = (struct i2c_bus_device *)bus;
156 
157     for (index = 0; index < num; index++)
158     {
159         msg = &msgs[index];
160         if (msg->flags & RT_I2C_RD)
161         {
162             i2c_read(i2c_bus_dev->periph,
163                           msg->addr,
164                           msg->flags,
165                           msg->len,
166                           msg->buf);
167         }
168         else
169         {
170             i2c_write(i2c_bus_dev->periph,
171                            msg->addr,
172                            msg->flags,
173                            msg->buf,
174                            msg->len);
175         }
176     }
177 
178     return index;
179 }
180 
181 static const struct rt_i2c_bus_device_ops ch32_i2c_ops =
182 {
183         .master_xfer = i2c_master_xfer,
184         .slave_xfer = RT_NULL,                   //Not Used in i2c_core?
185         .i2c_bus_control = RT_NULL
186 };
187 
188 int rt_hw_i2c_init(struct i2c_config *config = &{5000, I2C_DutyCycle_2, 0, I2C_Ack_Disable, I2C_AcknowledgedAddress_7bit})
189 {
190     int result = RT_EOK;
191 
192     GPIO_InitTypeDef GPIO_InitStructure = {0};
193     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
194     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
195 
196     I2C_InitTypeDef I2C_InitTSturcture = {0};
197     I2C_StructInit(&I2C_InitTSturcture);
198     I2C_InitTSturcture.I2C_ClockSpeed = config->clock_speed;
199     I2C_InitTSturcture.I2C_DutyCycle = config->duty_cycle;
200     I2C_InitTSturcture.I2C_OwnAddress1 = config->own_address;
201     I2C_InitTSturcture.I2C_Ack = config->enable_ack ? I2C_Ack_Enable : I2C_Ack_Disable;
202     I2C_InitTSturcture.I2C_AcknowledgedAddress = config->is_7_bit_address ? I2C_AcknowledgedAddress_7bit : I2C_AcknowledgedAddress_10bit;
203 
204 
205 #ifdef BSP_USING_I2C1
206 
207     i2c_bus1.periph = I2C1;
208 
209     //Clock & IO Initialization
210     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
211     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
212 
213     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
214     GPIO_Init(GPIOB, &GPIO_InitStructure);
215 
216     GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
217 
218     //I2C Initialization Config
219     I2C_Init(I2C1, &I2C_InitTSturcture);
220     I2C_Cmd(I2C1, ENABLE);
221 
222     //Hook to RT-Thread
223     i2c_bus1.parent.ops = &ch32_i2c_ops;
224     result += rt_i2c_bus_device_register(&i2c_bus1.parent, "i2c1");
225 
226 #endif
227 
228 #ifdef BSP_USING_I2C2
229 
230     i2c_bus2.periph = I2C2;
231 
232     //Clock & IO Initialization
233     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
234     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
235 
236     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
237     GPIO_Init(GPIOB, &GPIO_InitStructure);
238 
239     //I2C Initialization Config
240     I2C_Init(I2C2, &I2C_InitTSturcture);
241     I2C_Cmd(I2C2, ENABLE);
242 
243     //Hook to RT-Thread
244     i2c_bus2.parent.ops = &ch32_i2c_ops;
245     result += rt_i2c_bus_device_register(&i2c_bus2.parent, "i2c2");
246 
247 #endif
248 
249     return result;
250 }
251 
252 #endif //BSP_USING_HWI2C