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