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