1 /*!
2     \file    gd32e10x_i2c.c
3     \brief   I2C driver
4 
5     \version 2017-12-26, V1.0.0, firmware for GD32E10x
6     \version 2019-04-16, V1.0.1, firmware for GD32E10x
7     \version 2020-09-30, V1.1.0, firmware for GD32E10x
8     \version 2020-12-31, V1.2.0, firmware for GD32E10x
9     \version 2022-06-30, V1.3.0, firmware for GD32E10x
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 "gd32e10x_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)
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     default:
69         break;
70     }
71 }
72 
73 /*!
74     \brief      configure I2C clock
75     \param[in]  i2c_periph: I2Cx(x=0,1)
76     \param[in]  clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz)
77                           and fast mode plus (up to 1MHz)
78     \param[in]  dutycyc: duty cycle in fast mode or fast mode plus, and only I2C_DTCY_2 can be selected in standard mode
79                 only one parameter can be selected which is shown as below:
80       \arg        I2C_DTCY_2: T_low/T_high=2
81       \arg        I2C_DTCY_16_9: T_low/T_high=16/9
82     \param[out] none
83     \retval     none
84 */
i2c_clock_config(uint32_t i2c_periph,uint32_t clkspeed,uint32_t dutycyc)85 void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc)
86 {
87     uint32_t pclk1, clkc, freq, risetime;
88     uint32_t temp;
89 
90     pclk1 = rcu_clock_freq_get(CK_APB1);
91     /* I2C peripheral clock frequency */
92     freq = (uint32_t)(pclk1 / 1000000U);
93     if(freq >= I2CCLK_MAX) {
94         freq = I2CCLK_MAX;
95     }
96     temp = I2C_CTL1(i2c_periph);
97     temp &= ~I2C_CTL1_I2CCLK;
98     temp |= freq;
99 
100     I2C_CTL1(i2c_periph) = temp;
101 
102     if(100000U >= clkspeed) {
103         /* the maximum SCL rise time is 1000ns in standard mode */
104         risetime = (uint32_t)((pclk1 / 1000000U) + 1U);
105         if(risetime >= I2CCLK_MAX) {
106             I2C_RT(i2c_periph) = I2CCLK_MAX;
107         } else if(risetime <= I2CCLK_MIN) {
108             I2C_RT(i2c_periph) = I2CCLK_MIN;
109         }else{
110             I2C_RT(i2c_periph) = risetime;
111         }
112         clkc = (uint32_t)(pclk1 / (clkspeed * 2U));
113         if(clkc < 0x04U) {
114             /* the CLKC in standard mode minimum value is 4 */
115             clkc = 0x04U;
116         }
117 
118         I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);
119     } else if(400000U >= clkspeed) {
120         /* the maximum SCL rise time is 300ns in fast mode */
121         I2C_RT(i2c_periph) = (uint32_t)(((freq * (uint32_t)300U) / (uint32_t)1000U) + (uint32_t)1U);
122         if(I2C_DTCY_2 == dutycyc) {
123             /* I2C duty cycle is 2 */
124             clkc = (uint32_t)(pclk1 / (clkspeed * 3U));
125             I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
126         } else {
127             /* I2C duty cycle is 16/9 */
128             clkc = (uint32_t)(pclk1 / (clkspeed * 25U));
129             I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
130         }
131         if(0U == (clkc & I2C_CKCFG_CLKC)) {
132             /* the CLKC in fast mode minimum value is 1 */
133             clkc |= 0x0001U;
134         }
135         I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
136         I2C_CKCFG(i2c_periph) |= clkc;
137     }else{
138         /* fast mode plus, the maximum SCL rise time is 120ns */
139         I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)120U)/(uint32_t)1000U)+(uint32_t)1U);
140         if(I2C_DTCY_2 == dutycyc){
141             /* I2C duty cycle is 2 */
142             clkc = (uint32_t)(pclk1/(clkspeed*3U));
143             I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
144         }else{
145             /* I2C duty cycle is 16/9 */
146             clkc = (uint32_t)(pclk1/(clkspeed*25U));
147             I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
148         }
149         /* enable fast mode */
150         I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
151         I2C_CKCFG(i2c_periph) |= clkc;
152         /* enable I2C fast mode plus */
153         I2C_FMPCFG(i2c_periph) = I2C_FMPCFG_FMPEN;
154     }
155 }
156 
157 /*!
158     \brief      configure I2C address
159     \param[in]  i2c_periph: I2Cx(x=0,1)
160     \param[in]  mode:
161                 only one parameter can be selected which is shown as below:
162       \arg        I2C_I2CMODE_ENABLE: I2C mode
163       \arg        I2C_SMBUSMODE_ENABLE: SMBus mode
164     \param[in]  addformat: 7bits or 10bits
165                 only one parameter can be selected which is shown as below:
166       \arg        I2C_ADDFORMAT_7BITS: address format is 7 bits
167       \arg        I2C_ADDFORMAT_10BITS: address format is 10 bits
168     \param[in]  addr: I2C address
169     \param[out] none
170     \retval     none
171 */
i2c_mode_addr_config(uint32_t i2c_periph,uint32_t mode,uint32_t addformat,uint32_t addr)172 void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr)
173 {
174     /* SMBus/I2C mode selected */
175     uint32_t ctl = 0U;
176 
177     ctl = I2C_CTL0(i2c_periph);
178     ctl &= ~(I2C_CTL0_SMBEN);
179     ctl |= mode;
180     I2C_CTL0(i2c_periph) = ctl;
181     /* configure address */
182     addr = addr & I2C_ADDRESS_MASK;
183     I2C_SADDR0(i2c_periph) = (addformat | addr);
184 }
185 
186 /*!
187     \brief      select SMBus type
188     \param[in]  i2c_periph: I2Cx(x=0,1)
189     \param[in]  type:
190                 only one parameter can be selected which is shown as below:
191       \arg        I2C_SMBUS_DEVICE: SMBus mode device type
192       \arg        I2C_SMBUS_HOST: SMBus mode host type
193     \param[out] none
194     \retval     none
195 */
i2c_smbus_type_config(uint32_t i2c_periph,uint32_t type)196 void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type)
197 {
198     if(I2C_SMBUS_HOST == type){
199         I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;
200     }else{
201         I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);
202     }
203 }
204 
205 /*!
206     \brief      whether or not to send an ACK
207     \param[in]  i2c_periph: I2Cx(x=0,1)
208     \param[in]  ack:
209                 only one parameter can be selected which is shown as below:
210       \arg        I2C_ACK_ENABLE: ACK will be sent
211       \arg        I2C_ACK_DISABLE: ACK will not be sent
212     \param[out] none
213     \retval     none
214 */
i2c_ack_config(uint32_t i2c_periph,uint32_t ack)215 void i2c_ack_config(uint32_t i2c_periph, uint32_t ack)
216 {
217     uint32_t ctl = 0U;
218 
219     ctl = I2C_CTL0(i2c_periph);
220     ctl &= ~(I2C_CTL0_ACKEN);
221     ctl |= ack;
222     I2C_CTL0(i2c_periph) = ctl;
223 }
224 
225 /*!
226     \brief      configure I2C POAP position
227     \param[in]  i2c_periph: I2Cx(x=0,1)
228     \param[in]  pos:
229                 only one parameter can be selected which is shown as below:
230       \arg        I2C_ACKPOS_CURRENT: ACKEN bit decides whether or not to send ACK or not for the current byte
231       \arg        I2C_ACKPOS_NEXT: ACKEN bit decides whether or not to send ACK for the next byte
232     \param[out] none
233     \retval     none
234 */
i2c_ackpos_config(uint32_t i2c_periph,uint32_t pos)235 void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos)
236 {
237     uint32_t ctl = 0U;
238 
239     /* configure I2C POAP position */
240     ctl = I2C_CTL0(i2c_periph);
241     ctl &= ~(I2C_CTL0_POAP);
242     ctl |= pos;
243     I2C_CTL0(i2c_periph) = ctl;
244 }
245 
246 /*!
247     \brief      master sends slave address
248     \param[in]  i2c_periph: I2Cx(x=0,1)
249     \param[in]  addr: slave address
250     \param[in]  trandirection: transmitter or receiver
251                 only one parameter can be selected which is shown as below:
252       \arg        I2C_TRANSMITTER: transmitter
253       \arg        I2C_RECEIVER: receiver
254     \param[out] none
255     \retval     none
256 */
i2c_master_addressing(uint32_t i2c_periph,uint32_t addr,uint32_t trandirection)257 void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection)
258 {
259     /* master is a transmitter or a receiver */
260     if(I2C_TRANSMITTER == trandirection){
261         addr = addr & I2C_TRANSMITTER;
262     }else{
263         addr = addr | I2C_RECEIVER;
264     }
265     /* send slave address */
266     I2C_DATA(i2c_periph) = addr;
267 }
268 
269 /*!
270     \brief      enable dual-address mode
271     \param[in]  i2c_periph: I2Cx(x=0,1)
272     \param[in]  addr: the second address in dual-address mode
273     \param[out] none
274     \retval     none
275 */
i2c_dualaddr_enable(uint32_t i2c_periph,uint32_t addr)276 void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr)
277 {
278     /* configure address */
279     addr = addr & I2C_ADDRESS2_MASK;
280     I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr);
281 }
282 
283 /*!
284     \brief      disable dual-address mode
285     \param[in]  i2c_periph: I2Cx(x=0,1)
286     \param[out] none
287     \retval     none
288 */
i2c_dualaddr_disable(uint32_t i2c_periph)289 void i2c_dualaddr_disable(uint32_t i2c_periph)
290 {
291     I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN);
292 }
293 
294 /*!
295     \brief      enable I2C
296     \param[in]  i2c_periph: I2Cx(x=0,1)
297     \param[out] none
298     \retval     none
299 */
i2c_enable(uint32_t i2c_periph)300 void i2c_enable(uint32_t i2c_periph)
301 {
302     I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN;
303 }
304 
305 /*!
306     \brief      disable I2C
307     \param[in]  i2c_periph: I2Cx(x=0,1)
308     \param[out] none
309     \retval     none
310 */
i2c_disable(uint32_t i2c_periph)311 void i2c_disable(uint32_t i2c_periph)
312 {
313     I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN);
314 }
315 
316 /*!
317     \brief      generate a START condition on I2C bus
318     \param[in]  i2c_periph: I2Cx(x=0,1)
319     \param[out] none
320     \retval     none
321 */
i2c_start_on_bus(uint32_t i2c_periph)322 void i2c_start_on_bus(uint32_t i2c_periph)
323 {
324     I2C_CTL0(i2c_periph) |= I2C_CTL0_START;
325 }
326 
327 /*!
328     \brief      generate a STOP condition on I2C bus
329     \param[in]  i2c_periph: I2Cx(x=0,1)
330     \param[out] none
331     \retval     none
332 */
i2c_stop_on_bus(uint32_t i2c_periph)333 void i2c_stop_on_bus(uint32_t i2c_periph)
334 {
335     I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP;
336 }
337 
338 /*!
339     \brief      I2C transmit data function
340     \param[in]  i2c_periph: I2Cx(x=0,1)
341     \param[in]  data: data of transmission
342     \param[out] none
343     \retval     none
344 */
i2c_data_transmit(uint32_t i2c_periph,uint8_t data)345 void i2c_data_transmit(uint32_t i2c_periph, uint8_t data)
346 {
347     I2C_DATA(i2c_periph) = DATA_TRANS(data);
348 }
349 
350 /*!
351     \brief      I2C receive data function
352     \param[in]  i2c_periph: I2Cx(x=0,1)
353     \param[out] none
354     \retval     data of received
355 */
i2c_data_receive(uint32_t i2c_periph)356 uint8_t i2c_data_receive(uint32_t i2c_periph)
357 {
358     return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph));
359 }
360 
361 /*!
362     \brief      configure I2C DMA mode
363     \param[in]  i2c_periph: I2Cx(x=0,1)
364     \param[in]  dmastate:
365                 only one parameter can be selected which is shown as below:
366       \arg        I2C_DMA_ON: enable DMA mode
367       \arg        I2C_DMA_OFF: disable DMA mode
368     \param[out] none
369     \retval     none
370 */
i2c_dma_config(uint32_t i2c_periph,uint32_t dmastate)371 void i2c_dma_config(uint32_t i2c_periph, uint32_t dmastate)
372 {
373     /* configure I2C DMA function */
374     uint32_t ctl = 0U;
375 
376     ctl = I2C_CTL1(i2c_periph);
377     ctl &= ~(I2C_CTL1_DMAON);
378     ctl |= dmastate;
379     I2C_CTL1(i2c_periph) = ctl;
380 }
381 
382 /*!
383     \brief      configure whether next DMA EOT is DMA last transfer or not
384     \param[in]  i2c_periph: I2Cx(x=0,1)
385     \param[in]  dmalast:
386                 only one parameter can be selected which is shown as below:
387       \arg        I2C_DMALST_ON: next DMA EOT is the last transfer
388       \arg        I2C_DMALST_OFF: next DMA EOT is not the last transfer
389     \param[out] none
390     \retval     none
391 */
i2c_dma_last_transfer_config(uint32_t i2c_periph,uint32_t dmalast)392 void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast)
393 {
394     /* configure DMA last transfer */
395     uint32_t ctl = 0U;
396 
397     ctl = I2C_CTL1(i2c_periph);
398     ctl &= ~(I2C_CTL1_DMALST);
399     ctl |= dmalast;
400     I2C_CTL1(i2c_periph) = ctl;
401 }
402 
403 /*!
404     \brief      whether to stretch SCL low when data is not ready in slave mode
405     \param[in]  i2c_periph: I2Cx(x=0,1)
406     \param[in]  stretchpara:
407                 only one parameter can be selected which is shown as below:
408       \arg        I2C_SCLSTRETCH_ENABLE: enable SCL stretching
409       \arg        I2C_SCLSTRETCH_DISABLE: disable SCL stretching
410     \param[out] none
411     \retval     none
412 */
i2c_stretch_scl_low_config(uint32_t i2c_periph,uint32_t stretchpara)413 void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
414 {
415     /* configure I2C SCL stretching */
416     uint32_t ctl = 0U;
417 
418     ctl = I2C_CTL0(i2c_periph);
419     ctl &= ~(I2C_CTL0_SS);
420     ctl |= stretchpara;
421     I2C_CTL0(i2c_periph) = ctl;
422 }
423 
424 /*!
425     \brief      whether or not to response to a general call
426     \param[in]  i2c_periph: I2Cx(x=0,1)
427     \param[in]  gcallpara:
428                 only one parameter can be selected which is shown as below:
429       \arg        I2C_GCEN_ENABLE: slave will response to a general call
430       \arg        I2C_GCEN_DISABLE: slave will not response to a general call
431     \param[out] none
432     \retval     none
433 */
i2c_slave_response_to_gcall_config(uint32_t i2c_periph,uint32_t gcallpara)434 void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
435 {
436     /* configure slave response to a general call enable or disable */
437     uint32_t ctl = 0U;
438 
439     ctl = I2C_CTL0(i2c_periph);
440     ctl &= ~(I2C_CTL0_GCEN);
441     ctl |= gcallpara;
442     I2C_CTL0(i2c_periph) = ctl;
443 }
444 
445 /*!
446     \brief      configure software reset of I2C
447     \param[in]  i2c_periph: I2Cx(x=0,1)
448     \param[in]  sreset:
449                 only one parameter can be selected which is shown as below:
450       \arg        I2C_SRESET_SET: I2C is under reset
451       \arg        I2C_SRESET_RESET: I2C is not under reset
452     \param[out] none
453     \retval     none
454 */
i2c_software_reset_config(uint32_t i2c_periph,uint32_t sreset)455 void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
456 {
457     /* modify CTL0 and configure software reset I2C state */
458     uint32_t ctl = 0U;
459 
460     ctl = I2C_CTL0(i2c_periph);
461     ctl &= ~(I2C_CTL0_SRESET);
462     ctl |= sreset;
463     I2C_CTL0(i2c_periph) = ctl;
464 }
465 
466 /*!
467     \brief      configure I2C PEC calculation
468     \param[in]  i2c_periph: I2Cx(x=0,1)
469     \param[in]  pecstate:
470                 only one parameter can be selected which is shown as below:
471       \arg        I2C_PEC_ENABLE: PEC calculation on
472       \arg        I2C_PEC_DISABLE: PEC calculation off
473     \param[out] none
474     \retval     none
475 */
i2c_pec_config(uint32_t i2c_periph,uint32_t pecstate)476 void i2c_pec_config(uint32_t i2c_periph, uint32_t pecstate)
477 {
478     /* on/off PEC calculation */
479     uint32_t ctl = 0U;
480 
481     ctl = I2C_CTL0(i2c_periph);
482     ctl &= ~(I2C_CTL0_PECEN);
483     ctl |= pecstate;
484     I2C_CTL0(i2c_periph) = ctl;
485 }
486 
487 /*!
488     \brief      configure whether to transfer PEC value
489     \param[in]  i2c_periph: I2Cx(x=0,1)
490     \param[in]  pecpara:
491                 only one parameter can be selected which is shown as below:
492       \arg        I2C_PECTRANS_ENABLE: transfer PEC value
493       \arg        I2C_PECTRANS_DISABLE: not transfer PEC value
494     \param[out] none
495     \retval     none
496 */
i2c_pec_transfer_config(uint32_t i2c_periph,uint32_t pecpara)497 void i2c_pec_transfer_config(uint32_t i2c_periph, uint32_t pecpara)
498 {
499     /* whether to transfer PEC */
500     uint32_t ctl = 0U;
501 
502     ctl = I2C_CTL0(i2c_periph);
503     ctl &= ~(I2C_CTL0_PECTRANS);
504     ctl |= pecpara;
505     I2C_CTL0(i2c_periph) = ctl;
506 }
507 
508 /*!
509     \brief      get packet error checking value
510     \param[in]  i2c_periph: I2Cx(x=0,1)
511     \param[out] none
512     \retval     PEC value
513 */
i2c_pec_value_get(uint32_t i2c_periph)514 uint8_t i2c_pec_value_get(uint32_t i2c_periph)
515 {
516     return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV) >> STAT1_PECV_OFFSET);
517 }
518 
519 /*!
520     \brief      configure I2C alert through SMBA pin
521     \param[in]  i2c_periph: I2Cx(x=0,1)
522     \param[in]  smbuspara:
523                 only one parameter can be selected which is shown as below:
524       \arg        I2C_SALTSEND_ENABLE: issue alert through SMBA pin
525       \arg        I2C_SALTSEND_DISABLE: not issue alert through SMBA pin
526     \param[out] none
527     \retval     none
528 */
i2c_smbus_alert_config(uint32_t i2c_periph,uint32_t smbuspara)529 void i2c_smbus_alert_config(uint32_t i2c_periph, uint32_t smbuspara)
530 {
531     /* configure smbus alert through SMBA pin */
532     uint32_t ctl = 0U;
533 
534     ctl = I2C_CTL0(i2c_periph);
535     ctl &= ~(I2C_CTL0_SALT);
536     ctl |= smbuspara;
537     I2C_CTL0(i2c_periph) = ctl;
538 }
539 
540 /*!
541     \brief      configure I2C ARP protocol in SMBus
542     \param[in]  i2c_periph: I2Cx(x=0,1)
543     \param[in]  arpstate:
544                 only one parameter can be selected which is shown as below:
545       \arg        I2C_ARP_ENABLE: enable ARP
546       \arg        I2C_ARP_DISABLE: disable ARP
547     \param[out] none
548     \retval     none
549 */
i2c_smbus_arp_config(uint32_t i2c_periph,uint32_t arpstate)550 void i2c_smbus_arp_config(uint32_t i2c_periph, uint32_t arpstate)
551 {
552     /* enable or disable I2C ARP protocol*/
553     uint32_t ctl = 0U;
554 
555     ctl = I2C_CTL0(i2c_periph);
556     ctl &= ~(I2C_CTL0_ARPEN);
557     ctl |= arpstate;
558     I2C_CTL0(i2c_periph) = ctl;
559 }
560 
561 /*!
562     \brief      enable SAM_V interface
563     \param[in]  i2c_periph: I2Cx(x=0,1)
564     \param[out] none
565     \retval     none
566 */
i2c_sam_enable(uint32_t i2c_periph)567 void i2c_sam_enable(uint32_t i2c_periph)
568 {
569     I2C_SAMCS(i2c_periph) |= I2C_SAMCS_SAMEN;
570 }
571 
572 /*!
573     \brief      disable SAM_V interface
574     \param[in]  i2c_periph: I2Cx(x=0,1)
575     \param[out] none
576     \retval     none
577 */
i2c_sam_disable(uint32_t i2c_periph)578 void i2c_sam_disable(uint32_t i2c_periph)
579 {
580     I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_SAMEN);
581 }
582 
583 /*!
584     \brief      enable SAM_V interface timeout detect
585     \param[in]  i2c_periph: I2Cx(x=0,1)
586     \param[out] none
587     \retval     none
588 */
i2c_sam_timeout_enable(uint32_t i2c_periph)589 void i2c_sam_timeout_enable(uint32_t i2c_periph)
590 {
591     I2C_SAMCS(i2c_periph) |= I2C_SAMCS_STOEN;
592 }
593 
594 /*!
595     \brief      disable SAM_V interface timeout detect
596     \param[in]  i2c_periph: I2Cx(x=0,1)
597     \param[out] none
598     \retval     none
599 */
i2c_sam_timeout_disable(uint32_t i2c_periph)600 void i2c_sam_timeout_disable(uint32_t i2c_periph)
601 {
602     I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_STOEN);
603 }
604 
605 /*!
606     \brief      check I2C flag is set or not
607     \param[in]  i2c_periph: I2Cx(x=0,1)
608     \param[in]  flag: I2C flags, refer to i2c_flag_enum
609                 only one parameter can be selected which is shown as below:
610       \arg        I2C_FLAG_SBSEND: start condition sent out in master mode
611       \arg        I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
612       \arg        I2C_FLAG_BTC: byte transmission finishes
613       \arg        I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode
614       \arg        I2C_FLAG_STPDET: stop condition detected in slave mode
615       \arg        I2C_FLAG_RBNE: I2C_DATA is not empty during receiving
616       \arg        I2C_FLAG_TBE: I2C_DATA is empty during transmitting
617       \arg        I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
618       \arg        I2C_FLAG_LOSTARB: arbitration lost in master mode
619       \arg        I2C_FLAG_AERR: acknowledge error
620       \arg        I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
621       \arg        I2C_FLAG_PECERR: PEC error when receiving data
622       \arg        I2C_FLAG_SMBTO: timeout signal in SMBus mode
623       \arg        I2C_FLAG_SMBALT: SMBus alert status
624       \arg        I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode
625       \arg        I2C_FLAG_I2CBSY: busy flag
626       \arg        I2C_FLAG_TR: whether the I2C is a transmitter or a receiver
627       \arg        I2C_FLAG_RXGC: general call address (00h) received
628       \arg        I2C_FLAG_DEFSMB: default address of SMBus device
629       \arg        I2C_FLAG_HSTSMB: SMBus host header detected in slave mode
630       \arg        I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode
631       \arg        I2C_FLAG_TFF: txframe fall flag
632       \arg        I2C_FLAG_TFR: txframe rise flag
633       \arg        I2C_FLAG_RFF: rxframe fall flag
634       \arg        I2C_FLAG_RFR: rxframe rise flag
635     \param[out] none
636     \retval     FlagStatus: SET or RESET
637 */
i2c_flag_get(uint32_t i2c_periph,i2c_flag_enum flag)638 FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
639 {
640     if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){
641         return SET;
642     }else{
643         return RESET;
644     }
645 }
646 
647 /*!
648     \brief      clear I2C flag status
649     \param[in]  i2c_periph: I2Cx(x=0,1)
650     \param[in]  flag: I2C flags, refer to i2c_flag_enum
651                 only one parameter can be selected which is shown as below:
652       \arg       I2C_FLAG_SMBALT: SMBus alert status
653       \arg       I2C_FLAG_SMBTO: timeout signal in SMBus mode
654       \arg       I2C_FLAG_PECERR: PEC error when receiving data
655       \arg       I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
656       \arg       I2C_FLAG_AERR: acknowledge error
657       \arg       I2C_FLAG_LOSTARB: arbitration lost in master mode
658       \arg       I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
659       \arg       I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
660       \arg       I2C_FLAG_TFF: txframe fall flag
661       \arg       I2C_FLAG_TFR: txframe rise flag
662       \arg       I2C_FLAG_RFF: rxframe fall flag
663       \arg       I2C_FLAG_RFR: rxframe rise flag
664     \param[out] none
665     \retval     none
666 */
i2c_flag_clear(uint32_t i2c_periph,i2c_flag_enum flag)667 void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag)
668 {
669     if(I2C_FLAG_ADDSEND == flag){
670         /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
671         I2C_STAT0(i2c_periph);
672         I2C_STAT1(i2c_periph);
673     }else{
674         I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag));
675     }
676 }
677 
678 /*!
679     \brief      enable I2C interrupt
680     \param[in]  i2c_periph: I2Cx(x=0,1)
681     \param[in]  interrupt: I2C interrupts, refer to i2c_interrupt_enum
682                 only one parameter can be selected which is shown as below:
683       \arg        I2C_INT_ERR: error interrupt
684       \arg        I2C_INT_EV: event interrupt
685       \arg        I2C_INT_BUF: buffer interrupt
686       \arg        I2C_INT_TFF: txframe fall interrupt
687       \arg        I2C_INT_TFR: txframe rise interrupt
688       \arg        I2C_INT_RFF: rxframe fall interrupt
689       \arg        I2C_INT_RFR: rxframe rise interrupt
690     \param[out] none
691     \retval     none
692 */
i2c_interrupt_enable(uint32_t i2c_periph,i2c_interrupt_enum interrupt)693 void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
694 {
695     I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt));
696 }
697 
698 /*!
699     \brief      disable I2C interrupt
700     \param[in]  i2c_periph: I2Cx(x=0,1)
701     \param[in]  interrupt: I2C interrupts, refer to i2c_interrupt_enum
702                 only one parameter can be selected which is shown as below:
703       \arg        I2C_INT_ERR: error interrupt
704       \arg        I2C_INT_EV: event interrupt
705       \arg        I2C_INT_BUF: buffer interrupt
706       \arg        I2C_INT_TFF: txframe fall interrupt
707       \arg        I2C_INT_TFR: txframe rise interrupt
708       \arg        I2C_INT_RFF: rxframe fall interrupt
709       \arg        I2C_INT_RFR: rxframe rise interrupt
710     \param[out] none
711     \retval     none
712 */
i2c_interrupt_disable(uint32_t i2c_periph,i2c_interrupt_enum interrupt)713 void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
714 {
715     I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt));
716 }
717 
718 /*!
719     \brief      get I2C interrupt flag status
720     \param[in]  i2c_periph: I2Cx(x=0,1)
721     \param[in]  int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
722                 only one parameter can be selected which is shown as below:
723       \arg        I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag
724       \arg        I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
725       \arg        I2C_INT_FLAG_BTC: byte transmission finishes interrupt flag
726       \arg        I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag
727       \arg        I2C_INT_FLAG_STPDET: stop condition detected in slave mode interrupt flag
728       \arg        I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag
729       \arg        I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag
730       \arg        I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
731       \arg        I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
732       \arg        I2C_INT_FLAG_AERR: acknowledge error interrupt flag
733       \arg        I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
734       \arg        I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
735       \arg        I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
736       \arg        I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag
737       \arg        I2C_INT_FLAG_TFF: txframe fall interrupt flag
738       \arg        I2C_INT_FLAG_TFR: txframe rise interrupt flag
739       \arg        I2C_INT_FLAG_RFF: rxframe fall interrupt flag
740       \arg        I2C_INT_FLAG_RFR: rxframe rise interrupt flag
741     \param[out] none
742     \retval     FlagStatus: SET or RESET
743 */
i2c_interrupt_flag_get(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag)744 FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
745 {
746     uint32_t intenable = 0U, flagstatus = 0U, bufie;
747 
748     /* check BUFIE */
749     bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE;
750 
751     /* get the interrupt enable bit status */
752     intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag)));
753     /* get the corresponding flag bit status */
754     flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag)));
755 
756     if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){
757         if(intenable && bufie){
758             intenable = 1U;
759         }else{
760             intenable = 0U;
761         }
762     }
763     if((0U != flagstatus) && (0U != intenable)){
764         return SET;
765     }else{
766         return RESET;
767     }
768 }
769 
770 /*!
771     \brief      clear I2C interrupt flag status
772     \param[in]  i2c_periph: I2Cx(x=0,1)
773     \param[in]  int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
774                 only one parameter can be selected which is shown as below:
775       \arg        I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
776       \arg        I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
777       \arg        I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
778       \arg        I2C_INT_FLAG_AERR: acknowledge error interrupt flag
779       \arg        I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
780       \arg        I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
781       \arg        I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
782       \arg        I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag
783       \arg        I2C_INT_FLAG_TFF: txframe fall interrupt flag
784       \arg        I2C_INT_FLAG_TFR: txframe rise interrupt flag
785       \arg        I2C_INT_FLAG_RFF: rxframe fall interrupt flag
786       \arg        I2C_INT_FLAG_RFR: rxframe rise interrupt flag
787     \param[out] none
788     \retval     none
789 */
i2c_interrupt_flag_clear(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag)790 void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
791 {
792     if(I2C_INT_FLAG_ADDSEND == int_flag){
793         /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
794         I2C_STAT0(i2c_periph);
795         I2C_STAT1(i2c_periph);
796     }else{
797         I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag));
798     }
799 }
800