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