1 /*
2 * Copyright 2021 MindMotion Microelectronics Co., Ltd.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "hal_i2c.h"
9
10 /* Configure I2C speed to ordinary speed. */
I2C_CalcBandrate(I2C_Type * I2Cx,uint32_t clk,uint32_t bandrate)11 static bool I2C_CalcBandrate(I2C_Type * I2Cx, uint32_t clk, uint32_t bandrate)
12 {
13 /*
14 * SCLH = (xSHR + 12) * I2C_CLK + tSYNC1;
15 * SCLL = (xSLR + 1) * I2C_CLK + tSYNC2;
16 * tSYNC1 & tSYNC2 equal 0 ~ 1 clk.
17 */
18 if ( (clk / 24u) < bandrate ) /* the system clock cannot meet the baud rate requirement. */
19 {
20 return false;
21 }
22 else
23 {
24 uint32_t tmp = clk / bandrate;
25 I2Cx->SSHR = tmp / 2u - 12u; /* Configure high level count in normal speed. */
26 I2Cx->SSLR = tmp / 2u - 1u; /* Configure low level count in normal speed. */
27 I2Cx->FSHR = tmp / 2u - 14u; /* Configure high level count in fast speed. */
28 I2Cx->FSLR = tmp / 2u - 3u; /* Configure low level count in fast speed. */
29 return true;
30 }
31 }
32
33 /* Initialize I2C, Initialization failure return false, Initialization success return true. */
I2C_InitMaster(I2C_Type * I2Cx,I2C_Master_Init_Type * init)34 bool I2C_InitMaster(I2C_Type * I2Cx, I2C_Master_Init_Type * init)
35 {
36 I2Cx->ENR &= ~I2C_ENR_ENABLE_MASK; /* Disable I2C. */
37
38 if ( !I2C_CalcBandrate(I2Cx, init->ClockFreqHz, init->BaudRate) ) /* The system clock cannot meet the baud rate requirement. */
39 {
40 return false;
41 }
42
43 I2Cx->CR = I2C_CR_SPEED(1u);
44
45 /* Setup I2C. */
46 I2Cx->CR &= ~I2C_CR_MASTER10_MASK; /* Address format. */
47 I2Cx->CR |= I2C_CR_RESTART_MASK /* Generate restart signal. */
48 | I2C_CR_DISSLAVE_MASK /* Disable slave module. */
49 | I2C_CR_REPEN_MASK /* Enable sending restart condition. */
50 | I2C_CR_EMPINT_MASK /* Control tx_empty interrupt generation. */
51 | I2C_CR_MASTER_MASK; /* Enable master module. */
52
53 I2Cx->IMR = 0u; /* Close all interrupts. */
54 I2Cx->RXTLR = 0u; /* Configure the sending receive value. */
55 I2Cx->TXTLR = 0u; /* Configure the sending threshold value. */
56 return true; /* Initialize I2C succeeded, return true. */
57 }
58
59 /* Enable I2C. */
I2C_Enable(I2C_Type * I2Cx,bool enable)60 void I2C_Enable(I2C_Type * I2Cx, bool enable)
61 {
62 if (enable)
63 {
64 I2Cx->ENR |= I2C_ENR_ENABLE_MASK;
65 }
66 else
67 {
68 I2Cx->ENR &= ~I2C_ENR_ENABLE_MASK;
69 }
70 }
71
72 /* Configuration the target device address. */
I2C_SetTargetAddr(I2C_Type * I2Cx,uint8_t addr)73 void I2C_SetTargetAddr(I2C_Type * I2Cx, uint8_t addr)
74 {
75 I2Cx->TAR = I2C_TAR_ADDR(addr);
76 }
77
78 /* Get I2C target device address. */
I2C_GetTargetAddr(I2C_Type * I2Cx)79 uint16_t I2C_GetTargetAddr(I2C_Type * I2Cx)
80 {
81 return (I2Cx->TAR & I2C_TAR_ADDR_MASK);
82 }
83
84 /* Put data to target device. */
I2C_PutData(I2C_Type * I2Cx,uint8_t val)85 void I2C_PutData(I2C_Type * I2Cx, uint8_t val)
86 {
87 I2Cx->DR = I2C_DR_DAT(val);
88 }
89
90 /* Control read-write bit to prepare to read data. */
I2C_PrepareToGetData(I2C_Type * I2Cx)91 void I2C_PrepareToGetData(I2C_Type * I2Cx)
92 {
93 I2Cx->DR = I2C_DR_CMD_MASK;
94 }
95
96 /* Get the data received by target device. */
I2C_GetData(I2C_Type * I2Cx)97 uint8_t I2C_GetData(I2C_Type * I2Cx)
98 {
99 return ( (uint8_t)I2Cx->DR );
100 }
101
102 /* Get the current status flags of the I2C module. */
I2C_GetStatus(I2C_Type * I2Cx)103 uint32_t I2C_GetStatus(I2C_Type * I2Cx)
104 {
105 return I2Cx->SR;
106 }
107
108 /* Prepare for the stop, when transfer finish. */
I2C_Stop(I2C_Type * I2Cx)109 void I2C_Stop(I2C_Type * I2Cx)
110 {
111 I2Cx->ENR |= I2C_ENR_ABORT_MASK; /* Prepare for the stop. */
112 I2Cx->TXABRT; /* Read register to release tx fifo. */
113 }
114
115 /* Enable I2C interrupt. */
I2C_EnableInterrupts(I2C_Type * I2Cx,uint32_t interrupts,bool enable)116 void I2C_EnableInterrupts(I2C_Type * I2Cx, uint32_t interrupts, bool enable)
117 {
118 if (enable)
119 {
120 I2Cx->IMR |= interrupts;
121 }
122 else
123 {
124 I2Cx->IMR &= ~interrupts;
125 }
126 }
127
128 /* Get the current enabled interrupts the I2C module. */
I2C_GetEnabledInterrupts(I2C_Type * I2Cx)129 uint32_t I2C_GetEnabledInterrupts(I2C_Type * I2Cx)
130 {
131 return I2Cx->IMR;
132 }
133
134 /* Get the I2C interrupt status flags of the I2C module. */
I2C_GetInterruptStatus(I2C_Type * I2Cx)135 uint32_t I2C_GetInterruptStatus(I2C_Type * I2Cx)
136 {
137 return (I2Cx->RAWISR & I2Cx->IMR); /* To ensure that the acquired interrupt is an enabled interrupt. */
138 }
139
140 /* Clear I2C interrupt status. */
I2C_ClearInterruptStatus(I2C_Type * I2Cx,uint32_t interrupts)141 void I2C_ClearInterruptStatus(I2C_Type * I2Cx, uint32_t interrupts)
142 {
143 if ( (I2C_INT_RX_UNDER & interrupts) != 0u ) /* Clear receive buffer under status. */
144 {
145 I2Cx->RXUNDER;
146 }
147 if ( (I2C_INT_TX_ABORT & interrupts) != 0u ) /* Clear I2C transmit abort status. */
148 {
149 I2Cx->TXABRT;
150 }
151 if ( (I2C_INT_ACTIVE & interrupts) != 0u ) /* Clear I2C interface activation status. */
152 {
153 I2Cx->ACTIV;
154 }
155 if ( (I2C_INT_STOP & interrupts) != 0u ) /* Clear I2C stop condition detection status. */
156 {
157 I2Cx->STOP;
158 }
159 if ( (I2C_INT_START & interrupts) != 0u ) /* Clear I2C start condition detection status. */
160 {
161 I2Cx->START;
162 }
163 }
164
165 /* Performs polling tx. */
I2C_MasterWriteBlocking(I2C_Type * I2Cx,I2C_MasterXfer_Type * xfer)166 bool I2C_MasterWriteBlocking(I2C_Type * I2Cx, I2C_MasterXfer_Type * xfer)
167 {
168 /* Put register address. */
169 I2C_PutData(I2Cx, xfer->TxBuf[0u]);
170
171 uint32_t waittime1 = xfer->WaitTimes;
172 /* Wait to tx fifo empty. */
173 while ( (0u == (I2C_GetStatus(I2Cx) & I2C_STATUS_TX_EMPTY) ) && (0u != waittime1) )
174 {
175 waittime1--;
176 }
177 if (0u == waittime1) /* I2C write register address timeout. */
178 {
179 return false;
180 }
181
182 uint32_t waittime2 = xfer->WaitTimes;
183 /* Write data to target device. */
184 for (uint32_t i = 1u; i < xfer->TxLen; i++)
185 {
186 I2C_PutData(I2Cx, xfer->TxBuf[i]);
187
188 while ( ( 0u == (I2C_GetStatus(I2Cx) & I2C_STATUS_TX_EMPTY) ) && (0u != waittime2) ) /* Wait to tx fifo empty. */
189 {
190 waittime2--;
191 }
192 if (0u == waittime2) /* I2C write timeout. */
193 {
194 return false;
195 }
196 }
197
198 I2C_Stop(I2Cx); /* Prepare to stop send data. */
199
200 uint32_t waittime3 = xfer->WaitTimes;
201 /* Wait to I2C not active, which means stop is taking effect. */
202 while ( (I2C_GetStatus(I2Cx) & I2C_STATUS_ACTIVE) && (0u != waittime3) )
203 {
204 waittime3--;
205 }
206 if (0u == waittime3) /* The wait operation is timeout. */
207 {
208 return false;
209 }
210
211 /* Clear fifo and flags. */
212 I2C1->ICR;
213 I2C1->TXABRT;
214 return true;
215 }
216
217 /* Performs polling rx. */
I2C_MasterReadBlocking(I2C_Type * I2Cx,I2C_MasterXfer_Type * xfer)218 bool I2C_MasterReadBlocking(I2C_Type * I2Cx, I2C_MasterXfer_Type * xfer)
219 {
220 I2C_PutData(I2Cx, xfer->TxBuf[0u]); /* Put device register address. */
221
222 uint32_t waittime1 = xfer->WaitTimes;
223 while ( ( 0u == (I2C_GetStatus(I2Cx) & I2C_STATUS_TX_EMPTY) ) && (0u != waittime1) ) /* Wait to tx fifo empty. */
224 {
225 waittime1--;
226 }
227 if (0u == waittime1)
228 {
229 return false;
230 }
231
232 /* read data from target device. */
233 for (uint32_t i = 0u; i < xfer->RxLen; i++)
234 {
235 I2C_PrepareToGetData(I2Cx); /* Swich read-write bit, prepare to get data. */
236
237 while ( 0u == (I2C_GetStatus(I2Cx) & I2C_STATUS_RX_NOTEMPTY) ) /* Wait to rx fifo not empty. */
238 {
239 if ( 0u == (I2C_GetStatus(I2Cx) & I2C_STATUS_ACTIVE) ) /* Receive is active. */
240 {
241 return false;
242 }
243 }
244 xfer->RxBuf[i] = I2C_GetData(I2Cx);
245 }
246
247 I2C_Stop(I2Cx); /* Prepare to stop I2C. */
248
249 uint32_t waittime2 = xfer->WaitTimes;
250 while ( (I2C_GetStatus(I2Cx) & I2C_STATUS_ACTIVE) && (0u != waittime2) ) /* Wait I2C not active, which means stop being effective. */
251 {
252 waittime2--;
253 }
254 if (0u == waittime2)
255 {
256 return false;
257 }
258
259 /* Clear fifo and flags. */
260 I2C1->ICR;
261 I2C1->TXABRT;
262
263 return true;
264 }
265
266 /* I2C master interrupt transfer of the I2C module. */
I2C_MasterXfer(I2C_Type * I2Cx,I2C_MasterXfer_Type * xfer)267 void I2C_MasterXfer(I2C_Type * I2Cx, I2C_MasterXfer_Type * xfer)
268 {
269 I2C_PutData(I2Cx, (uint8_t)xfer->TxBuf[0u]); /* Put target register address. */
270 I2C_EnableInterrupts(I2Cx, I2C_INT_TX_EMPTY | I2C_INT_TX_ABORT | I2C_INT_STOP, true); /* Enable tx required interrupt. */
271 xfer->TxIdx = 1u; /* One data has been sent. */
272 xfer->RxIdx = 0u;
273 xfer->TxLen--;
274 }
275
276 /* I2C Master handler. */
I2C_MasterXferHandler(I2C_Type * I2Cx,I2C_MasterXfer_Type * xfer,uint32_t interrupts)277 void I2C_MasterXferHandler(I2C_Type * I2Cx, I2C_MasterXfer_Type * xfer, uint32_t interrupts)
278 {
279 if ( 0u != (interrupts & I2C_INT_TX_ABORT) ) /* Early termination of program. */
280 {
281 I2C_EnableInterrupts(I2Cx, I2C_INT_TX_EMPTY | I2C_INT_TX_ABORT | I2C_INT_STOP, false); /* Clear the interrupt used for tx. */
282 if (NULL != xfer->AbortCallback)
283 {
284 xfer->AbortCallback(xfer); /* Use abort call back. */
285 }
286 }
287 else if ( 0u != (interrupts & I2C_INT_TX_EMPTY) ) /* Tx fifo is empty, can send data. */
288 {
289 if (I2C_Direction_Rx == xfer->Direction) /* The current operation is receive, the register address has been sent. */
290 {
291 I2C_EnableInterrupts(I2Cx, I2C_INT_TX_EMPTY | I2C_INT_TX_ABORT, false); /* Clear tx interrupt. */
292 I2C_EnableInterrupts(I2Cx, I2C_INT_RX_NOTEMPTY, true); /* Enable receive required interrupt. */
293 if (0u != xfer->RxLen) /* The data to be received is not 0. */
294 {
295 I2C_PrepareToGetData(I2Cx); /* Prepare to get data. */
296 xfer->RxLen--;
297 }
298 else
299 {
300 I2C_Stop(I2Cx); /* No more transmition, prepare to stop. */
301 }
302 }
303 else
304 {
305 if (0u == xfer->TxLen) /* Tx finish. */
306 {
307 I2C_EnableInterrupts(I2Cx, I2C_INT_TX_EMPTY | I2C_INT_TX_ABORT, false); /* Clear Tx interrupt. */
308 I2C_Stop(I2Cx); /* Prepare to stop. */
309 }
310 else
311 {
312 xfer->TxLen--;
313 I2C_PutData(I2Cx, xfer->TxBuf[xfer->TxIdx++]); /* Tx is not over, continue to put data. */
314 }
315 }
316 }
317 else if ( 0u != (interrupts & I2C_INT_RX_NOTEMPTY) ) /* Receive interrupt. */
318 {
319 if (0u == xfer->RxLen) /* Receive finish. */
320 {
321 xfer->RxBuf[xfer->RxIdx++] = I2C_GetData(I2Cx); /* Get last data from I2C bus. */
322 I2C_EnableInterrupts(I2Cx, I2C_INT_RX_NOTEMPTY, false); /* Clear receive interrupt. */
323 I2C_Stop(I2Cx); /* Prepare to stop. */
324 }
325 else
326 {
327 xfer->RxLen--; /* Current count length count -1. */
328 xfer->RxBuf[xfer->RxIdx++] = I2C_GetData(I2Cx); /* Receive is not over, continue to get data. */
329 I2C_PrepareToGetData(I2Cx); /* Prepare to get data. */
330 }
331 }
332 else if ( 0u != (interrupts & I2C_INT_STOP) ) /* Xfer stop. */
333 {
334 I2C_EnableInterrupts(I2Cx, I2C_INT_STOP, false); /* Clear stop interrupt. */
335 if ( (0u != xfer->TxLen) || (0u != xfer->RxLen) ) /* The transmission was not completed but terminated. */
336 {
337 if (NULL != xfer->AbortCallback)
338 {
339 xfer->AbortCallback(xfer); /* Early termination of program, abort callback. */
340 I2C1->ICR;
341 I2C1->TXABRT; /* Clear FIFO. */
342 }
343 }
344 else
345 {
346 if (NULL != xfer->DoneCallback)
347 {
348 xfer->DoneCallback(xfer); /* Transmission finish and stop, xfer done callback. */
349 I2C1->ICR;
350 I2C1->TXABRT; /* Clear FIFO. */
351 }
352 }
353 }
354 }
355
356 /* EOF. */
357
358