1 /**************************************************************************//**
2  * @file     i2c.c
3  * @version  V3.00
4  * @brief    M2L31 series I2C driver source file
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  * @copyright (C) 2023 Nuvoton Technology Corp. All rights reserved.
8  *****************************************************************************/
9 #include "NuMicro.h"
10 
11 /** @addtogroup Standard_Driver Standard Driver
12   @{
13 */
14 
15 /** @addtogroup I2C_Driver I2C Driver
16   @{
17 */
18 
19 int32_t g_I2C_i32ErrCode = 0;       /*!< I2C global error code */
20 
21 /** @addtogroup I2C_EXPORTED_FUNCTIONS I2C Exported Functions
22   @{
23 */
24 
25 /**
26   * @brief      Enable specify I2C Controller and set Clock Divider
27   *
28   * @param[in]  i2c         Specify I2C port
29   * @param[in]  u32BusClock The target I2C bus clock in Hz
30   *
31   * @return     Actual I2C bus clock frequency
32   *
33   * @details    The function enable the specify I2C Controller and set proper Clock Divider
34   *             in I2C CLOCK DIVIDED REGISTER (I2CLK) according to the target I2C Bus clock.
35   *             I2C Bus clock = PCLK / (4*(divider+1).
36   *
37   */
I2C_Open(I2C_T * i2c,uint32_t u32BusClock)38 uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock)
39 {
40     uint32_t u32Div;
41     uint32_t u32Pclk;
42 
43     if( (i2c == I2C1) || (i2c == I2C3) )
44     {
45         u32Pclk = CLK_GetPCLK1Freq();
46     }
47     else
48     {
49         u32Pclk = CLK_GetPCLK0Freq();
50     }
51 
52     u32Div = (uint32_t)(((u32Pclk * 10U) / (u32BusClock * 4U) + 5U) / 10U - 1U); /* Compute proper divider for I2C clock */
53     i2c->CLKDIV = u32Div;
54 
55     /* Enable I2C */
56     i2c->CTL0 |= I2C_CTL0_I2CEN_Msk;
57 
58     return (u32Pclk / ((u32Div + 1U) << 2U));
59 }
60 
61 /**
62   * @brief      Disable specify I2C Controller
63   *
64   * @param[in]  i2c         Specify I2C port
65     *
66   * @return     None
67   *
68   * @details    Reset I2C Controller and disable specify I2C port.
69     *
70   */
71 
I2C_Close(I2C_T * i2c)72 void I2C_Close(I2C_T *i2c)
73 {
74     /* Reset I2C Controller */
75     if(i2c == I2C0)
76     {
77         SYS->IPRST1 |= SYS_IPRST1_I2C0RST_Msk;
78         SYS->IPRST1 &= ~SYS_IPRST1_I2C0RST_Msk;
79     }
80     else if(i2c == I2C1)
81     {
82         SYS->IPRST1 |= SYS_IPRST1_I2C1RST_Msk;
83         SYS->IPRST1 &= ~SYS_IPRST1_I2C1RST_Msk;
84     }
85     else if(i2c == I2C2)
86     {
87         SYS->IPRST1 |= SYS_IPRST1_I2C2RST_Msk;
88         SYS->IPRST1 &= ~SYS_IPRST1_I2C2RST_Msk;
89     }
90     else if(i2c == I2C3)
91     {
92         SYS->IPRST1 |= SYS_IPRST1_I2C3RST_Msk;
93         SYS->IPRST1 &= ~SYS_IPRST1_I2C3RST_Msk;
94     }
95 
96     /* Disable I2C */
97     i2c->CTL0 &= ~I2C_CTL0_I2CEN_Msk;
98 }
99 
100 /**
101   * @brief      Clear Time-out Counter flag
102   *
103   * @param[in]  i2c         Specify I2C port
104     *
105   * @return     None
106   *
107   * @details    When Time-out flag will be set, use this function to clear I2C Bus Time-out counter flag .
108     *
109   */
I2C_ClearTimeoutFlag(I2C_T * i2c)110 void I2C_ClearTimeoutFlag(I2C_T *i2c)
111 {
112     i2c->TOCTL |= I2C_TOCTL_TOIF_Msk;
113 }
114 
115 /**
116   * @brief      Set Control bit of I2C Controller
117   *
118   * @param[in]  i2c         Specify I2C port
119   * @param[in]  u8Start     Set I2C START condition
120   * @param[in]  u8Stop      Set I2C STOP condition
121   * @param[in]  u8Si        Clear SI flag
122   * @param[in]  u8Ack       Set I2C ACK bit
123   *
124   * @return     None
125   *
126   * @details    The function set I2C Control bit of I2C Bus protocol.
127   *
128   */
I2C_Trigger(I2C_T * i2c,uint8_t u8Start,uint8_t u8Stop,uint8_t u8Si,uint8_t u8Ack)129 void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack)
130 {
131     uint32_t u32Reg = 0U;
132 
133     if(u8Start)
134     {
135         u32Reg |= I2C_CTL_STA;
136     }
137 
138     if(u8Stop)
139     {
140         u32Reg |= I2C_CTL_STO;
141     }
142 
143     if(u8Si)
144     {
145         u32Reg |= I2C_CTL_SI;
146     }
147 
148     if(u8Ack)
149     {
150         u32Reg |= I2C_CTL_AA;
151     }
152 
153     i2c->CTL0 = (i2c->CTL0 & ~0x3CU) | u32Reg;
154 }
155 
156 /**
157   * @brief      Disable Interrupt of I2C Controller
158   *
159   * @param[in]  i2c         Specify I2C port
160   *
161   * @return     None
162   *
163   * @details    The function is used for disable I2C interrupt
164   *
165   */
I2C_DisableInt(I2C_T * i2c)166 void I2C_DisableInt(I2C_T *i2c)
167 {
168     i2c->CTL0 &= ~I2C_CTL0_INTEN_Msk;
169 }
170 
171 /**
172   * @brief      Enable Interrupt of I2C Controller
173   *
174   * @param[in]  i2c         Specify I2C port
175   *
176   * @return     None
177   *
178   * @details    The function is used for enable I2C interrupt
179   *
180   */
I2C_EnableInt(I2C_T * i2c)181 void I2C_EnableInt(I2C_T *i2c)
182 {
183     i2c->CTL0 |= I2C_CTL0_INTEN_Msk;
184 }
185 
186 /**
187  * @brief      Get I2C Bus Clock
188  *
189  * @param[in]  i2c          Specify I2C port
190  *
191  * @return     The actual I2C Bus clock in Hz
192  *
193  * @details    To get the actual I2C Bus Clock frequency.
194  */
I2C_GetBusClockFreq(I2C_T * i2c)195 uint32_t I2C_GetBusClockFreq(I2C_T *i2c)
196 {
197     uint32_t u32Divider = i2c->CLKDIV;
198     uint32_t u32Pclk;
199 
200     if( (i2c == I2C1) || (i2c == I2C3) )
201     {
202         u32Pclk = CLK_GetPCLK1Freq();
203     }
204     else
205     {
206         u32Pclk = CLK_GetPCLK0Freq();
207     }
208 
209     return (u32Pclk / ((u32Divider + 1U) << 2U));
210 }
211 
212 /**
213  * @brief      Set I2C Bus Clock
214  *
215  * @param[in]  i2c          Specify I2C port
216  * @param[in]  u32BusClock  The target I2C Bus Clock in Hz
217  *
218  * @return     The actual I2C Bus Clock in Hz
219  *
220  * @details    To set the actual I2C Bus Clock frequency.
221  */
I2C_SetBusClockFreq(I2C_T * i2c,uint32_t u32BusClock)222 uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock)
223 {
224     uint32_t u32Div;
225     uint32_t u32Pclk;
226 
227     if( (i2c == I2C1) || (i2c == I2C3) )
228     {
229         u32Pclk = CLK_GetPCLK1Freq();
230     }
231     else
232     {
233         u32Pclk = CLK_GetPCLK0Freq();
234     }
235 
236     u32Div = (uint32_t)(((u32Pclk * 10U) / (u32BusClock * 4U) + 5U) / 10U - 1U); /* Compute proper divider for I2C clock */
237     i2c->CLKDIV = u32Div;
238 
239     return (u32Pclk / ((u32Div + 1U) << 2U));
240 }
241 
242 /**
243  * @brief      Get Interrupt Flag
244  *
245  * @param[in]  i2c          Specify I2C port
246  *
247  * @return     I2C interrupt flag status
248  *
249  * @details    To get I2C Bus interrupt flag.
250  */
I2C_GetIntFlag(I2C_T * i2c)251 uint32_t I2C_GetIntFlag(I2C_T *i2c)
252 {
253     uint32_t u32Value;
254 
255     if((i2c->CTL0 & I2C_CTL0_SI_Msk) == I2C_CTL0_SI_Msk)
256     {
257         u32Value = 1U;
258     }
259     else
260     {
261         u32Value = 0U;
262     }
263 
264     return u32Value;
265 }
266 
267 /**
268  * @brief      Get I2C Bus Status Code
269  *
270  * @param[in]  i2c          Specify I2C port
271  *
272  * @return     I2C Status Code
273  *
274  * @details    To get I2C Bus Status Code.
275  */
I2C_GetStatus(I2C_T * i2c)276 uint32_t I2C_GetStatus(I2C_T *i2c)
277 {
278     return (i2c->STATUS0);
279 }
280 
281 /**
282  * @brief      Read a Byte from I2C Bus
283  *
284  * @param[in]  i2c          Specify I2C port
285  *
286  * @return     I2C Data
287  *
288  * @details    To read a bytes data from specify I2C port.
289  */
I2C_GetData(I2C_T * i2c)290 uint8_t I2C_GetData(I2C_T *i2c)
291 {
292     return (uint8_t)(i2c->DAT);
293 }
294 
295 /**
296  * @brief      Send a byte to I2C Bus
297  *
298  * @param[in]  i2c          Specify I2C port
299  * @param[in]  u8Data       The data to send to I2C bus
300  *
301  * @return     None
302  *
303  * @details    This function is used to write a byte to specified I2C port
304  */
I2C_SetData(I2C_T * i2c,uint8_t u8Data)305 void I2C_SetData(I2C_T *i2c, uint8_t u8Data)
306 {
307     i2c->DAT = u8Data;
308 }
309 
310 /**
311  * @brief      Set 7-bit Slave Address and GC Mode
312  *
313  * @param[in]  i2c          Specify I2C port
314  * @param[in]  u8SlaveNo    Set the number of I2C address register (0~3)
315  * @param[in]  u8SlaveAddr  7-bit slave address
316  * @param[in]  u8GCMode     Enable/Disable GC mode (I2C_GCMODE_ENABLE / I2C_GCMODE_DISABLE)
317  *
318  * @return     None
319  *
320  * @details    This function is used to set 7-bit slave addresses in I2C SLAVE ADDRESS REGISTER (I2CADDR0~3)
321  *             and enable GC Mode.
322  *
323  */
I2C_SetSlaveAddr(I2C_T * i2c,uint8_t u8SlaveNo,uint8_t u8SlaveAddr,uint8_t u8GCMode)324 void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode)
325 {
326     switch(u8SlaveNo)
327     {
328     case 1:
329         i2c->ADDR1  = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
330         break;
331     case 2:
332         i2c->ADDR2  = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
333         break;
334     case 3:
335         i2c->ADDR3  = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
336         break;
337     case 0:
338     default:
339         i2c->ADDR0  = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
340         break;
341     }
342 }
343 
344 /**
345  * @brief      Configure the mask bits of 7-bit Slave Address
346  *
347  * @param[in]  i2c              Specify I2C port
348  * @param[in]  u8SlaveNo        Set the number of I2C address mask register (0~3)
349  * @param[in]  u8SlaveAddrMask  A byte for slave address mask
350  *
351  * @return     None
352  *
353  * @details    This function is used to set 7-bit slave addresses.
354  *
355  */
I2C_SetSlaveAddrMask(I2C_T * i2c,uint8_t u8SlaveNo,uint8_t u8SlaveAddrMask)356 void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask)
357 {
358     switch(u8SlaveNo)
359     {
360     case 1:
361         i2c->ADDRMSK1  = (uint32_t)u8SlaveAddrMask << 1U;
362         break;
363     case 2:
364         i2c->ADDRMSK2  = (uint32_t)u8SlaveAddrMask << 1U;
365         break;
366     case 3:
367         i2c->ADDRMSK3  = (uint32_t)u8SlaveAddrMask << 1U;
368         break;
369     case 0:
370     default:
371         i2c->ADDRMSK0  = (uint32_t)u8SlaveAddrMask << 1U;
372         break;
373     }
374 }
375 
376 /**
377  * @brief      Enable Time-out Counter Function and support Long Time-out
378  *
379  * @param[in]  i2c              Specify I2C port
380  * @param[in]  u8LongTimeout    Configure DIV4 to enable Long Time-out (0/1)
381  *
382  * @return     None
383  *
384  * @details    This function enable Time-out Counter function and configure DIV4 to support Long
385  *             Time-out.
386  *
387  */
I2C_EnableTimeout(I2C_T * i2c,uint8_t u8LongTimeout)388 void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout)
389 {
390     if(u8LongTimeout)
391     {
392         i2c->TOCTL |= I2C_TOCTL_TOCDIV4_Msk;
393     }
394     else
395     {
396         i2c->TOCTL &= ~I2C_TOCTL_TOCDIV4_Msk;
397     }
398 
399     i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
400 }
401 
402 /**
403  * @brief      Disable Time-out Counter Function
404  *
405  * @param[in]  i2c          Specify I2C port
406  *
407  * @return     None
408  *
409  * @details    To disable Time-out Counter function in I2C_TOCTL register.
410  *
411  */
I2C_DisableTimeout(I2C_T * i2c)412 void I2C_DisableTimeout(I2C_T *i2c)
413 {
414     i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
415 }
416 
417 /**
418  * @brief      Enable I2C Wake-up Function
419  *
420  * @param[in]  i2c          Specify I2C port
421  *
422  * @return     None
423  *
424  * @details    To enable Wake-up function of I2C Wake-up control register.
425  *
426  */
I2C_EnableWakeup(I2C_T * i2c)427 void I2C_EnableWakeup(I2C_T *i2c)
428 {
429     i2c->WKCTL |= I2C_WKCTL_WKEN_Msk;
430 }
431 
432 /**
433  * @brief      Disable I2C Wake-up Function
434  *
435  * @param[in]  i2c          Specify I2C port
436  *
437  * @return     None
438  *
439  * @details    To disable Wake-up function of I2C Wake-up control register.
440  *
441  */
I2C_DisableWakeup(I2C_T * i2c)442 void I2C_DisableWakeup(I2C_T *i2c)
443 {
444     i2c->WKCTL &= ~I2C_WKCTL_WKEN_Msk;
445 }
446 
447 /**
448  * @brief      Enable I2C Two-level Buffer Function
449  *
450  * @param[in]  i2c          Specify I2C port
451  * @param[in]  u32BitCount  The bit count of date phase.
452  *                          - \ref I2C_DATA_PHASE_BIT_6
453  *                          - \ref I2C_DATA_PHASE_BIT_7
454  *                          - \ref I2C_DATA_PHASE_BIT_8
455  *
456  * @return     None
457  *
458  * @details    To enable I2C slave mode two-level buffer function.
459  *
460  */
I2C_EnableTwoBufferMode(I2C_T * i2c,uint32_t u32BitCount)461 void I2C_EnableTwoBufferMode(I2C_T *i2c, uint32_t u32BitCount)
462 {
463     /* Enable slave read and data phase interrupt and set data phase bit count */
464     i2c->CTL0 = (i2c->CTL0 & ~0xC33C) | (I2C_CTL0_SRCINTEN_Msk | I2C_CTL0_DPCINTEN_Msk | u32BitCount);
465 
466     /* Enable Two-level buffer mode */
467     i2c->CTL1 |= I2C_CTL1_TWOBUFEN_Msk;
468 }
469 
470 /**
471  * @brief      Disable I2C Two-level Buffer Function
472  *
473  * @param[in]  i2c          Specify I2C port
474  *
475  * @return     None
476  *
477  * @details    To disable I2C slave mode two-level buffer function.
478  *
479  */
I2C_DisableTwoBufferMode(I2C_T * i2c)480 void I2C_DisableTwoBufferMode(I2C_T *i2c)
481 {
482     /* Disable slave read and data phase interrupt */
483     i2c->CTL0 = (i2c->CTL0 & ~0xC03C) & ~(I2C_CTL0_SRCINTEN_Msk | I2C_CTL0_DPCINTEN_Msk | I2C_CTL0_DPBITSEL_Msk);
484 
485     /* Disable Two-level buffer mode */
486     i2c->CTL1 &= ~I2C_CTL1_TWOBUFEN_Msk;
487 }
488 
489 /**
490  * @brief      To get SMBus Status
491  *
492  * @param[in]  i2c          Specify I2C port
493  *
494  * @return     SMBus status
495  *
496  * @details    To get the Bus Management status of I2C_BUSSTS register
497  *
498  */
I2C_SMBusGetStatus(I2C_T * i2c)499 uint32_t I2C_SMBusGetStatus(I2C_T *i2c)
500 {
501     return (i2c->BUSSTS);
502 }
503 
504 /**
505  * @brief      Clear SMBus Interrupt Flag
506  *
507  * @param[in]  i2c              Specify I2C port
508  * @param[in]  u8SMBusIntFlag   Specify SMBus interrupt flag
509  *
510  * @return     None
511  *
512  * @details    To clear flags of I2C_BUSSTS status register if interrupt set.
513  *
514  */
I2C_SMBusClearInterruptFlag(I2C_T * i2c,uint8_t u8SMBusIntFlag)515 void I2C_SMBusClearInterruptFlag(I2C_T *i2c, uint8_t u8SMBusIntFlag)
516 {
517     i2c->BUSSTS = u8SMBusIntFlag;
518 }
519 
520 /**
521  * @brief      Set SMBus Bytes Counts of Transmission or Reception
522  *
523  * @param[in]  i2c              Specify I2C port
524  * @param[in]  u32PktSize       Transmit / Receive bytes
525  *
526  * @return     None
527  *
528  * @details    The transmission or receive byte number in one transaction when PECEN is set. The maximum is 255 bytes.
529  *
530  */
I2C_SMBusSetPacketByteCount(I2C_T * i2c,uint32_t u32PktSize)531 void I2C_SMBusSetPacketByteCount(I2C_T *i2c, uint32_t u32PktSize)
532 {
533     i2c->PKTSIZE = u32PktSize;
534 }
535 
536 /**
537  * @brief      Init SMBus Host/Device Mode
538  *
539  * @param[in]  i2c              Specify I2C port
540  * @param[in]  u8HostDevice     Init SMBus port mode(I2C_SMBH_ENABLE/I2C_SMBD_ENABLE)
541  *
542  * @return     None
543  *
544  * @details    Using SMBus communication must specify the port is a Host or a Device.
545  *
546  */
I2C_SMBusOpen(I2C_T * i2c,uint8_t u8HostDevice)547 void I2C_SMBusOpen(I2C_T *i2c, uint8_t u8HostDevice)
548 {
549     /* Clear  BMHEN, BMDEN of BUSCTL Register */
550     i2c->BUSCTL &=  ~(I2C_BUSCTL_BMHEN_Msk | I2C_BUSCTL_BMDEN_Msk);
551 
552     /* Set SMBus Host/Device Mode, and enable Bus Management*/
553     if(u8HostDevice == (uint8_t)I2C_SMBH_ENABLE)
554     {
555         i2c->BUSCTL |= (I2C_BUSCTL_BMHEN_Msk | I2C_BUSCTL_BUSEN_Msk);
556     }
557     else
558     {
559         i2c->BUSCTL |= (I2C_BUSCTL_BMDEN_Msk | I2C_BUSCTL_BUSEN_Msk);
560     }
561 }
562 
563 /**
564  * @brief      Disable SMBus function
565  *
566  * @param[in]  i2c              Specify I2C port
567  *
568  * @return     None
569  *
570  * @details    Disable all SMBus function include Bus disable, CRC check, Acknowledge by manual, Host/Device Mode.
571  *
572  */
I2C_SMBusClose(I2C_T * i2c)573 void I2C_SMBusClose(I2C_T *i2c)
574 {
575 
576     i2c->BUSCTL = 0x00U;
577 }
578 
579 /**
580  * @brief      Enable SMBus PEC Transmit Function
581  *
582  * @param[in]  i2c              Specify I2C port
583  * @param[in]  u8PECTxEn        CRC transmit enable(PECTX_ENABLE) or disable(PECTX_DISABLE)
584  *
585  * @return     None
586  *
587  * @details    When enable CRC check function, the Host or Device needs to transmit CRC byte.
588  *
589  */
I2C_SMBusPECTxEnable(I2C_T * i2c,uint8_t u8PECTxEn)590 void I2C_SMBusPECTxEnable(I2C_T *i2c, uint8_t u8PECTxEn)
591 {
592     i2c->BUSCTL &= ~I2C_BUSCTL_PECTXEN_Msk;
593 
594     if(u8PECTxEn)
595     {
596         i2c->BUSCTL |= (I2C_BUSCTL_PECEN_Msk | I2C_BUSCTL_PECTXEN_Msk);
597     }
598     else
599     {
600         i2c->BUSCTL |= I2C_BUSCTL_PECEN_Msk;
601     }
602 }
603 
604 /**
605  * @brief      Get SMBus CRC value
606  *
607  * @param[in]  i2c              Specify I2C port
608  *
609  * @return     A byte is packet error check value
610  *
611  * @details    The CRC check value after a transmission or a reception by count by using CRC8
612  *
613  */
I2C_SMBusGetPECValue(I2C_T * i2c)614 uint8_t I2C_SMBusGetPECValue(I2C_T *i2c)
615 {
616     return (uint8_t)i2c->PKTCRC;
617 }
618 
619 /**
620  * @brief      Calculate Time-out of SMBus idle period
621  *
622  * @param[in]  i2c              Specify I2C port
623  * @param[in]  us               Time-out length(us)
624  * @param[in]  u32Hclk          I2C peripheral clock frequency
625  *
626  * @return     None
627  *
628  * @details    This function is used to set SMBus Time-out length when bus is in Idle state.
629  *
630  */
631 
I2C_SMBusIdleTimeout(I2C_T * i2c,uint32_t us,uint32_t u32Hclk)632 void I2C_SMBusIdleTimeout(I2C_T *i2c, uint32_t us, uint32_t u32Hclk)
633 {
634     uint32_t  u32Div, u32Hclk_kHz;
635 
636     i2c->BUSCTL |= I2C_BUSCTL_TIDLE_Msk;
637     u32Hclk_kHz = u32Hclk / 1000U;
638     u32Div = (((us * u32Hclk_kHz) / 1000U) >> 2U) - 1U;
639     if(u32Div > 255U)
640     {
641         i2c->BUSTOUT = 0xFFU;
642     }
643     else
644     {
645         i2c->BUSTOUT = u32Div;
646     }
647 
648 }
649 
650 /**
651  * @brief      Calculate Time-out of SMBus active period
652  *
653  * @param[in]  i2c              Specify I2C port
654  * @param[in]  ms               Time-out length(ms)
655  * @param[in]  u32Pclk          peripheral clock frequency
656  *
657  * @return     None
658  *
659  * @details    This function is used to set SMBus Time-out length when bus is in active state.
660  *             Time-out length is calculate the SCL line "one clock" pull low timing.
661  *
662  */
663 
I2C_SMBusTimeout(I2C_T * i2c,uint32_t ms,uint32_t u32Pclk)664 void I2C_SMBusTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk)
665 {
666     uint32_t u32Div, u32Pclk_kHz;
667 
668     i2c->BUSCTL &= ~I2C_BUSCTL_TIDLE_Msk;
669 
670     /* DIV4 disabled */
671     i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
672     u32Pclk_kHz = u32Pclk / 1000U;
673     u32Div = ((ms * u32Pclk_kHz) / (16U * 1024U)) - 1U;
674     if(u32Div <= 0xFFU)
675     {
676         i2c->BUSTOUT = u32Div;
677     }
678     else
679     {
680         /* DIV4 enabled */
681         i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
682         i2c->BUSTOUT = (((ms * u32Pclk_kHz) / (16U * 1024U * 4U)) - 1U) & 0xFFU; /* The max value is 255 */
683     }
684 }
685 
686 /**
687  * @brief      Calculate Cumulative Clock low Time-out of SMBus active period
688  *
689  * @param[in]  i2c              Specify I2C port
690  * @param[in]  ms               Time-out length(ms)
691  * @param[in]  u32Pclk          peripheral clock frequency
692  *
693  * @return     None
694  *
695  * @details    This function is used to set SMBus Time-out length when bus is in Active state.
696  *             Time-out length is calculate the SCL line "clocks" low cumulative timing.
697  *
698  */
699 
I2C_SMBusClockLoTimeout(I2C_T * i2c,uint32_t ms,uint32_t u32Pclk)700 void I2C_SMBusClockLoTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk)
701 {
702     uint32_t u32Div, u32Pclk_kHz;
703 
704     i2c->BUSCTL &= ~I2C_BUSCTL_TIDLE_Msk;
705 
706     /* DIV4 disabled */
707     i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
708     u32Pclk_kHz = u32Pclk / 1000U;
709     u32Div = ((ms * u32Pclk_kHz) / (16U * 1024U)) - 1U;
710     if(u32Div <= 0xFFU)
711     {
712         i2c->CLKTOUT = u32Div;
713     }
714     else
715     {
716         /* DIV4 enabled */
717         i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
718         i2c->CLKTOUT = (((ms * u32Pclk_kHz) / (16U * 1024U * 4U)) - 1U) & 0xFFU; /* The max value is 255 */
719     }
720 }
721 
722 
723 /**
724   * @brief      Write a byte to Slave
725   *
726   * @param[in]  i2c             Point to I2C peripheral
727   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
728   * @param[in]  data            Write a byte data to Slave
729   *
730   * @retval     0               Write data success
731   * @retval     1               Write data fail, or bus occurs error events
732   *
733   * @details    The function is used for I2C Master write a byte data to Slave.
734   *
735   */
736 
I2C_WriteByte(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t data)737 uint8_t I2C_WriteByte(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data)
738 {
739     uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
740     uint32_t u32TimeOutCount;
741 
742     g_I2C_i32ErrCode = 0;
743 
744     I2C_START(i2c);
745     while(u8Xfering && (u8Err == 0u))
746     {
747         u32TimeOutCount = SystemCoreClock;
748         I2C_WAIT_READY(i2c)
749         {
750             u32TimeOutCount--;
751             if(u32TimeOutCount == 0)
752             {
753                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
754                 break;
755             }
756         }
757 
758         switch(I2C_GET_STATUS(i2c))
759         {
760         case 0x08u:
761             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));    /* Write SLA+W to Register I2CDAT */
762             u8Ctrl = I2C_CTL_SI;                              /* Clear SI */
763             break;
764         case 0x18u:                                           /* Slave Address ACK */
765             I2C_SET_DATA(i2c, data);                          /* Write data to I2CDAT */
766             break;
767         case 0x20u:                                           /* Slave Address NACK */
768         case 0x30u:                                           /* Master transmit data NACK */
769             u8Ctrl = I2C_CTL_STO_SI;                          /* Clear SI and send STOP */
770             u8Err = 1u;
771             break;
772         case 0x28u:
773             u8Ctrl = I2C_CTL_STO_SI;                          /* Clear SI and send STOP */
774             u8Xfering = 0u;
775             break;
776         case 0x38u:                                           /* Arbitration Lost */
777         default:                                              /* Unknow status */
778             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);      /* Clear SI and send STOP */
779             u8Ctrl = I2C_CTL_SI;
780             u8Err = 1u;
781             break;
782         }
783         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                        /* Write controlbit to I2C_CTL register */
784     }
785     return (u8Err | u8Xfering);                                  /* return (Success)/(Fail) status */
786 }
787 
788 /**
789   * @brief      Write multi bytes to Slave
790   *
791   * @param[in]  i2c             Point to I2C peripheral
792   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
793   * @param[in]  data[]           Pointer to array to write data to Slave
794   * @param[in]  u32wLen         How many bytes need to write to Slave
795   *
796   * @return     A length of how many bytes have been transmitted.
797   *
798   * @details    The function is used for I2C Master write multi bytes data to Slave.
799   *
800   */
801 
I2C_WriteMultiBytes(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t data[],uint32_t u32wLen)802 uint32_t I2C_WriteMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data[], uint32_t u32wLen)
803 {
804     uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
805     uint32_t u32txLen = 0u;
806     uint32_t u32TimeOutCount;
807 
808     g_I2C_i32ErrCode = 0;
809 
810     I2C_START(i2c);                                              /* Send START */
811     while(u8Xfering && (u8Err == 0u))
812     {
813         u32TimeOutCount = SystemCoreClock;
814         I2C_WAIT_READY(i2c)
815         {
816             u32TimeOutCount--;
817             if(u32TimeOutCount == 0)
818             {
819                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
820                 break;
821             }
822         }
823 
824         switch(I2C_GET_STATUS(i2c))
825         {
826         case 0x08u:
827             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));    /* Write SLA+W to Register I2CDAT */
828             u8Ctrl = I2C_CTL_SI;                           /* Clear SI */
829             break;
830         case 0x18u:                                           /* Slave Address ACK */
831         case 0x28u:
832             if(u32txLen < u32wLen)
833             {
834                 I2C_SET_DATA(i2c, data[u32txLen++]);                /* Write Data to I2CDAT */
835             }
836             else
837             {
838                 u8Ctrl = I2C_CTL_STO_SI;                   /* Clear SI and send STOP */
839                 u8Xfering = 0u;
840             }
841             break;
842         case 0x20u:                                           /* Slave Address NACK */
843         case 0x30u:                                           /* Master transmit data NACK */
844             u8Ctrl = I2C_CTL_STO_SI;                       /* Clear SI and send STOP */
845             u8Err = 1u;
846             break;
847         case 0x38u:                                           /* Arbitration Lost */
848         default:                                             /* Unknow status */
849             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);      /* Clear SI and send STOP */
850             u8Ctrl = I2C_CTL_SI;
851             u8Err = 1u;
852             break;
853         }
854         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                        /* Write controlbit to I2C_CTL register */
855     }
856     return u32txLen;                                             /* Return bytes length that have been transmitted */
857 }
858 
859 /**
860   * @brief      Specify a byte register address and write a byte to Slave
861   *
862   * @param[in]  i2c             Point to I2C peripheral
863   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
864   * @param[in]  u8DataAddr      Specify a address (1 byte) of data write to
865   * @param[in]  data            A byte data to write it to Slave
866   *
867   * @retval     0               Write data success
868   * @retval     1               Write data fail, or bus occurs error events
869   *
870   * @details    The function is used for I2C Master specify a address that data write to in Slave.
871   *
872   */
873 
I2C_WriteByteOneReg(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8DataAddr,uint8_t data)874 uint8_t I2C_WriteByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data)
875 {
876     uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
877     uint32_t u32txLen = 0u;
878     uint32_t u32TimeOutCount;
879 
880     g_I2C_i32ErrCode = 0;
881 
882     I2C_START(i2c);                                              /* Send START */
883     while(u8Xfering && (u8Err == 0u))
884     {
885         u32TimeOutCount = SystemCoreClock;
886         I2C_WAIT_READY(i2c)
887         {
888             u32TimeOutCount--;
889             if(u32TimeOutCount == 0)
890             {
891                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
892                 break;
893             }
894         }
895 
896         switch(I2C_GET_STATUS(i2c))
897         {
898         case 0x08u:
899             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));    /* Send Slave address with write bit */
900             u8Ctrl = I2C_CTL_SI;                           /* Clear SI */
901             break;
902         case 0x18u:                                           /* Slave Address ACK */
903             I2C_SET_DATA(i2c, u8DataAddr);                   /* Write Lo byte address of register */
904             break;
905         case 0x20u:                                           /* Slave Address NACK */
906         case 0x30u:                                           /* Master transmit data NACK */
907             u8Ctrl = I2C_CTL_STO_SI;                       /* Clear SI and send STOP */
908             u8Err = 1u;
909             break;
910         case 0x28u:
911             if(u32txLen < 1u)
912             {
913                 I2C_SET_DATA(i2c, data);
914                 u32txLen++;
915             }
916             else
917             {
918                 u8Ctrl = I2C_CTL_STO_SI;                   /* Clear SI and send STOP */
919                 u8Xfering = 0u;
920             }
921             break;
922         case 0x38u:                                           /* Arbitration Lost */
923         default:                                             /* Unknow status */
924             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);      /* Clear SI and send STOP */
925             u8Ctrl = I2C_CTL_SI;
926             u8Err = 1u;
927             break;
928         }
929         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                        /* Write controlbit to I2C_CTL register */
930     }
931     return (u8Err | u8Xfering);                                  /* return (Success)/(Fail) status */
932 }
933 
934 
935 /**
936   * @brief      Specify a byte register address and write multi bytes to Slave
937   *
938   * @param[in]  i2c             Point to I2C peripheral
939   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
940   * @param[in]  u8DataAddr      Specify a address (1 byte) of data write to
941   * @param[in]  data[]           Pointer to array to write data to Slave
942   * @param[in]  u32wLen         How many bytes need to write to Slave
943   *
944   * @return     A length of how many bytes have been transmitted.
945   *
946   * @details    The function is used for I2C Master specify a byte address that multi data bytes write to in Slave.
947   *
948   */
949 
I2C_WriteMultiBytesOneReg(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8DataAddr,uint8_t data[],uint32_t u32wLen)950 uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data[], uint32_t u32wLen)
951 {
952     uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
953     uint32_t u32txLen = 0u;
954     uint32_t u32TimeOutCount;
955 
956     g_I2C_i32ErrCode = 0;
957 
958     I2C_START(i2c);                                              /* Send START */
959     while(u8Xfering && (u8Err == 0u))
960     {
961         u32TimeOutCount = SystemCoreClock;
962         I2C_WAIT_READY(i2c)
963         {
964             u32TimeOutCount--;
965             if(u32TimeOutCount == 0)
966             {
967                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
968                 break;
969             }
970         }
971 
972         switch(I2C_GET_STATUS(i2c))
973         {
974         case 0x08u:
975             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));    /* Write SLA+W to Register I2CDAT */
976             u8Ctrl = I2C_CTL_SI;
977             break;
978         case 0x18u:                                           /* Slave Address ACK */
979             I2C_SET_DATA(i2c, u8DataAddr);                   /* Write Lo byte address of register */
980             break;
981         case 0x20u:                                           /* Slave Address NACK */
982         case 0x30u:                                           /* Master transmit data NACK */
983             u8Ctrl = I2C_CTL_STO_SI;                       /* Clear SI and send STOP */
984             u8Err = 1u;
985             break;
986         case 0x28u:
987             if(u32txLen < u32wLen)
988             {
989                 I2C_SET_DATA(i2c, data[u32txLen++]);
990             }
991             else
992             {
993                 u8Ctrl = I2C_CTL_STO_SI;                   /* Clear SI and send STOP */
994                 u8Xfering = 0u;
995             }
996             break;
997         case 0x38u:                                           /* Arbitration Lost */
998         default:                                             /* Unknow status */
999             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);        /* Clear SI and send STOP */
1000             u8Ctrl = I2C_CTL_SI;
1001             u8Err = 1u;
1002             break;
1003         }
1004         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                        /* Write controlbit to I2C_CTL register */
1005     }
1006 
1007     return u32txLen;                                             /* Return bytes length that have been transmitted */
1008 }
1009 
1010 /**
1011   * @brief      Specify two bytes register address and Write a byte to Slave
1012   *
1013   * @param[in]  i2c             Point to I2C peripheral
1014   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
1015   * @param[in]  u16DataAddr     Specify a address (2 byte) of data write to
1016   * @param[in]  data            Write a byte data to Slave
1017   *
1018   * @retval     0               Write data success
1019   * @retval     1               Write data fail, or bus occurs error events
1020   *
1021   * @details    The function is used for I2C Master specify two bytes address that data write to in Slave.
1022   *
1023   */
1024 
I2C_WriteByteTwoRegs(I2C_T * i2c,uint8_t u8SlaveAddr,uint16_t u16DataAddr,uint8_t data)1025 uint8_t I2C_WriteByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data)
1026 {
1027     uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
1028     uint32_t u32txLen = 0u;
1029     uint32_t u32TimeOutCount;
1030 
1031     g_I2C_i32ErrCode = 0;
1032 
1033     I2C_START(i2c);                                                         /* Send START */
1034     while(u8Xfering && (u8Err == 0u))
1035     {
1036         u32TimeOutCount = SystemCoreClock;
1037         I2C_WAIT_READY(i2c)
1038         {
1039             u32TimeOutCount--;
1040             if(u32TimeOutCount == 0)
1041             {
1042                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
1043                 break;
1044             }
1045         }
1046 
1047         switch(I2C_GET_STATUS(i2c))
1048         {
1049         case 0x08u:
1050             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));               /* Write SLA+W to Register I2CDAT */
1051             u8Ctrl = I2C_CTL_SI;                                      /* Clear SI */
1052             break;
1053         case 0x18u:                                                      /* Slave Address ACK */
1054             I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u));    /* Write Hi byte address of register */
1055             break;
1056         case 0x20u:                                                      /* Slave Address NACK */
1057         case 0x30u:                                                      /* Master transmit data NACK */
1058             u8Ctrl = I2C_CTL_STO_SI;                                  /* Clear SI and send STOP */
1059             u8Err = 1u;
1060             break;
1061         case 0x28u:
1062             if(u8Addr)
1063             {
1064                 I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu));       /* Write Lo byte address of register */
1065                 u8Addr = 0u;
1066             }
1067             else if((u32txLen < 1u) && (u8Addr == 0u))
1068             {
1069                 I2C_SET_DATA(i2c, data);
1070                 u32txLen++;
1071             }
1072             else
1073             {
1074                 u8Ctrl = I2C_CTL_STO_SI;                              /* Clear SI and send STOP */
1075                 u8Xfering = 0u;
1076             }
1077             break;
1078         case 0x38u:                                                      /* Arbitration Lost */
1079         default:                                                        /* Unknow status */
1080             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);                   /* Clear SI and send STOP */
1081             u8Ctrl = I2C_CTL_SI;
1082             u8Err = 1u;
1083             break;
1084         }
1085         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                                   /* Write controlbit to I2C_CTL register */
1086     }
1087     return (u8Err | u8Xfering);                                             /* return (Success)/(Fail) status */
1088 }
1089 
1090 
1091 /**
1092   * @brief      Specify two bytes register address and write multi bytes to Slave
1093   *
1094   * @param[in]  i2c             Point to I2C peripheral
1095   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
1096   * @param[in]  u16DataAddr     Specify a address (2 bytes) of data write to
1097   * @param[in]  data[]          A data array for write data to Slave
1098   * @param[in]  u32wLen         How many bytes need to write to Slave
1099   *
1100   * @return     A length of how many bytes have been transmitted.
1101   *
1102   * @details    The function is used for I2C Master specify two bytes address that multi data write to in Slave.
1103   *
1104   */
1105 
I2C_WriteMultiBytesTwoRegs(I2C_T * i2c,uint8_t u8SlaveAddr,uint16_t u16DataAddr,uint8_t data[],uint32_t u32wLen)1106 uint32_t I2C_WriteMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data[], uint32_t u32wLen)
1107 {
1108     uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
1109     uint32_t u32txLen = 0u;
1110     uint32_t u32TimeOutCount;
1111 
1112     g_I2C_i32ErrCode = 0;
1113 
1114     I2C_START(i2c);                                                         /* Send START */
1115     while(u8Xfering && (u8Err == 0u))
1116     {
1117         u32TimeOutCount = SystemCoreClock;
1118         I2C_WAIT_READY(i2c)
1119         {
1120             u32TimeOutCount--;
1121             if(u32TimeOutCount == 0)
1122             {
1123                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
1124                 break;
1125             }
1126         }
1127 
1128         switch(I2C_GET_STATUS(i2c))
1129         {
1130         case 0x08u:
1131             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));               /* Write SLA+W to Register I2CDAT */
1132             u8Ctrl = I2C_CTL_SI;                                      /* Clear SI */
1133             break;
1134         case 0x18u:                                                      /* Slave Address ACK */
1135             I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u));    /* Write Hi byte address of register */
1136             break;
1137         case 0x20u:                                                      /* Slave Address NACK */
1138         case 0x30u:                                                      /* Master transmit data NACK */
1139             u8Ctrl = I2C_CTL_STO_SI;                                  /* Clear SI and send STOP */
1140             u8Err = 1u;
1141             break;
1142         case 0x28u:
1143             if(u8Addr)
1144             {
1145                 I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu));       /* Write Lo byte address of register */
1146                 u8Addr = 0u;
1147             }
1148             else if((u32txLen < u32wLen) && (u8Addr == 0u))
1149             {
1150                 I2C_SET_DATA(i2c, data[u32txLen++]);                           /* Write data to Register I2CDAT*/
1151             }
1152             else
1153             {
1154                 u8Ctrl = I2C_CTL_STO_SI;                              /* Clear SI and send STOP */
1155                 u8Xfering = 0u;
1156             }
1157             break;
1158         case 0x38u:                                                      /* Arbitration Lost */
1159         default:                                                        /* Unknow status */
1160             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);                   /* Clear SI and send STOP */
1161             u8Ctrl = I2C_CTL_SI;
1162             u8Err = 1u;
1163             break;
1164         }
1165         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                                   /* Write controlbit to I2C_CTL register */
1166     }
1167     return u32txLen;                                                        /* Return bytes length that have been transmitted */
1168 }
1169 
1170 /**
1171   * @brief      Read a byte from Slave
1172   *
1173   * @param[in]  i2c             Point to I2C peripheral
1174   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
1175   *
1176   * @return     Read a byte data from Slave
1177   *
1178   * @details    The function is used for I2C Master to read a byte data from Slave.
1179   *
1180   */
I2C_ReadByte(I2C_T * i2c,uint8_t u8SlaveAddr)1181 uint8_t I2C_ReadByte(I2C_T *i2c, uint8_t u8SlaveAddr)
1182 {
1183     uint8_t u8Xfering = 1u, u8Err = 0u, rdata = 0u, u8Ctrl = 0u;
1184     uint32_t u32TimeOutCount;
1185 
1186     g_I2C_i32ErrCode = 0;
1187 
1188     I2C_START(i2c);                                                /* Send START */
1189     while(u8Xfering && (u8Err == 0u))
1190     {
1191         u32TimeOutCount = SystemCoreClock;
1192         I2C_WAIT_READY(i2c)
1193         {
1194             u32TimeOutCount--;
1195             if(u32TimeOutCount == 0)
1196             {
1197                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
1198                 break;
1199             }
1200         }
1201 
1202         switch(I2C_GET_STATUS(i2c))
1203         {
1204         case 0x08u:
1205             I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));    /* Write SLA+R to Register I2CDAT */
1206             u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
1207             break;
1208         case 0x40u:                                             /* Slave Address ACK */
1209             u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
1210             break;
1211         case 0x48u:                                             /* Slave Address NACK */
1212             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1213             u8Err = 1u;
1214             break;
1215         case 0x58u:
1216             rdata = (uint8_t) I2C_GET_DATA(i2c);         /* Receive Data */
1217             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1218             u8Xfering = 0u;
1219             break;
1220         case 0x38u:                                             /* Arbitration Lost */
1221         default:                                               /* Unknow status */
1222             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);        /* Clear SI and send STOP */
1223             u8Ctrl = I2C_CTL_SI;
1224             u8Err = 1u;
1225             break;
1226         }
1227         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                          /* Write controlbit to I2C_CTL register */
1228     }
1229     if(u8Err)
1230     {
1231         rdata = 0u;                                                 /* If occurs error, return 0 */
1232     }
1233     return rdata;                                                  /* Return read data */
1234 }
1235 
1236 
1237 /**
1238   * @brief      Read multi bytes from Slave
1239   *
1240   * @param[in]  i2c             Point to I2C peripheral
1241   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
1242   * @param[out] rdata[]         A data array to store data from Slave
1243   * @param[in]  u32rLen         How many bytes need to read from Slave
1244   *
1245   * @return     A length of how many bytes have been received
1246   *
1247   * @details    The function is used for I2C Master to read multi data bytes from Slave.
1248   *
1249   *
1250   */
I2C_ReadMultiBytes(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t rdata[],uint32_t u32rLen)1251 uint32_t I2C_ReadMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t rdata[], uint32_t u32rLen)
1252 {
1253     uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
1254     uint32_t u32rxLen = 0u;
1255     uint32_t u32TimeOutCount;
1256 
1257     g_I2C_i32ErrCode = 0;
1258 
1259     I2C_START(i2c);                                                /* Send START */
1260     while(u8Xfering && (u8Err == 0u))
1261     {
1262         u32TimeOutCount = SystemCoreClock;
1263         I2C_WAIT_READY(i2c)
1264         {
1265             u32TimeOutCount--;
1266             if(u32TimeOutCount == 0)
1267             {
1268                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
1269                 break;
1270             }
1271         }
1272 
1273         switch(I2C_GET_STATUS(i2c))
1274         {
1275         case 0x08u:
1276             I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));    /* Write SLA+R to Register I2CDAT */
1277             u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
1278             break;
1279         case 0x40u:                                             /* Slave Address ACK */
1280             u8Ctrl = I2C_CTL_SI_AA;                          /* Clear SI and set ACK */
1281             break;
1282         case 0x48u:                                             /* Slave Address NACK */
1283             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1284             u8Err = 1u;
1285             break;
1286         case 0x50u:
1287             rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);    /* Receive Data */
1288             if(u32rxLen < (u32rLen - 1u))
1289             {
1290                 u8Ctrl = I2C_CTL_SI_AA;                             /* Clear SI and set ACK */
1291             }
1292             else
1293             {
1294                 u8Ctrl = I2C_CTL_SI;                                /* Clear SI */
1295             }
1296             break;
1297         case 0x58u:
1298             rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);    /* Receive Data */
1299             u8Ctrl = I2C_CTL_STO_SI;                                /* Clear SI and send STOP */
1300             u8Xfering = 0u;
1301             break;
1302         case 0x38u:                                                    /* Arbitration Lost */
1303         default:                                                      /* Unknow status */
1304             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);               /* Clear SI and send STOP */
1305             u8Ctrl = I2C_CTL_SI;
1306             u8Err = 1u;
1307             break;
1308         }
1309         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                                 /* Write controlbit to I2C_CTL register */
1310     }
1311     return u32rxLen;                                                      /* Return bytes length that have been received */
1312 }
1313 
1314 
1315 /**
1316   * @brief      Specify a byte register address and read a byte from Slave
1317   *
1318   * @param[in]  i2c             Point to I2C peripheral
1319   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
1320   * @param[in]  u8DataAddr      Specify a address(1 byte) of data read from
1321   *
1322   * @return     Read a byte data from Slave
1323   *
1324   * @details    The function is used for I2C Master specify a byte address that a data byte read from Slave.
1325   *
1326   *
1327   */
I2C_ReadByteOneReg(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8DataAddr)1328 uint8_t I2C_ReadByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr)
1329 {
1330     uint8_t u8Xfering = 1u, u8Err = 0u, rdata = 0u, u8Ctrl = 0u;
1331     uint32_t u32TimeOutCount;
1332 
1333     g_I2C_i32ErrCode = 0;
1334 
1335     I2C_START(i2c);                                                /* Send START */
1336     while(u8Xfering && (u8Err == 0u))
1337     {
1338         u32TimeOutCount = SystemCoreClock;
1339         I2C_WAIT_READY(i2c)
1340         {
1341             u32TimeOutCount--;
1342             if(u32TimeOutCount == 0)
1343             {
1344                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
1345                 break;
1346             }
1347         }
1348 
1349         switch(I2C_GET_STATUS(i2c))
1350         {
1351         case 0x08u:
1352             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));      /* Write SLA+W to Register I2CDAT */
1353             u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
1354             break;
1355         case 0x18u:                                             /* Slave Address ACK */
1356             I2C_SET_DATA(i2c, u8DataAddr);                     /* Write Lo byte address of register */
1357             break;
1358         case 0x20u:                                             /* Slave Address NACK */
1359         case 0x30u:                                             /* Master transmit data NACK */
1360             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1361             u8Err = 1u;
1362             break;
1363         case 0x28u:
1364             u8Ctrl = I2C_CTL_STA_SI;                         /* Send repeat START */
1365             break;
1366         case 0x10u:
1367             I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));    /* Write SLA+R to Register I2CDAT */
1368             u8Ctrl = I2C_CTL_SI;                               /* Clear SI */
1369             break;
1370         case 0x40u:                                             /* Slave Address ACK */
1371             u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
1372             break;
1373         case 0x48u:                                             /* Slave Address NACK */
1374             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1375             u8Err = 1u;
1376             break;
1377         case 0x58u:
1378             rdata = (uint8_t) I2C_GET_DATA(i2c);               /* Receive Data */
1379             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1380             u8Xfering = 0u;
1381             break;
1382         case 0x38u:                                             /* Arbitration Lost */
1383         default:                                               /* Unknow status */
1384             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);        /* Clear SI and send STOP */
1385             u8Ctrl = I2C_CTL_SI;
1386             u8Err = 1u;
1387             break;
1388         }
1389         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                          /* Write controlbit to I2C_CTL register */
1390     }
1391     if(u8Err)
1392     {
1393         rdata = 0u;                                                 /* If occurs error, return 0 */
1394     }
1395     return rdata;                                                  /* Return read data */
1396 }
1397 
1398 /**
1399   * @brief      Specify a byte register address and read multi bytes from Slave
1400   *
1401   * @param[in]  i2c             Point to I2C peripheral
1402   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
1403   * @param[in]  u8DataAddr      Specify a address (1 byte) of data read from
1404   * @param[out] rdata[]         A data array to store data from Slave
1405   * @param[in]  u32rLen         How many bytes need to read from Slave
1406   *
1407   * @return     A length of how many bytes have been received
1408   *
1409   * @details    The function is used for I2C Master specify a byte address that multi data bytes read from Slave.
1410   *
1411   *
1412   */
I2C_ReadMultiBytesOneReg(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8DataAddr,uint8_t rdata[],uint32_t u32rLen)1413 uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t rdata[], uint32_t u32rLen)
1414 {
1415     uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
1416     uint32_t u32rxLen = 0u;
1417     uint32_t u32TimeOutCount;
1418 
1419     g_I2C_i32ErrCode = 0;
1420 
1421     I2C_START(i2c);                                                /* Send START */
1422     while(u8Xfering && (u8Err == 0u))
1423     {
1424         u32TimeOutCount = SystemCoreClock;
1425         I2C_WAIT_READY(i2c)
1426         {
1427             u32TimeOutCount--;
1428             if(u32TimeOutCount == 0)
1429             {
1430                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
1431                 break;
1432             }
1433         }
1434 
1435         switch(I2C_GET_STATUS(i2c))
1436         {
1437         case 0x08u:
1438             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));      /* Write SLA+W to Register I2CDAT */
1439             u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
1440             break;
1441         case 0x18u:                                             /* Slave Address ACK */
1442             I2C_SET_DATA(i2c, u8DataAddr);                     /* Write Lo byte address of register */
1443             break;
1444         case 0x20u:                                             /* Slave Address NACK */
1445         case 0x30u:                                             /* Master transmit data NACK */
1446             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1447             u8Err = 1u;
1448             break;
1449         case 0x28u:
1450             u8Ctrl = I2C_CTL_STA_SI;                         /* Send repeat START */
1451             break;
1452         case 0x10u:
1453             I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));    /* Write SLA+R to Register I2CDAT */
1454             u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
1455             break;
1456         case 0x40u:                                             /* Slave Address ACK */
1457             u8Ctrl = I2C_CTL_SI_AA;                          /* Clear SI and set ACK */
1458             break;
1459         case 0x48u:                                             /* Slave Address NACK */
1460             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1461             u8Err = 1u;
1462             break;
1463         case 0x50u:
1464             rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);   /* Receive Data */
1465             if(u32rxLen < (u32rLen - 1u))
1466             {
1467                 u8Ctrl = I2C_CTL_SI_AA;                      /* Clear SI and set ACK */
1468             }
1469             else
1470             {
1471                 u8Ctrl = I2C_CTL_SI;                         /* Clear SI */
1472             }
1473             break;
1474         case 0x58u:
1475             rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);   /* Receive Data */
1476             u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
1477             u8Xfering = 0u;
1478             break;
1479         case 0x38u:                                             /* Arbitration Lost */
1480         default:                                               /* Unknow status */
1481             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);        /* Clear SI and send STOP */
1482             u8Ctrl = I2C_CTL_SI;
1483             u8Err = 1u;
1484             break;
1485         }
1486         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                          /* Write controlbit to I2C_CTL register */
1487     }
1488     return u32rxLen;                                               /* Return bytes length that have been received */
1489 }
1490 
1491 /**
1492   * @brief      Specify two bytes register address and read a byte from Slave
1493   *
1494   * @param[in]  i2c             Point to I2C peripheral
1495   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
1496   * @param[in]  u16DataAddr     Specify an address(2 bytes) of data read from
1497   *
1498   * @return     Read a byte data from Slave
1499   *
1500   * @details    The function is used for I2C Master specify two bytes address that a data byte read from Slave.
1501   *
1502   *
1503   */
I2C_ReadByteTwoRegs(I2C_T * i2c,uint8_t u8SlaveAddr,uint16_t u16DataAddr)1504 uint8_t I2C_ReadByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr)
1505 {
1506     uint8_t u8Xfering = 1u, u8Err = 0u, rdata = 0u, u8Addr = 1u, u8Ctrl = 0u;
1507     uint32_t u32TimeOutCount;
1508 
1509     g_I2C_i32ErrCode = 0;
1510 
1511     I2C_START(i2c);                                                         /* Send START */
1512     while(u8Xfering && (u8Err == 0u))
1513     {
1514         u32TimeOutCount = SystemCoreClock;
1515         I2C_WAIT_READY(i2c)
1516         {
1517             u32TimeOutCount--;
1518             if(u32TimeOutCount == 0)
1519             {
1520                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
1521                 break;
1522             }
1523         }
1524 
1525         switch(I2C_GET_STATUS(i2c))
1526         {
1527         case 0x08u:
1528             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));               /* Write SLA+W to Register I2CDAT */
1529             u8Ctrl = I2C_CTL_SI;                                      /* Clear SI */
1530             break;
1531         case 0x18u:                                                      /* Slave Address ACK */
1532             I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u));    /* Write Hi byte address of register */
1533             break;
1534         case 0x20u:                                                      /* Slave Address NACK */
1535         case 0x30u:                                                      /* Master transmit data NACK */
1536             u8Ctrl = I2C_CTL_STO_SI;                                  /* Clear SI and send STOP */
1537             u8Err = 1u;
1538             break;
1539         case 0x28u:
1540             if(u8Addr)
1541             {
1542                 I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu));       /* Write Lo byte address of register */
1543                 u8Addr = 0u;
1544             }
1545             else
1546             {
1547                 u8Ctrl = I2C_CTL_STA_SI;                              /* Clear SI and send repeat START */
1548             }
1549             break;
1550         case 0x10u:
1551             I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));             /* Write SLA+R to Register I2CDAT */
1552             u8Ctrl = I2C_CTL_SI;                                      /* Clear SI */
1553             break;
1554         case 0x40u:                                                      /* Slave Address ACK */
1555             u8Ctrl = I2C_CTL_SI;                                      /* Clear SI */
1556             break;
1557         case 0x48u:                                                      /* Slave Address NACK */
1558             u8Ctrl = I2C_CTL_STO_SI;                                  /* Clear SI and send STOP */
1559             u8Err = 1u;
1560             break;
1561         case 0x58u:
1562             rdata = (uint8_t) I2C_GET_DATA(i2c);                  /* Receive Data */
1563             u8Ctrl = I2C_CTL_STO_SI;                                  /* Clear SI and send STOP */
1564             u8Xfering = 0u;
1565             break;
1566         case 0x38u:                                                      /* Arbitration Lost */
1567         default:                                                        /* Unknow status */
1568             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);                 /* Clear SI and send STOP */
1569             u8Ctrl = I2C_CTL_SI;
1570             u8Err = 1u;
1571             break;
1572         }
1573         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                                   /* Write controlbit to I2C_CTL register */
1574     }
1575     if(u8Err)
1576     {
1577         rdata = 0u;                                                          /* If occurs error, return 0 */
1578     }
1579     return rdata;                                                           /* Return read data */
1580 }
1581 
1582 /**
1583   * @brief      Specify two bytes register address and read multi bytes from Slave
1584   *
1585   * @param[in]  i2c             Point to I2C peripheral
1586   * @param[in]  u8SlaveAddr     Access Slave address(7-bit)
1587   * @param[in]  u16DataAddr     Specify a address (2 bytes) of data read from
1588   * @param[out] rdata[]         A data array to store data from Slave
1589   * @param[in]  u32rLen         How many bytes need to read from Slave
1590   *
1591   * @return     A length of how many bytes have been received
1592   *
1593   * @details    The function is used for I2C Master specify two bytes address that multi data bytes read from Slave.
1594   *
1595   *
1596   */
I2C_ReadMultiBytesTwoRegs(I2C_T * i2c,uint8_t u8SlaveAddr,uint16_t u16DataAddr,uint8_t rdata[],uint32_t u32rLen)1597 uint32_t I2C_ReadMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t rdata[], uint32_t u32rLen)
1598 {
1599     uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
1600     uint32_t u32rxLen = 0u;
1601     uint32_t u32TimeOutCount;
1602 
1603     g_I2C_i32ErrCode = 0;
1604 
1605     I2C_START(i2c);                                                         /* Send START */
1606     while(u8Xfering && (u8Err == 0u))
1607     {
1608         u32TimeOutCount = SystemCoreClock;
1609         I2C_WAIT_READY(i2c)
1610         {
1611             u32TimeOutCount--;
1612             if(u32TimeOutCount == 0)
1613             {
1614                 g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
1615                 break;
1616             }
1617         }
1618 
1619         switch(I2C_GET_STATUS(i2c))
1620         {
1621         case 0x08u:
1622             I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));               /* Write SLA+W to Register I2CDAT */
1623             u8Ctrl = I2C_CTL_SI;                                      /* Clear SI */
1624             break;
1625         case 0x18u:                                                      /* Slave Address ACK */
1626             I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u));    /* Write Hi byte address of register */
1627             break;
1628         case 0x20u:                                                      /* Slave Address NACK */
1629         case 0x30u:                                                      /* Master transmit data NACK */
1630             u8Ctrl = I2C_CTL_STO_SI;                                  /* Clear SI and send STOP */
1631             u8Err = 1u;
1632             break;
1633         case 0x28u:
1634             if(u8Addr)
1635             {
1636                 I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu));       /* Write Lo byte address of register */
1637                 u8Addr = 0u;
1638             }
1639             else
1640             {
1641                 u8Ctrl = I2C_CTL_STA_SI;                              /* Clear SI and send repeat START */
1642             }
1643             break;
1644         case 0x10u:
1645             I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));             /* Write SLA+R to Register I2CDAT */
1646             u8Ctrl = I2C_CTL_SI;                                      /* Clear SI */
1647             break;
1648         case 0x40u:                                                      /* Slave Address ACK */
1649             u8Ctrl = I2C_CTL_SI_AA;                                   /* Clear SI and set ACK */
1650             break;
1651         case 0x48u:                                                      /* Slave Address NACK */
1652             u8Ctrl = I2C_CTL_STO_SI;                                  /* Clear SI and send STOP */
1653             u8Err = 1u;
1654             break;
1655         case 0x50u:
1656             rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);      /* Receive Data */
1657             if(u32rxLen < (u32rLen - 1u))
1658             {
1659                 u8Ctrl = I2C_CTL_SI_AA;                               /* Clear SI and set ACK */
1660             }
1661             else
1662             {
1663                 u8Ctrl = I2C_CTL_SI;                                  /* Clear SI */
1664             }
1665             break;
1666         case 0x58u:
1667             rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);      /* Receive Data */
1668             u8Ctrl = I2C_CTL_STO_SI;                                  /* Clear SI and send STOP */
1669             u8Xfering = 0u;
1670             break;
1671         case 0x38u:                                                      /* Arbitration Lost */
1672         default:                                                        /* Unknow status */
1673             I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI);                 /* Clear SI and send STOP */
1674             u8Ctrl = I2C_CTL_SI;
1675             u8Err = 1u;
1676             break;
1677         }
1678         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                                   /* Write controlbit to I2C_CTL register */
1679     }
1680     return u32rxLen;                                                        /* Return bytes length that have been received */
1681 }
1682 
1683 
1684 /*@}*/ /* end of group I2C_EXPORTED_FUNCTIONS */
1685 
1686 /*@}*/ /* end of group I2C_Driver */
1687 
1688 /*@}*/ /* end of group Standard_Driver */
1689 
1690 /*** (C) COPYRIGHT 2023 Nuvoton Technology Corp. ***/
1691