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