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