1 /*!
2     \file    gd32vf103_i2c.c
3     \brief   I2C driver
4 
5     \version 2019-06-05, V1.0.0, firmware for GD32VF103
6     \version 2020-08-04, V1.1.0, firmware for GD32VF103
7 */
8 
9 /*
10     Copyright (c) 2020, GigaDevice Semiconductor Inc.
11 
12     Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14 
15     1. Redistributions of source code must retain the above copyright notice, this
16        list of conditions and the following disclaimer.
17     2. Redistributions in binary form must reproduce the above copyright notice,
18        this list of conditions and the following disclaimer in the documentation
19        and/or other materials provided with the distribution.
20     3. Neither the name of the copyright holder nor the names of its contributors
21        may be used to endorse or promote products derived from this software without
22        specific prior written permission.
23 
24     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGE.
34 */
35 
36 #include "gd32vf103_i2c.h"
37 
38 /* I2C register bit mask */
39 #define I2C_FLAG_MASK                 ((uint32_t)0x0000FFFFU)             /*!< i2c flag mask */
40 #define I2C_ADDRESS_MASK              ((uint32_t)0x000003FFU)             /*!< i2c address mask */
41 #define I2C_ADDRESS2_MASK             ((uint32_t)0x000000FEU)             /*!< the second i2c address mask */
42 
43 /* I2C register bit offset */
44 #define STAT1_PECV_OFFSET             ((uint32_t)8U)     /* bit offset of PECV in I2C_STAT1 */
45 
46 /*!
47     \brief      reset I2C
48     \param[in]  i2c_periph: I2Cx(x=0,1)
49     \param[out] none
50     \retval     none
51  */
i2c_deinit(uint32_t i2c_periph)52 void i2c_deinit(uint32_t i2c_periph)
53 {
54     switch (i2c_periph) {
55     case I2C0:
56         /* reset I2C0 */
57         rcu_periph_reset_enable(RCU_I2C0RST);
58         rcu_periph_reset_disable(RCU_I2C0RST);
59         break;
60     case I2C1:
61         /* reset I2C1 */
62         rcu_periph_reset_enable(RCU_I2C1RST);
63         rcu_periph_reset_disable(RCU_I2C1RST);
64         break;
65     default:
66         break;
67     }
68 }
69 
70 /*!
71     \brief      configure I2C clock
72     \param[in]  i2c_periph: I2Cx(x=0,1)
73     \param[in]  clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz)
74                           and fast mode plus (up to 1MHz)
75     \param[in]  dutycyc: duty cycle in fast mode or fast mode plus
76                 only one parameter can be selected which is shown as below:
77      \arg        I2C_DTCY_2: T_low/T_high=2
78      \arg        I2C_DTCY_16_9: T_low/T_high=16/9
79     \param[out] none
80     \retval     none
81  */
i2c_clock_config(uint32_t i2c_periph,uint32_t clkspeed,uint32_t dutycyc)82 void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc)
83 {
84     uint32_t pclk1, clkc, freq, risetime;
85     uint32_t temp;
86 
87     pclk1 = rcu_clock_freq_get(CK_APB1);
88     /* I2C peripheral clock frequency */
89     freq = (uint32_t) (pclk1 / 1000000U);
90     if (freq >= I2CCLK_MAX) {
91         freq = I2CCLK_MAX;
92     }
93     temp = I2C_CTL1(i2c_periph);
94     temp &= ~I2C_CTL1_I2CCLK;
95     temp |= freq;
96 
97     I2C_CTL1(i2c_periph) = temp;
98 
99     if (100000U >= clkspeed) {
100         /* the maximum SCL rise time is 1000ns in standard mode */
101         risetime = (uint32_t) ((pclk1 / 1000000U) + 1U);
102         if (risetime >= I2CCLK_MAX) {
103             I2C_RT(i2c_periph) = I2CCLK_MAX;
104         } else if (risetime <= I2CCLK_MIN) {
105             I2C_RT(i2c_periph) = I2CCLK_MIN;
106         } else {
107             I2C_RT(i2c_periph) = risetime;
108         }
109         clkc = (uint32_t) (pclk1 / (clkspeed * 2U));
110         if (clkc < 0x04U) {
111             /* the CLKC in standard mode minmum value is 4 */
112             clkc = 0x04U;
113         }
114         I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);
115 
116     } else if (400000U >= clkspeed) {
117         /* the maximum SCL rise time is 300ns in fast mode */
118         I2C_RT(i2c_periph) = (uint32_t) (((freq * (uint32_t) 300U)/(uint32_t)1000U)+(uint32_t)1U);
119         if (I2C_DTCY_2 == dutycyc){
120             /* I2C duty cycle is 2 */
121             clkc = (uint32_t) (pclk1 / (clkspeed * 3U));
122             I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
123         } else {
124             /* I2C duty cycle is 16/9 */
125             clkc = (uint32_t) (pclk1 / (clkspeed * 25U));
126             I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
127         }
128         if (0U == (clkc & I2C_CKCFG_CLKC)) {
129             /* the CLKC in fast mode minmum value is 1 */
130             clkc |= 0x0001U;
131         }
132         I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
133         I2C_CKCFG(i2c_periph) |= clkc;
134     } else {
135         /* fast mode plus, the maximum SCL rise time is 120ns */
136         I2C_RT (i2c_periph) = (uint32_t) (((freq * (uint32_t) 120U) / (uint32_t) 1000U)+(uint32_t) 1U);
137         if (I2C_DTCY_2 == dutycyc) {
138             /* I2C duty cycle is 2 */
139             clkc = (uint32_t) (pclk1 / (clkspeed * 3U));
140             I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
141         } else {
142             /* I2C duty cycle is 16/9 */
143             clkc = (uint32_t) (pclk1 / (clkspeed * 25U));
144             I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
145         }
146         /* enable fast mode */
147         I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
148         I2C_CKCFG(i2c_periph) |= clkc;
149         /* enable I2C fast mode plus */
150         I2C_FMPCFG(i2c_periph) |= I2C_FMPCFG_FMPEN;
151     }
152 }
153 
154 /*!
155     \brief      configure I2C address
156     \param[in]  i2c_periph: I2Cx(x=0,1)
157     \param[in]  mode:
158                 only one parameter can be selected which is shown as below:
159     \arg        I2C_I2CMODE_ENABLE: I2C mode
160     \arg        I2C_SMBUSMODE_ENABLE: SMBus mode
161     \param[in]  addformat: 7bits or 10bits
162                 only one parameter can be selected which is shown as below:
163     \arg        I2C_ADDFORMAT_7BITS: 7bits
164     \arg        I2C_ADDFORMAT_10BITS: 10bits
165     \param[in]  addr: I2C address
166     \param[out] none
167     \retval     none
168  */
i2c_mode_addr_config(uint32_t i2c_periph,uint32_t mode,uint32_t addformat,uint32_t addr)169 void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode,uint32_t addformat, uint32_t addr)
170 {
171     /* SMBus/I2C mode selected */
172     uint32_t ctl = 0U;
173 
174     ctl = I2C_CTL0(i2c_periph);
175     ctl &= ~(I2C_CTL0_SMBEN);
176     ctl |= mode;
177     I2C_CTL0(i2c_periph) = ctl;
178     /* configure address */
179     addr = addr & I2C_ADDRESS_MASK;
180     I2C_SADDR0(i2c_periph) = (addformat | addr);
181 }
182 
183 /*!
184     \brief      SMBus type selection
185     \param[in]  i2c_periph: I2Cx(x=0,1)
186     \param[in]  type:
187                 only one parameter can be selected which is shown as below:
188     \arg        I2C_SMBUS_DEVICE: device
189     \arg        I2C_SMBUS_HOST: host
190     \param[out] none
191     \retval     none
192  */
i2c_smbus_type_config(uint32_t i2c_periph,uint32_t type)193 void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type)
194 {
195     if (I2C_SMBUS_HOST == type) {
196         I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;
197     } else {
198         I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);
199     }
200 }
201 
202 /*!
203     \brief      whether or not to send an ACK
204     \param[in]  i2c_periph: I2Cx(x=0,1)
205     \param[in]  ack:
206                 only one parameter can be selected which is shown as below:
207     \arg        I2C_ACK_ENABLE: ACK will be sent
208     \arg        I2C_ACK_DISABLE: ACK will not be sent
209     \param[out] none
210     \retval     none
211  */
i2c_ack_config(uint32_t i2c_periph,uint32_t ack)212 void i2c_ack_config(uint32_t i2c_periph, uint32_t ack)
213 {
214     if (I2C_ACK_ENABLE == ack) {
215         I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN;
216     } else {
217         I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN);
218     }
219 }
220 
221 /*!
222     \brief      configure I2C POAP position
223     \param[in]  i2c_periph: I2Cx(x=0,1)
224     \param[in]  pos:
225                 only one parameter can be selected which is shown as below:
226     \arg        I2C_ACKPOS_CURRENT: whether to send ACK or not for the current
227     \arg        I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte
228     \param[out] none
229     \retval     none
230  */
i2c_ackpos_config(uint32_t i2c_periph,uint32_t pos)231 void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos)
232 {
233     /* configure I2C POAP position */
234     if (I2C_ACKPOS_NEXT == pos) {
235         I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP;
236     } else {
237         I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP);
238     }
239 }
240 
241 /*!
242     \brief      master sends slave address
243     \param[in]  i2c_periph: I2Cx(x=0,1)
244     \param[in]  addr: slave address
245     \param[in]  trandirection: transmitter or receiver
246                 only one parameter can be selected which is shown as below:
247     \arg        I2C_TRANSMITTER: transmitter
248     \arg        I2C_RECEIVER:    receiver
249     \param[out] none
250     \retval     none
251  */
i2c_master_addressing(uint32_t i2c_periph,uint32_t addr,uint32_t trandirection)252 void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr,uint32_t trandirection)
253 {
254     /* master is a transmitter or a receiver */
255     if (I2C_TRANSMITTER == trandirection) {
256         addr = addr & I2C_TRANSMITTER;
257     } else {
258         addr = addr | I2C_RECEIVER;
259     }
260     /* send slave address */
261     I2C_DATA(i2c_periph) = addr;
262 }
263 
264 /*!
265     \brief      enable dual-address mode
266     \param[in]  i2c_periph: I2Cx(x=0,1)
267     \param[in]  dualaddr: the second address in dual-address mode
268     \param[out] none
269     \retval     none
270 */
i2c_dualaddr_enable(uint32_t i2c_periph,uint32_t dualaddr)271 void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t dualaddr)
272 {
273     /* configure address */
274     dualaddr = dualaddr & I2C_ADDRESS2_MASK;
275     I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | dualaddr);
276 }
277 
278 /*!
279     \brief      disable dual-address mode
280     \param[in]  i2c_periph: I2Cx(x=0,1)
281     \param[out] none
282     \retval     none
283 */
i2c_dualaddr_disable(uint32_t i2c_periph)284 void i2c_dualaddr_disable(uint32_t i2c_periph)
285 {
286     I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN);
287 }
288 
289 /*!
290     \brief      enable I2C
291     \param[in]  i2c_periph: I2Cx(x=0,1)
292     \param[out] none
293     \retval     none
294  */
i2c_enable(uint32_t i2c_periph)295 void i2c_enable(uint32_t i2c_periph)
296 {
297     I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN;
298 }
299 
300 /*!
301     \brief      disable I2C
302     \param[in]  i2c_periph: I2Cx(x=0,1)
303     \param[out] none
304     \retval     none
305  */
i2c_disable(uint32_t i2c_periph)306 void i2c_disable(uint32_t i2c_periph)
307 {
308     I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN);
309 }
310 
311 /*!
312     \brief      generate a START condition on I2C bus
313     \param[in]  i2c_periph: I2Cx(x=0,1)
314     \param[out] none
315     \retval     none
316  */
i2c_start_on_bus(uint32_t i2c_periph)317 void i2c_start_on_bus(uint32_t i2c_periph)
318 {
319     I2C_CTL0(i2c_periph) |= I2C_CTL0_START;
320 }
321 
322 /*!
323     \brief      generate a STOP condition on I2C bus
324     \param[in]  i2c_periph: I2Cx(x=0,1)
325     \param[out] none
326     \retval     none
327  */
i2c_stop_on_bus(uint32_t i2c_periph)328 void i2c_stop_on_bus(uint32_t i2c_periph)
329 {
330     I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP;
331 }
332 
333 /*!
334     \brief      I2C transmit data function
335     \param[in]  i2c_periph: I2Cx(x=0,1)
336     \param[in]  data: data of transmission
337     \param[out] none
338     \retval     none
339  */
i2c_data_transmit(uint32_t i2c_periph,uint8_t data)340 void i2c_data_transmit(uint32_t i2c_periph, uint8_t data)
341 {
342     I2C_DATA(i2c_periph) = DATA_TRANS(data);
343 }
344 
345 /*!
346     \brief      I2C receive data function
347     \param[in]  i2c_periph: I2Cx(x=0,1)
348     \param[out] none
349     \retval     data of received
350  */
i2c_data_receive(uint32_t i2c_periph)351 uint8_t i2c_data_receive(uint32_t i2c_periph)
352 {
353     return (uint8_t) DATA_RECV(I2C_DATA(i2c_periph));
354 }
355 
356 /*!
357     \brief      enable I2C DMA mode
358     \param[in]  i2c_periph: I2Cx(x=0,1)
359     \param[in]  dmastate:
360                 only one parameter can be selected which is shown as below:
361     \arg        I2C_DMA_ON: DMA mode enable
362     \arg        I2C_DMA_OFF: DMA mode disable
363     \param[out] none
364     \retval     none
365  */
i2c_dma_enable(uint32_t i2c_periph,uint32_t dmastate)366 void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate)
367 {
368     /* configure I2C DMA function */
369     uint32_t ctl = 0U;
370 
371     ctl = I2C_CTL1(i2c_periph);
372     ctl &= ~(I2C_CTL1_DMAON);
373     ctl |= dmastate;
374     I2C_CTL1(i2c_periph) = ctl;
375 }
376 
377 /*!
378     \brief      configure whether next DMA EOT is DMA last transfer or not
379     \param[in]  i2c_periph: I2Cx(x=0,1)
380     \param[in]  dmalast:
381                 only one parameter can be selected which is shown as below:
382     \arg        I2C_DMALST_ON: next DMA EOT is the last transfer
383     \arg        I2C_DMALST_OFF: next DMA EOT is not the last transfer
384     \param[out] none
385     \retval     none
386  */
i2c_dma_last_transfer_config(uint32_t i2c_periph,uint32_t dmalast)387 void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast)
388 {
389     /* configure DMA last transfer */
390     uint32_t ctl = 0U;
391 
392     ctl = I2C_CTL1(i2c_periph);
393     ctl &= ~(I2C_CTL1_DMALST);
394     ctl |= dmalast;
395     I2C_CTL1(i2c_periph) = ctl;
396 }
397 
398 /*!
399     \brief      whether to stretch SCL low when data is not ready in slave mode
400     \param[in]  i2c_periph: I2Cx(x=0,1)
401     \param[in]  stretchpara:
402                 only one parameter can be selected which is shown as below:
403     \arg        I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled
404     \arg        I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled
405     \param[out] none
406     \retval     none
407  */
i2c_stretch_scl_low_config(uint32_t i2c_periph,uint32_t stretchpara)408 void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
409 {
410     /* configure I2C SCL strerching enable or disable */
411     uint32_t ctl = 0U;
412 
413     ctl = I2C_CTL0(i2c_periph);
414     ctl &= ~(I2C_CTL0_SS);
415     ctl |= stretchpara;
416     I2C_CTL0(i2c_periph) = ctl;
417 }
418 
419 /*!
420     \brief      whether or not to response to a general call
421     \param[in]  i2c_periph: I2Cx(x=0,1)
422     \param[in]  gcallpara:
423                 only one parameter can be selected which is shown as below:
424     \arg        I2C_GCEN_ENABLE: slave will response to a general call
425     \arg        I2C_GCEN_DISABLE: slave will not response to a general call
426     \param[out] none
427     \retval     none
428  */
i2c_slave_response_to_gcall_config(uint32_t i2c_periph,uint32_t gcallpara)429 void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
430 {
431     /* configure slave response to a general call enable or disable */
432     uint32_t ctl = 0U;
433 
434     ctl = I2C_CTL0(i2c_periph);
435     ctl &= ~(I2C_CTL0_GCEN);
436     ctl |= gcallpara;
437     I2C_CTL0(i2c_periph) = ctl;
438 }
439 
440 /*!
441     \brief      software reset I2C
442     \param[in]  i2c_periph: I2Cx(x=0,1)
443     \param[in]  sreset:
444                 only one parameter can be selected which is shown as below:
445     \arg        I2C_SRESET_SET: I2C is under reset
446     \arg        I2C_SRESET_RESET: I2C is not under reset
447     \param[out] none
448     \retval     none
449  */
i2c_software_reset_config(uint32_t i2c_periph,uint32_t sreset)450 void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
451 {
452     /* modify CTL0 and configure software reset I2C state */
453     uint32_t ctl = 0U;
454 
455     ctl = I2C_CTL0(i2c_periph);
456     ctl &= ~(I2C_CTL0_SRESET);
457     ctl |= sreset;
458     I2C_CTL0(i2c_periph) = ctl;
459 }
460 
461 /*!
462     \brief      I2C PEC calculation on or off
463     \param[in]  i2c_periph: I2Cx(x=0,1)
464     \param[in]  pecpara:
465                 only one parameter can be selected which is shown as below:
466     \arg        I2C_PEC_ENABLE: PEC calculation on
467     \arg        I2C_PEC_DISABLE: PEC calculation off
468     \param[out] none
469     \retval     none
470  */
i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate)471 void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate)
472 {
473     /* on/off PEC calculation */
474     uint32_t ctl = 0U;
475 
476     ctl = I2C_CTL0(i2c_periph);
477     ctl &= ~(I2C_CTL0_PECEN);
478     ctl |= pecstate;
479     I2C_CTL0(i2c_periph) = ctl;
480 }
481 
482 /*!
483     \brief      I2C whether to transfer PEC value
484     \param[in]  i2c_periph: I2Cx(x=0,1)
485     \param[in]  pecpara:
486                 only one parameter can be selected which is shown as below:
487     \arg        I2C_PECTRANS_ENABLE: transfer PEC
488     \arg        I2C_PECTRANS_DISABLE: not transfer PEC
489     \param[out] none
490     \retval     none
491  */
i2c_pec_transfer_enable(uint32_t i2c_periph,uint32_t pecpara)492 void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara)
493 {
494     /* whether to transfer PEC */
495     uint32_t ctl = 0U;
496 
497     ctl = I2C_CTL0(i2c_periph);
498     ctl &= ~(I2C_CTL0_PECTRANS);
499     ctl |= pecpara;
500     I2C_CTL0(i2c_periph) = ctl;
501 }
502 
503 /*!
504     \brief      get packet error checking value
505     \param[in]  i2c_periph: I2Cx(x=0,1)
506     \param[out] none
507     \retval     PEC value
508  */
i2c_pec_value_get(uint32_t i2c_periph)509 uint8_t i2c_pec_value_get(uint32_t i2c_periph)
510 {
511     return (uint8_t) ((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>> STAT1_PECV_OFFSET);
512 }
513 
514 /*!
515     \brief      I2C issue alert through SMBA pin
516     \param[in]  i2c_periph: I2Cx(x=0,1)
517     \param[in]  smbuspara:
518                 only one parameter can be selected which is shown as below:
519     \arg        I2C_SALTSEND_ENABLE: issue alert through SMBA pin
520     \arg        I2C_SALTSEND_DISABLE: not issue alert through SMBA pin
521     \param[out] none
522     \retval     none
523  */
i2c_smbus_issue_alert(uint32_t i2c_periph,uint32_t smbuspara)524 void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara)
525 {
526     /* issue alert through SMBA pin configure*/
527     uint32_t ctl = 0U;
528 
529     ctl = I2C_CTL0(i2c_periph);
530     ctl &= ~(I2C_CTL0_SALT);
531     ctl |= smbuspara;
532     I2C_CTL0(i2c_periph) = ctl;
533 }
534 
535 /*!
536     \brief      enable or disable I2C ARP protocol in SMBus switch
537     \param[in]  i2c_periph: I2Cx(x=0,1)
538     \param[in]  arpstate:
539                 only one parameter can be selected which is shown as below:
540     \arg        I2C_ARP_ENABLE: enable ARP
541     \arg        I2C_ARP_DISABLE: disable ARP
542     \param[out] none
543     \retval     none
544  */
i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate)545 void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate)
546 {
547     /* enable or disable I2C ARP protocol*/
548     uint32_t ctl = 0U;
549 
550     ctl = I2C_CTL0(i2c_periph);
551     ctl &= ~(I2C_CTL0_ARPEN);
552     ctl |= arpstate;
553     I2C_CTL0(i2c_periph) = ctl;
554 }
555 
556 /*!
557     \brief      check I2C flag is set or not
558     \param[in]  i2c_periph: I2Cx(x=0,1)
559     \param[in]  flag: I2C flags, refer to i2c_flag_enum
560                 only one parameter can be selected which is shown as below:
561     \arg        I2C_FLAG_SBSEND: start condition send out
562     \arg        I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
563     \arg        I2C_FLAG_BTC: byte transmission finishes
564     \arg        I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode
565     \arg        I2C_FLAG_STPDET: stop condition detected in slave mode
566     \arg        I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving
567     \arg        I2C_FLAG_TBE: I2C_DATA is empty during transmitting
568     \arg        I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
569     \arg        I2C_FLAG_LOSTARB: arbitration lost in master mode
570     \arg        I2C_FLAG_AERR: acknowledge error
571     \arg        I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode
572     \arg        I2C_FLAG_PECERR: PEC error when receiving data
573     \arg        I2C_FLAG_SMBTO: timeout signal in SMBus mode
574     \arg        I2C_FLAG_SMBALT: SMBus alert status
575     \arg        I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode
576     \arg        I2C_FLAG_I2CBSY: busy flag
577     \arg        I2C_FLAG_TR: whether the I2C is a transmitter or a receiver
578     \arg        I2C_FLAG_RXGC: general call address (00h) received
579     \arg        I2C_FLAG_DEFSMB: default address of SMBus device
580     \arg        I2C_FLAG_HSTSMB: SMBus host header detected in slave mode
581     \arg        I2C_FLAG_DUMODF: dual flag in slave mode indicating which address is matched in dual-address mode
582     \param[out] none
583     \retval     FlagStatus: SET or RESET
584  */
i2c_flag_get(uint32_t i2c_periph,i2c_flag_enum flag)585 FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
586 {
587     if (RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) {
588         return SET;
589     } else {
590         return RESET;
591     }
592 }
593 
594 /*!
595     \brief      clear I2C flag
596     \param[in]  i2c_periph: I2Cx(x=0,1)
597     \param[in]  flag: I2C flags, refer to i2c_flag_enum
598                 only one parameter can be selected which is shown as below:
599     \arg        I2C_FLAG_SMBALT: SMBus Alert status
600     \arg        I2C_FLAG_SMBTO: timeout signal in SMBus mode
601     \arg        I2C_FLAG_PECERR: PEC error when receiving data
602     \arg        I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
603     \arg        I2C_FLAG_AERR: acknowledge error
604     \arg        I2C_FLAG_LOSTARB: arbitration lost in master mode
605     \arg        I2C_FLAG_BERR: a bus error
606     \arg        I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1
607     \param[out] none
608     \retval     none
609  */
i2c_flag_clear(uint32_t i2c_periph,i2c_flag_enum flag)610 void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag)
611 {
612     if (I2C_FLAG_ADDSEND == flag) {
613         /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
614         I2C_STAT0(i2c_periph);
615         I2C_STAT1(i2c_periph);
616     } else {
617         I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag));
618     }
619 }
620 
621 /*!
622     \brief      enable I2C interrupt
623     \param[in]  i2c_periph: I2Cx(x=0,1)
624     \param[in]  interrupt: I2C interrupts, refer to i2c_interrupt_enum
625                 only one parameter can be selected which is shown as below:
626     \arg        I2C_INT_ERR: error interrupt enable
627     \arg        I2C_INT_EV: event interrupt enable
628     \arg        I2C_INT_BUF: buffer interrupt enable
629     \param[out] none
630     \retval     none
631  */
i2c_interrupt_enable(uint32_t i2c_periph,i2c_interrupt_enum interrupt)632 void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
633 {
634     I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt));
635 }
636 
637 /*!
638     \brief      disable I2C interrupt
639     \param[in]  i2c_periph: I2Cx(x=0,1)
640     \param[in]  interrupt: I2C interrupts, refer to i2c_flag_enum
641                 only one parameter can be selected which is shown as below:
642     \arg        I2C_INT_ERR: error interrupt enable
643     \arg        I2C_INT_EV: event interrupt enable
644     \arg        I2C_INT_BUF: buffer interrupt enable
645     \param[out] none
646     \retval     none
647  */
i2c_interrupt_disable(uint32_t i2c_periph,i2c_interrupt_enum interrupt)648 void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
649 {
650     I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt));
651 }
652 
653 /*!
654     \brief      check I2C interrupt flag
655     \param[in]  i2c_periph: I2Cx(x=0,1)
656     \param[in]  int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
657                 only one parameter can be selected which is shown as below:
658     \arg        I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag
659     \arg        I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
660     \arg        I2C_INT_FLAG_BTC: byte transmission finishes
661     \arg        I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag
662     \arg        I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag
663     \arg        I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag
664     \arg        I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag
665     \arg        I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
666     \arg        I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
667     \arg        I2C_INT_FLAG_AERR: acknowledge error interrupt flag
668     \arg        I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
669     \arg        I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
670     \arg        I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
671     \arg        I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag
672     \param[out] none
673     \retval     FlagStatus: SET or RESET
674  */
i2c_interrupt_flag_get(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag)675 FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag)
676 {
677     uint32_t intenable = 0U, flagstatus = 0U, bufie;
678 
679     /* check BUFIE */
680     bufie = I2C_CTL1(i2c_periph) & I2C_CTL1_BUFIE;
681 
682     /* get the interrupt enable bit status */
683     intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag)));
684     /* get the corresponding flag bit status */
685     flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag)& BIT(I2C_BIT_POS2(int_flag)));
686 
687     if ((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) {
688         if (intenable && bufie) {
689             intenable = 1U;
690         } else {
691             intenable = 0U;
692         }
693     }
694     if ((0U != flagstatus) && (0U != intenable)) {
695         return SET;
696     } else {
697         return RESET;
698     }
699 }
700 
701 /*!
702     \brief      clear I2C interrupt flag
703     \param[in]  i2c_periph: I2Cx(x=0,1)
704     \param[in]  int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
705                 only one parameter can be selected which is shown as below:
706     \arg        I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
707     \arg        I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
708     \arg        I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
709     \arg        I2C_INT_FLAG_AERR: acknowledge error interrupt flag
710     \arg        I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
711     \arg        I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
712     \arg        I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
713     \arg        I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag
714     \param[out] none
715     \retval     none
716  */
i2c_interrupt_flag_clear(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag)717 void i2c_interrupt_flag_clear(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag)
718 {
719     if (I2C_INT_FLAG_ADDSEND == int_flag) {
720         /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
721         I2C_STAT0(i2c_periph);
722         I2C_STAT1(i2c_periph);
723     } else {
724         I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag));
725     }
726 }
727