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