1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_lpi2c.h"
10 #include <stdlib.h>
11 #include <string.h>
12 
13 /*
14  * $Coverage Justification Reference$
15  *
16  * $Justification fsl_lpi2c_c_ref_1$
17  * The default branch cannot be executed in any circumstances, it is only added to avoid MISRA violation.
18  *
19  * $Justification fsl_lpi2c_c_ref_2$
20  * Two instances failed to simulate #kStatus_LPI2C_Busy.
21  *
22  * $Justification fsl_lpi2c_c_ref_3$
23  * When the transmission is completed (remaining == 0), the SDF and RSF will be set, and the flags are get before
24  * that(get before set), it will be over when the next cycle occurs, the first condition cannot be verified, and the
25  * remaining will not be verified.(will improve)
26  *
27  */
28 
29 /*******************************************************************************
30  * Definitions
31  ******************************************************************************/
32 
33 /* Component ID definition, used by tools. */
34 #ifndef FSL_COMPONENT_ID
35 #define FSL_COMPONENT_ID "platform.drivers.lpi2c"
36 #endif
37 
38 #if defined(LPI2C_RSTS)
39 #define LPI2C_RESETS_ARRAY LPI2C_RSTS
40 #endif
41 
42 /*! @brief LPI2C master fifo commands. */
43 enum
44 {
45     kTxDataCmd = LPI2C_MTDR_CMD(0x0U), /*!< Transmit DATA[7:0] */
46     kRxDataCmd = LPI2C_MTDR_CMD(0X1U), /*!< Receive (DATA[7:0] + 1) bytes */
47     kStopCmd   = LPI2C_MTDR_CMD(0x2U), /*!< Generate STOP condition */
48     kStartCmd  = LPI2C_MTDR_CMD(0x4U), /*!< Generate(repeated) START and transmit address in DATA[[7:0] */
49 };
50 
51 /*!
52  * @brief Default watermark values.
53  *
54  * The default watermarks are set to zero.
55  */
56 enum
57 {
58     kDefaultTxWatermark = 0,
59     kDefaultRxWatermark = 0,
60 };
61 
62 /*! @brief States for the state machine used by transactional APIs. */
63 enum
64 {
65     kIdleState = 0,
66     kSendCommandState,
67     kIssueReadCommandState,
68     kTransferDataState,
69     kStopState,
70     kWaitForCompletionState,
71 };
72 
73 /*!
74  * @brief Structure definition for variables that passed as parameters in LPI2C_RunTransferStateMachine.
75  * The structure is private.
76  */
77 typedef struct _lpi2c_state_machine_param
78 {
79     bool state_complete; /*!< status of complete */
80     size_t rxCount;      /*!< rx count */
81     size_t txCount;      /*!< tx count */
82     uint32_t status;     /*!< machine status */
83 } lpi2c_state_machine_param_t;
84 
85 /*! @brief Typedef for slave interrupt handler. */
86 typedef void (*lpi2c_slave_isr_t)(LPI2C_Type *base, lpi2c_slave_handle_t *handle);
87 
88 /*******************************************************************************
89  * Prototypes
90  ******************************************************************************/
91 static uint32_t LPI2C_GetCyclesForWidth(
92     uint32_t sourceClock_Hz, uint32_t width_ns, uint32_t minCycles, uint32_t maxCycles, uint32_t prescaler);
93 
94 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base);
95 
96 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone);
97 
98 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle);
99 
100 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags);
101 
102 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance);
103 
104 /*!
105  * @brief introduce function LPI2C_TransferStateMachineSendCommandState.
106  * This function was deal with Send Command State.
107  *
108  * @param base The I2C peripheral base address.
109  * @param handle Master nonblocking driver handle.
110  * @param variable_set Pass the address of the parent function variable.
111  */
112 static void LPI2C_TransferStateMachineSendCommand(LPI2C_Type *base,
113                                                   lpi2c_master_handle_t *handle,
114                                                   lpi2c_state_machine_param_t *stateParams);
115 
116 /*!
117  * @brief introduce function LPI2C_TransferStateMachineIssueReadCommandState.
118  * This function was deal with Issue Read Command State.
119  *
120  * @param base The I2C peripheral base address.
121  * @param handle Master nonblocking driver handle.
122  * @param stateParams Pass the address of the parent function variable.
123  */
124 static void LPI2C_TransferStateMachineReadCommand(LPI2C_Type *base,
125                                                   lpi2c_master_handle_t *handle,
126                                                   lpi2c_state_machine_param_t *stateParams);
127 
128 /*!
129  * @brief introduce function LPI2C_TransferStateMachineTransferDataState.
130  * This function was deal with init Transfer Data State.
131  *
132  * @param base The I2C peripheral base address.
133  * @param handle Master nonblocking driver handle.
134  * @param stateParams Pass the address of the parent function variable.
135  */
136 static void LPI2C_TransferStateMachineTransferData(LPI2C_Type *base,
137                                                    lpi2c_master_handle_t *handle,
138                                                    lpi2c_state_machine_param_t *stateParams);
139 
140 /*!
141  * @brief introduce function LPI2C_TransferStateMachineStopState.
142  * This function was deal with Stop State.
143  *
144  * @param base The I2C peripheral base address.
145  * @param handle Master nonblocking driver handle.
146  * @param stateParams Pass the address of the parent function variable.
147  * @param[out] isDone Set to true if the transfer has completed.
148  */
149 static void LPI2C_TransferStateMachineStopState(LPI2C_Type *base,
150                                                 lpi2c_master_handle_t *handle,
151                                                 lpi2c_state_machine_param_t *stateParams,
152                                                 bool *isDone);
153 
154 /*!
155  * @brief introduce function LPI2C_TransferStateMachineWaitState.
156  * This function was deal with Wait For Completion State.
157  *
158  * @param base The I2C peripheral base address.
159  * @param handle Master nonblocking driver handle.
160  * @param stateParams Pass the address of the parent function variable.
161  * @param[out] isDone Set to true if the transfer has completed.
162  */
163 static void LPI2C_TransferStateMachineWaitState(LPI2C_Type *base,
164                                                 lpi2c_master_handle_t *handle,
165                                                 lpi2c_state_machine_param_t *stateParams,
166                                                 bool *isDone);
167 
168 /*******************************************************************************
169  * Variables
170  ******************************************************************************/
171 
172 /*! @brief Array to map LPI2C instance number to base pointer. */
173 static LPI2C_Type *const kLpi2cBases[] = LPI2C_BASE_PTRS;
174 
175 /*! @brief Array to map LPI2C instance number to IRQ number, used internally for LPI2C master interrupt and EDMA
176 transactional APIs. */
177 IRQn_Type const kLpi2cIrqs[] = LPI2C_IRQS;
178 
179 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
180 /*! @brief Array to map LPI2C instance number to clock gate enum. */
181 static clock_ip_name_t const kLpi2cClocks[] = LPI2C_CLOCKS;
182 
183 #if defined(LPI2C_PERIPH_CLOCKS)
184 /*! @brief Array to map LPI2C instance number to pheripheral clock gate enum. */
185 static const clock_ip_name_t kLpi2cPeriphClocks[] = LPI2C_PERIPH_CLOCKS;
186 #endif
187 
188 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
189 
190 /*! @brief Pointer to master IRQ handler for each instance, used internally for LPI2C master interrupt and EDMA
191 transactional APIs. */
192 lpi2c_master_isr_t s_lpi2cMasterIsr;
193 
194 /*! @brief Pointers to master handles for each instance, used internally for LPI2C master interrupt and EDMA
195 transactional APIs. */
196 void *s_lpi2cMasterHandle[ARRAY_SIZE(kLpi2cBases)];
197 
198 /*! @brief Pointer to slave IRQ handler for each instance. */
199 static lpi2c_slave_isr_t s_lpi2cSlaveIsr;
200 
201 /*! @brief Pointers to slave handles for each instance. */
202 static lpi2c_slave_handle_t *s_lpi2cSlaveHandle[ARRAY_SIZE(kLpi2cBases)];
203 
204 #if defined(LPI2C_RESETS_ARRAY)
205 /* Reset array */
206 static const reset_ip_name_t s_lpi2cResets[] = LPI2C_RESETS_ARRAY;
207 #endif
208 
209 /*******************************************************************************
210  * Code
211  ******************************************************************************/
212 
213 /*!
214  * brief Returns an instance number given a base address.
215  *
216  * If an invalid base address is passed, debug builds will assert. Release builds will just return
217  * instance number 0.
218  *
219  * param base The LPI2C peripheral base address.
220  * return LPI2C instance number starting from 0.
221  */
LPI2C_GetInstance(LPI2C_Type * base)222 uint32_t LPI2C_GetInstance(LPI2C_Type *base)
223 {
224     uint32_t instance;
225     for (instance = 0U; instance < ARRAY_SIZE(kLpi2cBases); ++instance)
226     {
227         if (kLpi2cBases[instance] == base)
228         {
229             break;
230         }
231     }
232 
233     assert(instance < ARRAY_SIZE(kLpi2cBases));
234     return instance;
235 }
236 
237 /*!
238  * @brief Computes a cycle count for a given time in nanoseconds.
239  * @param sourceClock_Hz LPI2C functional clock frequency in Hertz.
240  * @param width_ns Desired with in nanoseconds.
241  * @param minCycles Minimum cycle count.
242  * @param maxCycles Maximum cycle count.
243  * @param prescaler LPI2C prescaler setting. If the cycle period is not affected by the prescaler value, set it to 0.
244  */
LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,uint32_t width_ns,uint32_t minCycles,uint32_t maxCycles,uint32_t prescaler)245 static uint32_t LPI2C_GetCyclesForWidth(
246     uint32_t sourceClock_Hz, uint32_t width_ns, uint32_t minCycles, uint32_t maxCycles, uint32_t prescaler)
247 {
248     assert(sourceClock_Hz > 0U);
249 
250     uint32_t divider = 1U;
251 
252     while (prescaler != 0U)
253     {
254         divider *= 2U;
255         prescaler--;
256     }
257 
258     uint32_t busCycle_ns = 1000000U / (sourceClock_Hz / divider / 1000U);
259     /* Calculate the cycle count, round up the calculated value. */
260     uint32_t cycles = (width_ns * 10U / busCycle_ns + 5U) / 10U;
261 
262     /* If the calculated value is smaller than the minimum value, use the minimum value */
263     if (cycles < minCycles)
264     {
265         cycles = minCycles;
266     }
267     /* If the calculated value is larger than the maximum value, use the maxmum value */
268     if (cycles > maxCycles)
269     {
270         cycles = maxCycles;
271     }
272 
273     return cycles;
274 }
275 
276 /*!
277  * brief Convert provided flags to status code, and clear any errors if present.
278  * param base The LPI2C peripheral base address.
279  * param status Current status flags value that will be checked.
280  * retval #kStatus_Success
281  * retval #kStatus_LPI2C_PinLowTimeout
282  * retval #kStatus_LPI2C_ArbitrationLost
283  * retval #kStatus_LPI2C_Nak
284  * retval #kStatus_LPI2C_FifoError
285  */
LPI2C_MasterCheckAndClearError(LPI2C_Type * base,uint32_t status)286 status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status)
287 {
288     status_t result = kStatus_Success;
289 
290     /* Check for error. These errors cause a stop to automatically be sent. We must */
291     /* clear the errors before a new transfer can start. */
292     status &= (uint32_t)kLPI2C_MasterErrorFlags;
293     if (0U != status)
294     {
295         /* Select the correct error code. Ordered by severity, with bus issues first. */
296         if (0U != (status & (uint32_t)kLPI2C_MasterPinLowTimeoutFlag))
297         {
298             result = kStatus_LPI2C_PinLowTimeout;
299         }
300         else if (0U != (status & (uint32_t)kLPI2C_MasterArbitrationLostFlag))
301         {
302             result = kStatus_LPI2C_ArbitrationLost;
303         }
304         else if (0U != (status & (uint32_t)kLPI2C_MasterNackDetectFlag))
305         {
306             result = kStatus_LPI2C_Nak;
307         }
308         /*
309          * $Branch Coverage Justification$
310          * Before that, the state was stripped of other attributes, and it only contained the four brother flags.(will
311          * improve)
312          */
313         else if (0U != (status & (uint32_t)kLPI2C_MasterFifoErrFlag))
314         {
315             result = kStatus_LPI2C_FifoError;
316         }
317         else
318         {
319             ; /* Intentional empty */
320         }
321 
322         /* Clear the flags. */
323         LPI2C_MasterClearStatusFlags(base, status);
324 
325         if (((base->MCFGR1 & LPI2C_MCFGR1_IGNACK_MASK) != 0x00U) && (result == kStatus_LPI2C_Nak))
326         {
327             /* ERR051119: If IGNACK was set and nak detect , we will ignore the Nak status */
328             result = kStatus_Success;
329         }
330         else
331         {
332             /* Reset fifos. These flags clear automatically.*/
333             base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
334         }
335     }
336     else
337     {
338         ; /* Intentional empty */
339     }
340 
341     return result;
342 }
343 
344 /*!
345  * @brief Wait until there is room in the tx fifo.
346  * @param base The LPI2C peripheral base address.
347  * @retval #kStatus_Success
348  * @retval #kStatus_LPI2C_PinLowTimeout
349  * @retval #kStatus_LPI2C_ArbitrationLost
350  * @retval #kStatus_LPI2C_Nak
351  * @retval #kStatus_LPI2C_FifoError
352  */
LPI2C_MasterWaitForTxReady(LPI2C_Type * base)353 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base)
354 {
355     status_t result = kStatus_Success;
356     uint32_t status;
357     size_t txCount;
358     size_t txFifoSize = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
359 
360 #if I2C_RETRY_TIMES != 0U
361     uint32_t waitTimes = I2C_RETRY_TIMES;
362 #endif
363     do
364     {
365         /* Get the number of words in the tx fifo and compute empty slots. */
366         LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
367         txCount = txFifoSize - txCount;
368 
369         /* Check for error flags. */
370         status = LPI2C_MasterGetStatusFlags(base);
371         result = LPI2C_MasterCheckAndClearError(base, status);
372         if (kStatus_Success != result)
373         {
374             break;
375         }
376 #if I2C_RETRY_TIMES != 0U
377         waitTimes--;
378     } while ((0U == txCount) && (0U != waitTimes));
379 
380     if (0U == waitTimes)
381     {
382         result = kStatus_LPI2C_Timeout;
383     }
384 #else
385     } while (0U == txCount);
386 #endif
387 
388     return result;
389 }
390 
391 /*!
392  * brief Make sure the bus isn't already busy.
393  *
394  * A busy bus is allowed if we are the one driving it.
395  *
396  * param base The LPI2C peripheral base address.
397  * retval #kStatus_Success
398  * retval #kStatus_LPI2C_Busy
399  */
400 /* Not static so it can be used from fsl_lpi2c_edma.c. */
LPI2C_CheckForBusyBus(LPI2C_Type * base)401 status_t LPI2C_CheckForBusyBus(LPI2C_Type *base)
402 {
403     status_t ret = kStatus_Success;
404 
405     uint32_t status = LPI2C_MasterGetStatusFlags(base);
406     /*
407      * $Branch Coverage Justification$
408      * $ref fsl_lpi2c_c_ref_2$
409      */
410     if ((0U != (status & (uint32_t)kLPI2C_MasterBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_MasterBusyFlag)))
411     {
412         ret = kStatus_LPI2C_Busy;
413     }
414 
415     return ret;
416 }
417 
418 /*!
419  * brief Provides a default configuration for the LPI2C master peripheral.
420  *
421  * This function provides the following default configuration for the LPI2C master peripheral:
422  * code
423  *  masterConfig->enableMaster            = true;
424  *  masterConfig->debugEnable             = false;
425  *  masterConfig->ignoreAck               = false;
426  *  masterConfig->pinConfig               = kLPI2C_2PinOpenDrain;
427  *  masterConfig->baudRate_Hz             = 100000U;
428  *  masterConfig->busIdleTimeout_ns       = 0U;
429  *  masterConfig->pinLowTimeout_ns        = 0U;
430  *  masterConfig->sdaGlitchFilterWidth_ns = 0U;
431  *  masterConfig->sclGlitchFilterWidth_ns = 0U;
432  *  masterConfig->hostRequest.enable      = false;
433  *  masterConfig->hostRequest.source      = kLPI2C_HostRequestExternalPin;
434  *  masterConfig->hostRequest.polarity    = kLPI2C_HostRequestPinActiveHigh;
435  * endcode
436  *
437  * After calling this function, you can override any settings in order to customize the configuration,
438  * prior to initializing the master driver with LPI2C_MasterInit().
439  *
440  * param[out] masterConfig User provided configuration structure for default values. Refer to #lpi2c_master_config_t.
441  */
LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t * masterConfig)442 void LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t *masterConfig)
443 {
444     /* Initializes the configure structure to zero. */
445     (void)memset(masterConfig, 0, sizeof(*masterConfig));
446 
447     masterConfig->enableMaster            = true;
448     masterConfig->debugEnable             = false;
449     masterConfig->enableDoze              = true;
450     masterConfig->ignoreAck               = false;
451     masterConfig->pinConfig               = kLPI2C_2PinOpenDrain;
452     masterConfig->baudRate_Hz             = 100000U;
453     masterConfig->busIdleTimeout_ns       = 0U; /* Set to 0 to disable the function */
454     masterConfig->pinLowTimeout_ns        = 0U; /* Set to 0 to disable the function */
455     masterConfig->sdaGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
456     masterConfig->sclGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
457     masterConfig->hostRequest.enable      = false;
458     masterConfig->hostRequest.source      = kLPI2C_HostRequestExternalPin;
459     masterConfig->hostRequest.polarity    = kLPI2C_HostRequestPinActiveHigh;
460 }
461 
462 /*!
463  * brief Initializes the LPI2C master peripheral.
464  *
465  * This function enables the peripheral clock and initializes the LPI2C master peripheral as described by the user
466  * provided configuration. A software reset is performed prior to configuration.
467  *
468  * param base The LPI2C peripheral base address.
469  * param masterConfig User provided peripheral configuration. Use LPI2C_MasterGetDefaultConfig() to get a set of
470  * defaults
471  *      that you can override.
472  * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the baud rate divisors,
473  *      filter widths, and timeout periods.
474  */
LPI2C_MasterInit(LPI2C_Type * base,const lpi2c_master_config_t * masterConfig,uint32_t sourceClock_Hz)475 void LPI2C_MasterInit(LPI2C_Type *base, const lpi2c_master_config_t *masterConfig, uint32_t sourceClock_Hz)
476 {
477     uint32_t prescaler;
478     uint32_t cycles;
479     uint32_t cfgr2;
480     uint32_t value;
481 
482 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
483 
484     uint32_t instance = LPI2C_GetInstance(base);
485 
486     /* Ungate the clock. */
487     (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
488 #if defined(LPI2C_PERIPH_CLOCKS)
489     /* Ungate the functional clock in initialize function. */
490     CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
491 #endif
492 
493 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
494 
495 #if defined(LPI2C_RESETS_ARRAY)
496     RESET_ReleasePeripheralReset(s_lpi2cResets[LPI2C_GetInstance(base)]);
497 #endif
498 
499     /* Reset peripheral before configuring it. */
500     LPI2C_MasterReset(base);
501 
502     /* Doze bit: 0 is enable, 1 is disable */
503     base->MCR = LPI2C_MCR_DBGEN(masterConfig->debugEnable) | LPI2C_MCR_DOZEN(!(masterConfig->enableDoze));
504 
505     /* host request */
506     value = base->MCFGR0;
507     value &= (~(LPI2C_MCFGR0_HREN_MASK | LPI2C_MCFGR0_HRPOL_MASK | LPI2C_MCFGR0_HRSEL_MASK));
508     value |= LPI2C_MCFGR0_HREN(masterConfig->hostRequest.enable) |
509              LPI2C_MCFGR0_HRPOL(masterConfig->hostRequest.polarity) |
510              LPI2C_MCFGR0_HRSEL(masterConfig->hostRequest.source);
511     base->MCFGR0 = value;
512 
513     /* pin config and ignore ack */
514     value = base->MCFGR1;
515     value &= ~(LPI2C_MCFGR1_PINCFG_MASK | LPI2C_MCFGR1_IGNACK_MASK);
516     value |= LPI2C_MCFGR1_PINCFG(masterConfig->pinConfig);
517     value |= LPI2C_MCFGR1_IGNACK(masterConfig->ignoreAck);
518     base->MCFGR1 = value;
519 
520     LPI2C_MasterSetWatermarks(base, (size_t)kDefaultTxWatermark, (size_t)kDefaultRxWatermark);
521 
522     /* Configure glitch filters. */
523     cfgr2 = base->MCFGR2;
524     if (0U != (masterConfig->sdaGlitchFilterWidth_ns))
525     {
526         /* Calculate SDA filter width. The width is equal to FILTSDA cycles of functional clock.
527            And set FILTSDA to 0 disables the fileter, so the min value is 1. */
528         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sdaGlitchFilterWidth_ns, 1U,
529                                          (LPI2C_MCFGR2_FILTSDA_MASK >> LPI2C_MCFGR2_FILTSDA_SHIFT), 0U);
530         cfgr2 &= ~LPI2C_MCFGR2_FILTSDA_MASK;
531         cfgr2 |= LPI2C_MCFGR2_FILTSDA(cycles);
532     }
533     if (0U != masterConfig->sclGlitchFilterWidth_ns)
534     {
535         /* Calculate SDL filter width. The width is equal to FILTSCL cycles of functional clock.
536            And set FILTSCL to 0 disables the fileter, so the min value is 1. */
537         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sclGlitchFilterWidth_ns, 1U,
538                                          (LPI2C_MCFGR2_FILTSCL_MASK >> LPI2C_MCFGR2_FILTSCL_SHIFT), 0U);
539         cfgr2 &= ~LPI2C_MCFGR2_FILTSCL_MASK;
540         cfgr2 |= LPI2C_MCFGR2_FILTSCL(cycles);
541     }
542     base->MCFGR2 = cfgr2;
543 
544     /* Configure baudrate after the SDA/SCL glitch filter setting,
545        since the baudrate calculation needs them as parameter. */
546     LPI2C_MasterSetBaudRate(base, sourceClock_Hz, masterConfig->baudRate_Hz);
547 
548     /* Configure bus idle and pin low timeouts after baudrate setting,
549        since the timeout calculation needs prescaler as parameter. */
550     prescaler = (base->MCFGR1 & LPI2C_MCFGR1_PRESCALE_MASK) >> LPI2C_MCFGR1_PRESCALE_SHIFT;
551 
552     if (0U != (masterConfig->busIdleTimeout_ns))
553     {
554         /* Calculate bus idle timeout value. The value is equal to BUSIDLE cycles of functional clock divided by
555            prescaler. And set BUSIDLE to 0 disables the fileter, so the min value is 1. */
556         cycles       = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->busIdleTimeout_ns, 1U,
557                                                (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
558         base->MCFGR2 = (base->MCFGR2 & (~LPI2C_MCFGR2_BUSIDLE_MASK)) | LPI2C_MCFGR2_BUSIDLE(cycles);
559     }
560     if (0U != masterConfig->pinLowTimeout_ns)
561     {
562         /* Calculate bus pin low timeout value. The value is equal to PINLOW cycles of functional clock divided by
563            prescaler. And set PINLOW to 0 disables the fileter, so the min value is 1. */
564         cycles       = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->pinLowTimeout_ns / 256U, 1U,
565                                                (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
566         base->MCFGR3 = (base->MCFGR3 & ~LPI2C_MCFGR3_PINLOW_MASK) | LPI2C_MCFGR3_PINLOW(cycles);
567     }
568 
569     LPI2C_MasterEnable(base, masterConfig->enableMaster);
570 }
571 
572 /*!
573  * brief Deinitializes the LPI2C master peripheral.
574  *
575  * This function disables the LPI2C master peripheral and gates the clock. It also performs a software
576  * reset to restore the peripheral to reset conditions.
577  *
578  * param base The LPI2C peripheral base address.
579  */
LPI2C_MasterDeinit(LPI2C_Type * base)580 void LPI2C_MasterDeinit(LPI2C_Type *base)
581 {
582     /* Restore to reset state. */
583     LPI2C_MasterReset(base);
584 
585 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
586 
587     uint32_t instance = LPI2C_GetInstance(base);
588 
589     /* Gate clock. */
590     (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
591 #if defined(LPI2C_PERIPH_CLOCKS)
592     /* Gate the functional clock. */
593     CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
594 #endif
595 
596 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
597 }
598 
599 /*!
600  * brief Configures LPI2C master data match feature.
601  *
602  * param base The LPI2C peripheral base address.
603  * param matchConfig Settings for the data match feature.
604  */
LPI2C_MasterConfigureDataMatch(LPI2C_Type * base,const lpi2c_data_match_config_t * matchConfig)605 void LPI2C_MasterConfigureDataMatch(LPI2C_Type *base, const lpi2c_data_match_config_t *matchConfig)
606 {
607     /* Disable master mode. */
608     bool wasEnabled = (0U != ((base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT));
609     LPI2C_MasterEnable(base, false);
610 
611     base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_MATCFG_MASK) | LPI2C_MCFGR1_MATCFG(matchConfig->matchMode);
612     base->MCFGR0 = (base->MCFGR0 & ~LPI2C_MCFGR0_RDMO_MASK) | LPI2C_MCFGR0_RDMO(matchConfig->rxDataMatchOnly);
613     base->MDMR   = LPI2C_MDMR_MATCH0(matchConfig->match0) | LPI2C_MDMR_MATCH1(matchConfig->match1);
614 
615     /* Restore master mode. */
616     if (wasEnabled)
617     {
618         LPI2C_MasterEnable(base, true);
619     }
620 }
621 
622 /*!
623  * brief Sets the I2C bus frequency for master transactions.
624  *
625  * The LPI2C master is automatically disabled and re-enabled as necessary to configure the baud
626  * rate. Do not call this function during a transfer, or the transfer is aborted.
627  *
628  * note Please note that the second parameter is the clock frequency of LPI2C module, the third
629  * parameter means user configured bus baudrate, this implementation is different from other I2C drivers
630  * which use baudrate configuration as second parameter and source clock frequency as third parameter.
631  *
632  * param base The LPI2C peripheral base address.
633  * param sourceClock_Hz LPI2C functional clock frequency in Hertz.
634  * param baudRate_Hz Requested bus frequency in Hertz.
635  */
LPI2C_MasterSetBaudRate(LPI2C_Type * base,uint32_t sourceClock_Hz,uint32_t baudRate_Hz)636 void LPI2C_MasterSetBaudRate(LPI2C_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Hz)
637 {
638     bool wasEnabled;
639     uint8_t filtScl = (uint8_t)((base->MCFGR2 & LPI2C_MCFGR2_FILTSCL_MASK) >> LPI2C_MCFGR2_FILTSCL_SHIFT);
640 
641     uint8_t divider     = 1U;
642     uint8_t bestDivider = 1U;
643     uint8_t prescale    = 0U;
644     uint8_t bestPre     = 0U;
645 
646     uint8_t clkCycle;
647     uint8_t bestclkCycle = 0U;
648 
649     uint32_t absError  = 0U;
650     uint32_t bestError = 0xffffffffu;
651     uint32_t computedRate;
652 
653     uint32_t tmpReg = 0U;
654 
655     /* Disable master mode. */
656     wasEnabled = (0U != ((base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT));
657     LPI2C_MasterEnable(base, false);
658 
659     /* Baud rate = (sourceClock_Hz / 2 ^ prescale) / (CLKLO + 1 + CLKHI + 1 + SCL_LATENCY)
660      * SCL_LATENCY = ROUNDDOWN((2 + FILTSCL) / (2 ^ prescale))
661      */
662     for (prescale = 0U; prescale <= 7U; prescale++)
663     {
664         /* Calculate the clkCycle, clkCycle = CLKLO + CLKHI, divider = 2 ^ prescale */
665         clkCycle = (uint8_t)((10U * sourceClock_Hz / divider / baudRate_Hz + 5U) / 10U - (2U + filtScl) / divider - 2U);
666         /* According to register description, The max value for CLKLO and CLKHI is 63.
667            however to meet the I2C specification of tBUF, CLKHI should be less than
668            clkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / divider + 1U. Refer to the comment of the tmpHigh's
669            calculation for details. So we have:
670            CLKHI < clkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / divider + 1U,
671            clkCycle = CLKHI + CLKLO and
672            sourceClock_Hz / baudRate_Hz / divider = clkCycle + 2 + ROUNDDOWN((2 + FILTSCL) / divider),
673            we can come up with: CLKHI < 0.92 x CLKLO - ROUNDDOWN(2 + FILTSCL) / divider
674            so the max boundary of CLKHI should be 0.92 x 63 - ROUNDDOWN(2 + FILTSCL) / divider,
675            and the max boundary of clkCycle is 1.92 x 63 - ROUNDDOWN(2 + FILTSCL) / divider. */
676         if (clkCycle > (120U - (2U + filtScl) / divider))
677         {
678             divider *= 2U;
679             continue;
680         }
681         /* Calculate the computed baudrate and compare it with the desired baudrate */
682         computedRate = (sourceClock_Hz / (uint32_t)divider) /
683                        ((uint32_t)clkCycle + 2U + (2U + (uint32_t)filtScl) / (uint32_t)divider);
684         absError = baudRate_Hz > computedRate ? baudRate_Hz - computedRate : computedRate - baudRate_Hz;
685         if (absError < bestError)
686         {
687             bestPre      = prescale;
688             bestDivider  = divider;
689             bestclkCycle = clkCycle;
690             bestError    = absError;
691 
692             /* If the error is 0, then we can stop searching because we won't find a better match. */
693             if (absError == 0U)
694             {
695                 break;
696             }
697         }
698         divider *= 2U;
699     }
700 
701     /* SCL low time tLO should be larger than or equal to SCL high time tHI:
702        tLO = ((CLKLO + 1) x (2 ^ PRESCALE)) >= tHI = ((CLKHI + 1 + SCL_LATENCY) x (2 ^ PRESCALE)),
703        which is CLKLO >= CLKHI + (2U + filtScl) / bestDivider.
704        Also since bestclkCycle = CLKLO + CLKHI, bestDivider = 2 ^ PRESCALE
705        which makes CLKHI <= (bestclkCycle - (2U + filtScl) / bestDivider) / 2U.
706 
707        The max tBUF should be at least 0.52 times of the SCL clock cycle:
708        tBUF = ((CLKLO + 1) x (2 ^ PRESCALE) / sourceClock_Hz) > (0.52 / baudRate_Hz),
709        plus bestDivider = 2 ^ PRESCALE, bestclkCycle = CLKLO + CLKHI we can come up with
710        CLKHI <= (bestclkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / bestDivider + 1U).
711        In this case to get a safe CLKHI calculation, we can assume:
712     */
713     uint8_t tmpHigh = (bestclkCycle - (2U + filtScl) / bestDivider) / 2U;
714     while (tmpHigh > (bestclkCycle - 52U * sourceClock_Hz / baudRate_Hz / bestDivider / 100U + 1U))
715     {
716         tmpHigh = tmpHigh - 1U;
717     }
718 
719     /* Calculate DATAVD and SETHOLD.
720        To meet the timing requirement of I2C spec for standard mode, fast mode and fast mode plus: */
721     /* The min tHD:STA/tSU:STA/tSU:STO should be at least 0.4 times of the SCL clock cycle, use 0.5 to be safe:
722        tHD:STA = ((SETHOLD + 1) x (2 ^ PRESCALE) / sourceClock_Hz) > (0.5 / baudRate_Hz), bestDivider = 2 ^ PRESCALE */
723     uint8_t tmpHold = (uint8_t)(sourceClock_Hz / baudRate_Hz / bestDivider / 2U) - 1U;
724 
725     /* The max tVD:DAT/tVD:ACK/tHD:DAT should be at most 0.345 times of the SCL clock cycle, use 0.25 to be safe:
726        tVD:DAT = ((DATAVD + 1) x (2 ^ PRESCALE) / sourceClock_Hz) < (0.25 / baudRate_Hz), bestDivider = 2 ^ PRESCALE */
727     uint8_t tmpDataVd = (uint8_t)(sourceClock_Hz / baudRate_Hz / bestDivider / 4U) - 1U;
728 
729     /* The min tSU:DAT should be at least 0.05 times of the SCL clock cycle:
730        tSU:DAT = ((2 + FILTSDA + 2 ^ PRESCALE) / sourceClock_Hz) >= (0.05 / baud),
731        plus bestDivider = 2 ^ PRESCALE, we can come up with:
732        FILTSDA >= (0.05 x sourceClock_Hz / baudRate_Hz - bestDivider - 2) */
733     if ((sourceClock_Hz / baudRate_Hz / 20U) > (bestDivider + 2U))
734     {
735         /* Read out the FILTSDA configuration, if it is smaller than expected, change the setting. */
736         uint8_t filtSda = (uint8_t)((base->MCFGR2 & LPI2C_MCFGR2_FILTSDA_MASK) >> LPI2C_MCFGR2_FILTSDA_SHIFT);
737         if (filtSda < (sourceClock_Hz / baudRate_Hz / 20U - bestDivider - 2U))
738         {
739             filtSda = (uint8_t)(sourceClock_Hz / baudRate_Hz / 20U) - bestDivider - 2U;
740         }
741         base->MCFGR2 = (base->MCFGR2 & ~LPI2C_MCFGR2_FILTSDA_MASK) | LPI2C_MCFGR2_FILTSDA(filtSda);
742     }
743 
744     /* Set CLKHI, CLKLO, SETHOLD, DATAVD value. */
745     tmpReg = LPI2C_MCCR0_CLKHI((uint32_t)tmpHigh) |
746              LPI2C_MCCR0_CLKLO((uint32_t)((uint32_t)bestclkCycle - (uint32_t)tmpHigh)) |
747              LPI2C_MCCR0_SETHOLD((uint32_t)tmpHold) | LPI2C_MCCR0_DATAVD((uint32_t)tmpDataVd);
748     base->MCCR0 = tmpReg;
749 
750     /* Set PRESCALE value. */
751     base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_PRESCALE_MASK) | LPI2C_MCFGR1_PRESCALE(bestPre);
752 
753     /* Restore master mode. */
754     if (wasEnabled)
755     {
756         LPI2C_MasterEnable(base, true);
757     }
758 }
759 
760 /*!
761  * brief Sends a START signal and slave address on the I2C bus.
762  *
763  * This function is used to initiate a new master mode transfer. First, the bus state is checked to ensure
764  * that another master is not occupying the bus. Then a START signal is transmitted, followed by the
765  * 7-bit address specified in the a address parameter. Note that this function does not actually wait
766  * until the START and address are successfully sent on the bus before returning.
767  *
768  * param base The LPI2C peripheral base address.
769  * param address 7-bit slave device address, in bits [6:0].
770  * param dir Master transfer direction, either #kLPI2C_Read or #kLPI2C_Write. This parameter is used to set
771  *      the R/w bit (bit 0) in the transmitted slave address.
772  * retval #kStatus_Success START signal and address were successfully enqueued in the transmit FIFO.
773  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
774  */
LPI2C_MasterStart(LPI2C_Type * base,uint8_t address,lpi2c_direction_t dir)775 status_t LPI2C_MasterStart(LPI2C_Type *base, uint8_t address, lpi2c_direction_t dir)
776 {
777     /* Return an error if the bus is already in use not by us. */
778     status_t result = LPI2C_CheckForBusyBus(base);
779     /*
780      * $Branch Coverage Justification$
781      * $ref fsl_lpi2c_c_ref_2$
782      */
783     if (kStatus_Success == result)
784     {
785         /* Clear all flags. */
786         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
787 
788         /* Turn off auto-stop option. */
789         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
790 
791         /* Wait until there is room in the fifo. */
792         result = LPI2C_MasterWaitForTxReady(base);
793         if (kStatus_Success == result)
794         {
795             /* Issue start command. */
796             base->MTDR = (uint32_t)kStartCmd | (((uint32_t)address << 1U) | (uint32_t)dir);
797         }
798     }
799 
800     return result;
801 }
802 
803 /*!
804  * brief Sends a STOP signal on the I2C bus.
805  *
806  * This function does not return until the STOP signal is seen on the bus, or an error occurs.
807  *
808  * param base The LPI2C peripheral base address.
809  * retval #kStatus_Success The STOP signal was successfully sent on the bus and the transaction terminated.
810  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
811  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
812  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
813  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
814  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
815  */
LPI2C_MasterStop(LPI2C_Type * base)816 status_t LPI2C_MasterStop(LPI2C_Type *base)
817 {
818     /* Wait until there is room in the fifo. */
819     status_t result = LPI2C_MasterWaitForTxReady(base);
820     if (kStatus_Success == result)
821     {
822         /* Send the STOP signal */
823         base->MTDR = (uint32_t)kStopCmd;
824 
825         /* Wait for the stop detected flag to set, indicating the transfer has completed on the bus. */
826         /* Also check for errors while waiting. */
827 #if I2C_RETRY_TIMES != 0U
828         uint32_t waitTimes = I2C_RETRY_TIMES;
829 #endif
830 
831 #if I2C_RETRY_TIMES != 0U
832         while ((result == kStatus_Success) && (0U != waitTimes))
833         {
834             waitTimes--;
835 #else
836         while (result == kStatus_Success)
837         {
838 #endif
839             uint32_t status = LPI2C_MasterGetStatusFlags(base);
840 
841             /* Check for error flags. */
842             result = LPI2C_MasterCheckAndClearError(base, status);
843 
844             /* Check if the stop was sent successfully. */
845             if ((0U != (status & (uint32_t)kLPI2C_MasterStopDetectFlag)) &&
846                 (0U != (status & (uint32_t)kLPI2C_MasterTxReadyFlag)))
847             {
848                 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterStopDetectFlag);
849                 break;
850             }
851         }
852 
853 #if I2C_RETRY_TIMES != 0U
854         if (0U == waitTimes)
855         {
856             result = kStatus_LPI2C_Timeout;
857         }
858 #endif
859     }
860 
861     return result;
862 }
863 
864 /*!
865  * brief Performs a polling receive transfer on the I2C bus.
866  *
867  * param base  The LPI2C peripheral base address.
868  * param rxBuff The pointer to the data to be transferred.
869  * param rxSize The length in bytes of the data to be transferred.
870  * retval #kStatus_Success Data was received successfully.
871  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
872  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
873  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
874  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
875  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
876  */
877 status_t LPI2C_MasterReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize)
878 {
879     assert(NULL != rxBuff);
880 
881     status_t result = kStatus_Success;
882     uint8_t *buf;
883     size_t tmpRxSize = rxSize;
884 #if I2C_RETRY_TIMES != 0U
885     uint32_t waitTimes;
886 #endif
887 
888     /* Check transfer data size. */
889     if (rxSize > ((size_t)256 * (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base)))
890     {
891         return kStatus_InvalidArgument;
892     }
893 
894     /* Handle empty read. */
895     if (rxSize != 0U)
896     {
897         /* Wait until there is room in the command fifo. */
898         result = LPI2C_MasterWaitForTxReady(base);
899         if (kStatus_Success == result)
900         {
901             /* Issue command to receive data. A single write to MTDR can issue read operation of 0xFFU + 1 byte of data
902                at most, so when the rxSize is larger than 0x100U, push multiple read commands to MTDR until rxSize is
903                reached. */
904             while (tmpRxSize != 0U)
905             {
906                 if (tmpRxSize > 256U)
907                 {
908                     base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
909                     tmpRxSize -= 256U;
910                 }
911                 else
912                 {
913                     base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
914                     tmpRxSize  = 0U;
915                 }
916             }
917 
918             /* Receive data */
919             buf = (uint8_t *)rxBuff;
920             while (0U != (rxSize--))
921             {
922 #if I2C_RETRY_TIMES != 0U
923                 waitTimes = I2C_RETRY_TIMES;
924 #endif
925                 /* Read LPI2C receive fifo register. The register includes a flag to indicate whether */
926                 /* the FIFO is empty, so we can both get the data and check if we need to keep reading */
927                 /* using a single register read. */
928                 uint32_t value = 0U;
929                 do
930                 {
931                     /* Check for errors. */
932                     result = LPI2C_MasterCheckAndClearError(base, LPI2C_MasterGetStatusFlags(base));
933                     if (kStatus_Success != result)
934                     {
935                         break;
936                     }
937 
938                     value = base->MRDR;
939 #if I2C_RETRY_TIMES != 0U
940                     waitTimes--;
941                 } while ((0U != (value & LPI2C_MRDR_RXEMPTY_MASK)) && (0U != waitTimes));
942                 if (0U == waitTimes)
943                 {
944                     result = kStatus_LPI2C_Timeout;
945                 }
946 #else
947                 } while (0U != (value & LPI2C_MRDR_RXEMPTY_MASK));
948 #endif
949                 if ((status_t)kStatus_Success != result)
950                 {
951                     break;
952                 }
953 
954                 *buf++ = (uint8_t)(value & LPI2C_MRDR_DATA_MASK);
955             }
956         }
957     }
958 
959     return result;
960 }
961 
962 /*!
963  * brief Performs a polling send transfer on the I2C bus.
964  *
965  * Sends up to a txSize number of bytes to the previously addressed slave device. The slave may
966  * reply with a NAK to any byte in order to terminate the transfer early. If this happens, this
967  * function returns #kStatus_LPI2C_Nak.
968  *
969  * param base  The LPI2C peripheral base address.
970  * param txBuff The pointer to the data to be transferred.
971  * param txSize The length in bytes of the data to be transferred.
972  * retval #kStatus_Success Data was sent successfully.
973  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
974  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
975  * retval #kStatus_LPI2C_FifoError FIFO under run or over run.
976  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
977  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
978  */
LPI2C_MasterSend(LPI2C_Type * base,void * txBuff,size_t txSize)979 status_t LPI2C_MasterSend(LPI2C_Type *base, void *txBuff, size_t txSize)
980 {
981     status_t result = kStatus_Success;
982     uint8_t *buf    = (uint8_t *)txBuff;
983 
984     assert(NULL != txBuff);
985 
986     /* Send data buffer */
987     while (0U != (txSize--))
988     {
989         /* Wait until there is room in the fifo. This also checks for errors. */
990         result = LPI2C_MasterWaitForTxReady(base);
991         if (kStatus_Success != result)
992         {
993             break;
994         }
995 
996         /* Write byte into LPI2C master data register. */
997         base->MTDR = *buf++;
998     }
999 
1000     return result;
1001 }
1002 
1003 /*!
1004  * brief Performs a master polling transfer on the I2C bus.
1005  *
1006  * note The API does not return until the transfer succeeds or fails due
1007  * to error happens during transfer.
1008  *
1009  * param base The LPI2C peripheral base address.
1010  * param transfer Pointer to the transfer structure.
1011  * retval #kStatus_Success Data was received successfully.
1012  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
1013  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
1014  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
1015  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
1016  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1017  */
LPI2C_MasterTransferBlocking(LPI2C_Type * base,lpi2c_master_transfer_t * transfer)1018 status_t LPI2C_MasterTransferBlocking(LPI2C_Type *base, lpi2c_master_transfer_t *transfer)
1019 {
1020     assert(NULL != transfer);
1021     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1022 
1023     status_t result = kStatus_Success;
1024     status_t ret    = kStatus_Success;
1025     uint16_t commandBuffer[7];
1026     uint32_t cmdCount = 0U;
1027 
1028     /* Check transfer data size in read operation. */
1029     if ((transfer->direction == kLPI2C_Read) &&
1030         (transfer->dataSize > ((size_t)256 * (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1031     {
1032         return kStatus_InvalidArgument;
1033     }
1034 
1035     /* Enable the master function and disable the slave function. */
1036     LPI2C_MasterEnable(base, true);
1037     LPI2C_SlaveEnable(base, false);
1038 
1039     /* Return an error if the bus is already in use not by us. */
1040     result = LPI2C_CheckForBusyBus(base);
1041     /*
1042      * $Branch Coverage Justification$
1043      * $ref fsl_lpi2c_c_ref_2$
1044      */
1045     if (kStatus_Success == result)
1046     {
1047         /* Clear all flags. */
1048         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1049 
1050         /* Turn off auto-stop option. */
1051         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1052 
1053         lpi2c_direction_t direction = (0U != transfer->subaddressSize) ? kLPI2C_Write : transfer->direction;
1054         if (0U == (transfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1055         {
1056             commandBuffer[cmdCount++] =
1057                 (uint16_t)kStartCmd |
1058                 (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)direction);
1059         }
1060 
1061         /* Subaddress, MSB first. */
1062         if (0U != transfer->subaddressSize)
1063         {
1064             uint32_t subaddressRemaining = transfer->subaddressSize;
1065             while (0U != subaddressRemaining--)
1066             {
1067                 uint8_t subaddressByte    = (uint8_t)((transfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1068                 commandBuffer[cmdCount++] = subaddressByte;
1069             }
1070         }
1071 
1072         /* Reads need special handling. */
1073         if ((0U != transfer->dataSize) && (transfer->direction == kLPI2C_Read))
1074         {
1075             /* Need to send repeated start if switching directions to read. */
1076             if (direction == kLPI2C_Write)
1077             {
1078                 commandBuffer[cmdCount++] =
1079                     (uint16_t)kStartCmd |
1080                     (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1081             }
1082         }
1083 
1084         /* Send command buffer */
1085         uint32_t index = 0U;
1086         while (0U != cmdCount--)
1087         {
1088             /* Wait until there is room in the fifo. This also checks for errors. */
1089             result = LPI2C_MasterWaitForTxReady(base);
1090             if (kStatus_Success != result)
1091             {
1092                 break;
1093             }
1094 
1095             /* Write byte into LPI2C master data register. */
1096             base->MTDR = commandBuffer[index];
1097             index++;
1098         }
1099 
1100         if (kStatus_Success == result)
1101         {
1102             /* Transmit data. */
1103             if ((transfer->direction == kLPI2C_Write) && (transfer->dataSize > 0U))
1104             {
1105                 /* Send Data. */
1106                 result = LPI2C_MasterSend(base, transfer->data, transfer->dataSize);
1107             }
1108 
1109             /* Receive Data. */
1110             if ((transfer->direction == kLPI2C_Read) && (transfer->dataSize > 0U))
1111             {
1112                 result = LPI2C_MasterReceive(base, transfer->data, transfer->dataSize);
1113             }
1114             /*
1115              * $Branch Coverage Justification$
1116              * Errors cannot be simulated by software during transmission.(will improve)
1117              */
1118             if (kStatus_Success == result)
1119             {
1120                 if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1121                 {
1122                     result = LPI2C_MasterStop(base);
1123                 }
1124             }
1125         }
1126 
1127         /* Transmit fail */
1128         if (kStatus_Success != result)
1129         {
1130             if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1131             {
1132                 ret = LPI2C_MasterStop(base);
1133                 if (kStatus_Success != ret)
1134                 {
1135                     result = ret;
1136                 }
1137             }
1138         }
1139     }
1140 
1141     return result;
1142 }
1143 
1144 /*!
1145  * brief Creates a new handle for the LPI2C master non-blocking APIs.
1146  *
1147  * The creation of a handle is for use with the non-blocking APIs. Once a handle
1148  * is created, there is not a corresponding destroy handle. If the user wants to
1149  * terminate a transfer, the LPI2C_MasterTransferAbort() API shall be called.
1150  *
1151  *
1152  * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
1153  * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
1154  * enable the associated INTMUX IRQ in application.
1155  *
1156  * param base The LPI2C peripheral base address.
1157  * param[out] handle Pointer to the LPI2C master driver handle.
1158  * param callback User provided pointer to the asynchronous callback function.
1159  * param userData User provided pointer to the application callback data.
1160  */
LPI2C_MasterTransferCreateHandle(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_callback_t callback,void * userData)1161 void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
1162                                       lpi2c_master_handle_t *handle,
1163                                       lpi2c_master_transfer_callback_t callback,
1164                                       void *userData)
1165 {
1166     uint32_t instance;
1167 
1168     assert(NULL != handle);
1169 
1170     /* Clear out the handle. */
1171     (void)memset(handle, 0, sizeof(*handle));
1172 
1173     /* Look up instance number */
1174     instance = LPI2C_GetInstance(base);
1175 
1176     /* Save base and instance. */
1177     handle->completionCallback = callback;
1178     handle->userData           = userData;
1179 
1180     /* Save this handle for IRQ use. */
1181     s_lpi2cMasterHandle[instance] = handle;
1182 
1183     /* Set irq handler. */
1184     s_lpi2cMasterIsr = LPI2C_MasterTransferHandleIRQ;
1185 
1186     /* Clear internal IRQ enables and enable NVIC IRQ. */
1187     LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1188 
1189     /* Enable NVIC IRQ, this only enables the IRQ directly connected to the NVIC.
1190      In some cases the LPI2C IRQ is configured through INTMUX, user needs to enable
1191      INTMUX IRQ in application code. */
1192     (void)EnableIRQ(kLpi2cIrqs[instance]);
1193 }
1194 
LPI2C_TransferStateMachineSendCommand(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1195 static void LPI2C_TransferStateMachineSendCommand(LPI2C_Type *base,
1196                                                   lpi2c_master_handle_t *handle,
1197                                                   lpi2c_state_machine_param_t *stateParams)
1198 {
1199     assert(stateParams != NULL);
1200     uint16_t sendval;
1201 
1202     /* Make sure there is room in the tx fifo for the next command. */
1203     if (0U == (stateParams->txCount)--)
1204     {
1205         stateParams->state_complete = true;
1206         return;
1207     }
1208 
1209     /* Issue command. buf is a uint8_t* pointing at the uint16 command array. */
1210     sendval    = ((uint16_t)handle->buf[0]) | (((uint16_t)handle->buf[1]) << 8U);
1211     base->MTDR = sendval;
1212     handle->buf++;
1213     handle->buf++;
1214 
1215     /* Count down until all commands are sent. */
1216     if (--handle->remainingBytes == 0U)
1217     {
1218         /* Choose next state and set up buffer pointer and count. */
1219         if (0U != handle->transfer.dataSize)
1220         {
1221             /* Either a send or receive transfer is next. */
1222             handle->state          = (uint8_t)kTransferDataState;
1223             handle->buf            = (uint8_t *)handle->transfer.data;
1224             handle->remainingBytes = (uint16_t)handle->transfer.dataSize;
1225             if (handle->transfer.direction == kLPI2C_Read)
1226             {
1227                 /* Disable TX interrupt */
1228                 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1229                 /* Issue command to receive data. A single write to MTDR can issue read operation of
1230                     0xFFU + 1 byte of data at most, so when the dataSize is larger than 0x100U, push
1231                     multiple read commands to MTDR until dataSize is reached. */
1232                 size_t tmpRxSize = handle->transfer.dataSize;
1233                 while (tmpRxSize != 0U)
1234                 {
1235                     LPI2C_MasterGetFifoCounts(base, NULL, &stateParams->txCount);
1236                     /*
1237                      * $Branch Coverage Justification$
1238                      * The transmission commands will not exceed FIFO SIZE.(will improve)
1239                      */
1240                     while ((size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base) == stateParams->txCount)
1241                     {
1242                         LPI2C_MasterGetFifoCounts(base, NULL, &stateParams->txCount);
1243                     }
1244 
1245                     if (tmpRxSize > 256U)
1246                     {
1247                         base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
1248                         tmpRxSize -= 256U;
1249                     }
1250                     else
1251                     {
1252                         base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
1253                         tmpRxSize  = 0U;
1254                     }
1255                 }
1256             }
1257         }
1258         else
1259         {
1260             /* No transfer, so move to stop state. */
1261             handle->state = (uint8_t)kStopState;
1262         }
1263     }
1264 }
1265 
LPI2C_TransferStateMachineReadCommand(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1266 static void LPI2C_TransferStateMachineReadCommand(LPI2C_Type *base,
1267                                                   lpi2c_master_handle_t *handle,
1268                                                   lpi2c_state_machine_param_t *stateParams)
1269 {
1270     assert(stateParams != NULL);
1271 
1272     /* Make sure there is room in the tx fifo for the read command. */
1273     if (0U == (stateParams->txCount)--)
1274     {
1275         stateParams->state_complete = true;
1276         return;
1277     }
1278 
1279     base->MTDR = (uint32_t)kRxDataCmd | LPI2C_MTDR_DATA(handle->transfer.dataSize - 1U);
1280 
1281     /* Move to transfer state. */
1282     handle->state = (uint8_t)kTransferDataState;
1283     if (handle->transfer.direction == kLPI2C_Read)
1284     {
1285         /* Disable TX interrupt */
1286         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1287     }
1288 }
1289 
LPI2C_TransferStateMachineTransferData(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1290 static void LPI2C_TransferStateMachineTransferData(LPI2C_Type *base,
1291                                                    lpi2c_master_handle_t *handle,
1292                                                    lpi2c_state_machine_param_t *stateParams)
1293 {
1294     assert(stateParams != NULL);
1295 
1296     if (handle->transfer.direction == kLPI2C_Write)
1297     {
1298         /* Make sure there is room in the tx fifo. */
1299         if (0U == stateParams->txCount--)
1300         {
1301             stateParams->state_complete = true;
1302             return;
1303         }
1304 
1305         /* Put byte to send in fifo. */
1306         base->MTDR = *(handle->buf)++;
1307     }
1308     else
1309     {
1310         /* XXX handle receive sizes > 256, use kIssueReadCommandState */
1311         /* Make sure there is data in the rx fifo. */
1312         if (0U == stateParams->rxCount--)
1313         {
1314             stateParams->state_complete = true;
1315             return;
1316         }
1317 
1318         /* Read byte from fifo. */
1319         *(handle->buf)++ = (uint8_t)(base->MRDR & LPI2C_MRDR_DATA_MASK);
1320     }
1321 
1322     /* Move to stop when the transfer is done. */
1323     if (--handle->remainingBytes == 0U)
1324     {
1325         if (handle->transfer.direction == kLPI2C_Write)
1326         {
1327             stateParams->state_complete = true;
1328         }
1329         handle->state = (uint8_t)kStopState;
1330     }
1331 }
1332 
LPI2C_TransferStateMachineStopState(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams,bool * isDone)1333 static void LPI2C_TransferStateMachineStopState(LPI2C_Type *base,
1334                                                 lpi2c_master_handle_t *handle,
1335                                                 lpi2c_state_machine_param_t *stateParams,
1336                                                 bool *isDone)
1337 {
1338     assert(stateParams != NULL);
1339 
1340     /* Only issue a stop transition if the caller requested it. */
1341     if ((handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1342     {
1343         /* Make sure there is room in the tx fifo for the stop command. */
1344         if (0U == (stateParams->txCount)--)
1345         {
1346             stateParams->state_complete = true;
1347             return;
1348         }
1349 
1350         base->MTDR = (uint32_t)kStopCmd;
1351     }
1352     else
1353     {
1354         /* If all data is read and no stop flag is required to send, we are done. */
1355         if (handle->transfer.direction == kLPI2C_Read)
1356         {
1357             *isDone = true;
1358         }
1359         stateParams->state_complete = true;
1360     }
1361     handle->state = (uint8_t)kWaitForCompletionState;
1362 }
1363 
LPI2C_TransferStateMachineWaitState(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams,bool * isDone)1364 static void LPI2C_TransferStateMachineWaitState(LPI2C_Type *base,
1365                                                 lpi2c_master_handle_t *handle,
1366                                                 lpi2c_state_machine_param_t *stateParams,
1367                                                 bool *isDone)
1368 {
1369     assert(stateParams != NULL);
1370 
1371     if ((handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1372     {
1373         /* We stay in this state until the stop state is detected. */
1374         if (0U != ((stateParams->status) & (uint32_t)kLPI2C_MasterStopDetectFlag))
1375         {
1376             *isDone = true;
1377         }
1378     }
1379     else
1380     {
1381         /* If all data is pushed to FIFO and no stop flag is required to send, we need to make sure they
1382             are all send out to bus. */
1383         if ((handle->transfer.direction == kLPI2C_Write) && ((base->MFSR & LPI2C_MFSR_TXCOUNT_MASK) == 0U))
1384         {
1385             /* We stay in this state until the data is sent out to bus. */
1386             *isDone = true;
1387         }
1388     }
1389     stateParams->state_complete = true;
1390 }
1391 
1392 /*!
1393  * @brief Execute states until FIFOs are exhausted.
1394  * @param handle Master nonblocking driver handle.
1395  * @param[out] isDone Set to true if the transfer has completed.
1396  * @retval #kStatus_Success
1397  * @retval #kStatus_LPI2C_PinLowTimeout
1398  * @retval #kStatus_LPI2C_ArbitrationLost
1399  * @retval #kStatus_LPI2C_Nak
1400  * @retval #kStatus_LPI2C_FifoError
1401  */
LPI2C_RunTransferStateMachine(LPI2C_Type * base,lpi2c_master_handle_t * handle,bool * isDone)1402 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone)
1403 {
1404     assert(NULL != base && NULL != handle && NULL != isDone);
1405 
1406     status_t result = kStatus_Success;
1407     lpi2c_state_machine_param_t stateParams;
1408     (void)memset(&stateParams, 0, sizeof(stateParams));
1409 
1410     stateParams.state_complete = false;
1411 
1412     /* Set default isDone return value. */
1413     *isDone = false;
1414 
1415     /* Check for errors. */
1416     stateParams.status = LPI2C_MasterGetStatusFlags(base);
1417 
1418     /* Get fifo counts. */
1419     LPI2C_MasterGetFifoCounts(base, &stateParams.rxCount, &stateParams.txCount);
1420 
1421     /* For the last byte, nack flag is expected.
1422        Do not check and clear kLPI2C_MasterNackDetectFlag for the last byte,
1423        in case FIFO is emptied when stop command has not been sent. */
1424     if (handle->remainingBytes == 0U)
1425     {
1426         /* When data size is not zero which means it is not only one byte of address is sent, and */
1427         /* when the txfifo is empty, or have one byte which is the stop command, then the nack status can be ignored. */
1428         if (((handle->transfer).dataSize != 0U) &&
1429             ((stateParams.txCount == 0U) ||
1430              (((stateParams.txCount) == 1U) && (handle->state == (uint8_t)kWaitForCompletionState) &&
1431               (((handle->transfer).flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U))))
1432         {
1433             (stateParams.status) &= ~(uint32_t)kLPI2C_MasterNackDetectFlag;
1434         }
1435     }
1436 
1437     result = LPI2C_MasterCheckAndClearError(base, stateParams.status);
1438 
1439     if (kStatus_Success == result)
1440     {
1441         /* Compute room in tx fifo */
1442         stateParams.txCount = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base) - stateParams.txCount;
1443 
1444         while (!stateParams.state_complete)
1445         {
1446             /* Execute the state. */
1447             /*
1448              * $Branch Coverage Justification$
1449              * $ref fsl_lpi2c_c_ref_1$
1450              */
1451             switch (handle->state)
1452             {
1453                 case (uint8_t)kSendCommandState:
1454                     LPI2C_TransferStateMachineSendCommand(base, handle, &stateParams);
1455                     break;
1456 
1457                 case (uint8_t)kIssueReadCommandState:
1458                     LPI2C_TransferStateMachineReadCommand(base, handle, &stateParams);
1459                     break;
1460 
1461                 case (uint8_t)kTransferDataState:
1462                     LPI2C_TransferStateMachineTransferData(base, handle, &stateParams);
1463                     break;
1464 
1465                 case (uint8_t)kStopState:
1466                     LPI2C_TransferStateMachineStopState(base, handle, &stateParams, isDone);
1467                     break;
1468 
1469                 case (uint8_t)kWaitForCompletionState:
1470                     LPI2C_TransferStateMachineWaitState(base, handle, &stateParams, isDone);
1471                     break;
1472                 default:
1473                     assert(false);
1474                     break;
1475             }
1476         }
1477     }
1478     return result;
1479 }
1480 
1481 /*!
1482  * @brief Prepares the transfer state machine and fills in the command buffer.
1483  * @param handle Master nonblocking driver handle.
1484  */
LPI2C_InitTransferStateMachine(lpi2c_master_handle_t * handle)1485 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle)
1486 {
1487     lpi2c_master_transfer_t *xfer = &handle->transfer;
1488 
1489     /* Handle no start option. */
1490     if (0U != (xfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1491     {
1492         if (xfer->direction == kLPI2C_Read)
1493         {
1494             /* Need to issue read command first. */
1495             handle->state = (uint8_t)kIssueReadCommandState;
1496         }
1497         else
1498         {
1499             /* Start immediately in the data transfer state. */
1500             handle->state = (uint8_t)kTransferDataState;
1501         }
1502 
1503         handle->buf            = (uint8_t *)xfer->data;
1504         handle->remainingBytes = (uint16_t)xfer->dataSize;
1505     }
1506     else
1507     {
1508         uint16_t *cmd     = (uint16_t *)&handle->commandBuffer;
1509         uint32_t cmdCount = 0U;
1510 
1511         /* Initial direction depends on whether a subaddress was provided, and of course the actual */
1512         /* data transfer direction. */
1513         lpi2c_direction_t direction = (0U != xfer->subaddressSize) ? kLPI2C_Write : xfer->direction;
1514 
1515         /* Start command. */
1516         cmd[cmdCount++] =
1517             (uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
1518 
1519         /* Subaddress, MSB first. */
1520         if (0U != xfer->subaddressSize)
1521         {
1522             uint32_t subaddressRemaining = xfer->subaddressSize;
1523             while (0U != (subaddressRemaining--))
1524             {
1525                 uint8_t subaddressByte = (uint8_t)((xfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1526                 cmd[cmdCount++]        = subaddressByte;
1527             }
1528         }
1529 
1530         /* Reads need special handling. */
1531         if ((0U != xfer->dataSize) && (xfer->direction == kLPI2C_Read))
1532         {
1533             /* Need to send repeated start if switching directions to read. */
1534             if (direction == kLPI2C_Write)
1535             {
1536                 cmd[cmdCount++] = (uint16_t)kStartCmd |
1537                                   (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1538             }
1539         }
1540 
1541         /* Set up state machine for transferring the commands. */
1542         handle->state          = (uint8_t)kSendCommandState;
1543         handle->remainingBytes = (uint16_t)cmdCount;
1544         handle->buf            = (uint8_t *)&handle->commandBuffer;
1545     }
1546 }
1547 
1548 /*!
1549  * brief Performs a non-blocking transaction on the I2C bus.
1550  *
1551  * param base The LPI2C peripheral base address.
1552  * param handle Pointer to the LPI2C master driver handle.
1553  * param transfer The pointer to the transfer descriptor.
1554  * retval #kStatus_Success The transaction was started successfully.
1555  * retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or a non-blocking
1556  *      transaction is already in progress.
1557  */
LPI2C_MasterTransferNonBlocking(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_t * transfer)1558 status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
1559                                          lpi2c_master_handle_t *handle,
1560                                          lpi2c_master_transfer_t *transfer)
1561 {
1562     assert(NULL != handle);
1563     assert(NULL != transfer);
1564     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1565 
1566     status_t result;
1567 
1568     /* Check transfer data size in read operation. */
1569     if ((transfer->direction == kLPI2C_Read) &&
1570         (transfer->dataSize > (256U * (uint32_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1571     {
1572         return kStatus_InvalidArgument;
1573     }
1574 
1575     /* Return busy if another transaction is in progress. */
1576     if (handle->state != (uint8_t)kIdleState)
1577     {
1578         result = kStatus_LPI2C_Busy;
1579     }
1580     else
1581     {
1582         result = LPI2C_CheckForBusyBus(base);
1583     }
1584 
1585     if ((status_t)kStatus_Success == result)
1586     {
1587         /* Enable the master function and disable the slave function. */
1588         LPI2C_MasterEnable(base, true);
1589         LPI2C_SlaveEnable(base, false);
1590 
1591         /* Disable LPI2C IRQ sources while we configure stuff. */
1592         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1593 
1594         /* Reset FIFO in case there are data. */
1595         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1596 
1597         /* Save transfer into handle. */
1598         handle->transfer = *transfer;
1599 
1600         /* Generate commands to send. */
1601         LPI2C_InitTransferStateMachine(handle);
1602 
1603         /* Clear all flags. */
1604         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1605 
1606         /* Turn off auto-stop option. */
1607         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1608 
1609         /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
1610         LPI2C_MasterEnableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1611     }
1612 
1613     return result;
1614 }
1615 
1616 /*!
1617  * brief Returns number of bytes transferred so far.
1618  * param base The LPI2C peripheral base address.
1619  * param handle Pointer to the LPI2C master driver handle.
1620  * param[out] count Number of bytes transferred so far by the non-blocking transaction.
1621  * retval #kStatus_Success
1622  * retval #kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1623  */
LPI2C_MasterTransferGetCount(LPI2C_Type * base,lpi2c_master_handle_t * handle,size_t * count)1624 status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count)
1625 {
1626     status_t result = kStatus_Success;
1627 
1628     assert(NULL != handle);
1629 
1630     if (NULL == count)
1631     {
1632         result = kStatus_InvalidArgument;
1633     }
1634 
1635     /* Catch when there is not an active transfer. */
1636     else if (handle->state == (uint8_t)kIdleState)
1637     {
1638         *count = 0;
1639         result = kStatus_NoTransferInProgress;
1640     }
1641     else
1642     {
1643         uint8_t state;
1644         uint16_t remainingBytes;
1645         uint32_t dataSize;
1646 
1647         /* Cache some fields with IRQs disabled. This ensures all field values */
1648         /* are synchronized with each other during an ongoing transfer. */
1649         uint32_t irqs = LPI2C_MasterGetEnabledInterrupts(base);
1650         LPI2C_MasterDisableInterrupts(base, irqs);
1651         state          = handle->state;
1652         remainingBytes = handle->remainingBytes;
1653         dataSize       = handle->transfer.dataSize;
1654         LPI2C_MasterEnableInterrupts(base, irqs);
1655 
1656         /* Get transfer count based on current transfer state. */
1657         switch (state)
1658         {
1659             case (uint8_t)kIdleState:
1660             case (uint8_t)kSendCommandState:
1661             case (uint8_t)
1662                 kIssueReadCommandState: /* XXX return correct value for this state when >256 reads are supported */
1663                 *count = 0;
1664                 break;
1665 
1666             case (uint8_t)kTransferDataState:
1667                 *count = dataSize - remainingBytes;
1668                 break;
1669 
1670             case (uint8_t)kStopState:
1671             case (uint8_t)kWaitForCompletionState:
1672             default:
1673                 *count = dataSize;
1674                 break;
1675         }
1676     }
1677 
1678     return result;
1679 }
1680 
1681 /*!
1682  * brief Terminates a non-blocking LPI2C master transmission early.
1683  *
1684  * note It is not safe to call this function from an IRQ handler that has a higher priority than the
1685  *      LPI2C peripheral's IRQ priority.
1686  *
1687  * param base The LPI2C peripheral base address.
1688  * param handle Pointer to the LPI2C master driver handle.
1689  */
LPI2C_MasterTransferAbort(LPI2C_Type * base,lpi2c_master_handle_t * handle)1690 void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1691 {
1692     if (handle->state != (uint8_t)kIdleState)
1693     {
1694         /* Disable internal IRQ enables. */
1695         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1696 
1697         /* Reset fifos. */
1698         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1699 
1700         /* If master is still busy and has not send out stop signal yet. */
1701         if ((LPI2C_MasterGetStatusFlags(base) & ((uint32_t)kLPI2C_MasterStopDetectFlag |
1702                                                  (uint32_t)kLPI2C_MasterBusyFlag)) == (uint32_t)kLPI2C_MasterBusyFlag)
1703         {
1704             /* Send a stop command to finalize the transfer. */
1705             base->MTDR = (uint32_t)kStopCmd;
1706         }
1707 
1708         /* Reset handle. */
1709         handle->state = (uint8_t)kIdleState;
1710     }
1711 }
1712 
1713 /*!
1714  * brief Reusable routine to handle master interrupts.
1715  * note This function does not need to be called unless you are reimplementing the
1716  *  nonblocking API's interrupt handler routines to add special functionality.
1717  * param base The LPI2C peripheral base address.
1718  * param lpi2cMasterHandle Pointer to the LPI2C master driver handle.
1719  */
LPI2C_MasterTransferHandleIRQ(LPI2C_Type * base,void * lpi2cMasterHandle)1720 void LPI2C_MasterTransferHandleIRQ(LPI2C_Type *base, void *lpi2cMasterHandle)
1721 {
1722     assert(lpi2cMasterHandle != NULL);
1723 
1724     lpi2c_master_handle_t *handle = (lpi2c_master_handle_t *)lpi2cMasterHandle;
1725     bool isDone                   = false;
1726     status_t result;
1727 
1728     /* Don't do anything if we don't have a valid handle. */
1729     if (NULL != handle)
1730     {
1731         if (handle->state != (uint8_t)kIdleState)
1732         {
1733             result = LPI2C_RunTransferStateMachine(base, handle, &isDone);
1734 
1735             if ((result != kStatus_Success) || isDone)
1736             {
1737                 /* Handle error, terminate xfer */
1738                 if (result != kStatus_Success)
1739                 {
1740                     LPI2C_MasterTransferAbort(base, handle);
1741                 }
1742 
1743                 /* Disable internal IRQ enables. */
1744                 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1745 
1746                 /* Set handle to idle state. */
1747                 handle->state = (uint8_t)kIdleState;
1748 
1749                 /* Invoke callback. */
1750                 if (NULL != handle->completionCallback)
1751                 {
1752                     handle->completionCallback(base, handle, result, handle->userData);
1753                 }
1754             }
1755         }
1756     }
1757 }
1758 
1759 /*!
1760  * brief Provides a default configuration for the LPI2C slave peripheral.
1761  *
1762  * This function provides the following default configuration for the LPI2C slave peripheral:
1763  * code
1764  *  slaveConfig->enableSlave               = true;
1765  *  slaveConfig->address0                  = 0U;
1766  *  slaveConfig->address1                  = 0U;
1767  *  slaveConfig->addressMatchMode          = kLPI2C_MatchAddress0;
1768  *  slaveConfig->filterDozeEnable          = true;
1769  *  slaveConfig->filterEnable              = true;
1770  *  slaveConfig->enableGeneralCall         = false;
1771  *  slaveConfig->sclStall.enableAck        = false;
1772  *  slaveConfig->sclStall.enableTx         = true;
1773  *  slaveConfig->sclStall.enableRx         = true;
1774  *  slaveConfig->sclStall.enableAddress    = true;
1775  *  slaveConfig->ignoreAck                 = false;
1776  *  slaveConfig->enableReceivedAddressRead = false;
1777  *  slaveConfig->sdaGlitchFilterWidth_ns   = 0;
1778  *  slaveConfig->sclGlitchFilterWidth_ns   = 0;
1779  *  slaveConfig->dataValidDelay_ns         = 0;
1780  *  slaveConfig->clockHoldTime_ns          = 0;
1781  * endcode
1782  *
1783  * After calling this function, override any settings  to customize the configuration,
1784  * prior to initializing the master driver with LPI2C_SlaveInit(). Be sure to override at least the a
1785  * address0 member of the configuration structure with the desired slave address.
1786  *
1787  * param[out] slaveConfig User provided configuration structure that is set to default values. Refer to
1788  *      #lpi2c_slave_config_t.
1789  */
LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t * slaveConfig)1790 void LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t *slaveConfig)
1791 {
1792     /* Initializes the configure structure to zero. */
1793     (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
1794 
1795     slaveConfig->enableSlave               = true;
1796     slaveConfig->address0                  = 0U;
1797     slaveConfig->address1                  = 0U;
1798     slaveConfig->addressMatchMode          = kLPI2C_MatchAddress0;
1799     slaveConfig->filterDozeEnable          = true;
1800     slaveConfig->filterEnable              = true;
1801     slaveConfig->enableGeneralCall         = false;
1802     slaveConfig->sclStall.enableAck        = false;
1803     slaveConfig->sclStall.enableTx         = true;
1804     slaveConfig->sclStall.enableRx         = true;
1805     slaveConfig->sclStall.enableAddress    = false;
1806     slaveConfig->ignoreAck                 = false;
1807     slaveConfig->enableReceivedAddressRead = false;
1808     slaveConfig->sdaGlitchFilterWidth_ns   = 0U; /* Set to 0 to disable the function */
1809     slaveConfig->sclGlitchFilterWidth_ns   = 0U; /* Set to 0 to disable the function */
1810     slaveConfig->dataValidDelay_ns         = 0U;
1811     /* When enabling the slave tx SCL stall, set the default clock hold time to 250ns according
1812        to I2C spec for standard mode baudrate(100k). User can manually change it to 100ns or 50ns
1813        for fast-mode(400k) or fast-mode+(1m). */
1814     slaveConfig->clockHoldTime_ns = 250U;
1815 }
1816 
1817 /*!
1818  * brief Initializes the LPI2C slave peripheral.
1819  *
1820  * This function enables the peripheral clock and initializes the LPI2C slave peripheral as described by the user
1821  * provided configuration.
1822  *
1823  * param base The LPI2C peripheral base address.
1824  * param slaveConfig User provided peripheral configuration. Use LPI2C_SlaveGetDefaultConfig() to get a set of defaults
1825  *      that you can override.
1826  * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the filter widths,
1827  *      data valid delay, and clock hold time.
1828  */
LPI2C_SlaveInit(LPI2C_Type * base,const lpi2c_slave_config_t * slaveConfig,uint32_t sourceClock_Hz)1829 void LPI2C_SlaveInit(LPI2C_Type *base, const lpi2c_slave_config_t *slaveConfig, uint32_t sourceClock_Hz)
1830 {
1831     uint32_t tmpReg;
1832     uint32_t tmpCycle;
1833 
1834 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1835 
1836     uint32_t instance = LPI2C_GetInstance(base);
1837 
1838     /* Ungate the clock. */
1839     (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
1840 #if defined(LPI2C_PERIPH_CLOCKS)
1841     /* Ungate the functional clock in initialize function. */
1842     CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
1843 #endif
1844 
1845 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1846 
1847 #if defined(LPI2C_RESETS_ARRAY)
1848     RESET_ReleasePeripheralReset(s_lpi2cResets[LPI2C_GetInstance(base)]);
1849 #endif
1850 
1851     /* Restore to reset conditions. */
1852     LPI2C_SlaveReset(base);
1853 
1854     /* Configure peripheral. */
1855     base->SAMR = LPI2C_SAMR_ADDR0(slaveConfig->address0) | LPI2C_SAMR_ADDR1(slaveConfig->address1);
1856 
1857     base->SCFGR1 =
1858         LPI2C_SCFGR1_ADDRCFG(slaveConfig->addressMatchMode) | LPI2C_SCFGR1_IGNACK(slaveConfig->ignoreAck) |
1859         LPI2C_SCFGR1_RXCFG(slaveConfig->enableReceivedAddressRead) | LPI2C_SCFGR1_GCEN(slaveConfig->enableGeneralCall) |
1860         LPI2C_SCFGR1_ACKSTALL(slaveConfig->sclStall.enableAck) | LPI2C_SCFGR1_TXDSTALL(slaveConfig->sclStall.enableTx) |
1861         LPI2C_SCFGR1_RXSTALL(slaveConfig->sclStall.enableRx) |
1862         LPI2C_SCFGR1_ADRSTALL(slaveConfig->sclStall.enableAddress);
1863 
1864     /* Calculate SDA filter width. The width is equal to FILTSDA+3 cycles of functional clock.
1865        And set FILTSDA to 0 disables the fileter, so the min value is 4. */
1866     tmpReg = LPI2C_SCFGR2_FILTSDA(
1867         LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sdaGlitchFilterWidth_ns, 4U,
1868                                 (LPI2C_SCFGR2_FILTSDA_MASK >> LPI2C_SCFGR2_FILTSDA_SHIFT) + 3U, 0U) -
1869         3U);
1870 
1871     /* Calculate SDL filter width. The width is equal to FILTSCL+3 cycles of functional clock.
1872        And set FILTSCL to 0 disables the fileter, so the min value is 4. */
1873     tmpCycle = LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sclGlitchFilterWidth_ns, 4U,
1874                                        (LPI2C_SCFGR2_FILTSCL_MASK >> LPI2C_SCFGR2_FILTSCL_SHIFT) + 3U, 0U);
1875     tmpReg |= LPI2C_SCFGR2_FILTSCL(tmpCycle - 3U);
1876 
1877     /* Calculate data valid time. The time is equal to FILTSCL+DATAVD+3 cycles of functional clock.
1878        So the min value is FILTSCL+3. */
1879     tmpReg |= LPI2C_SCFGR2_DATAVD(
1880         LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->dataValidDelay_ns, tmpCycle,
1881                                 tmpCycle + (LPI2C_SCFGR2_DATAVD_MASK >> LPI2C_SCFGR2_DATAVD_SHIFT), 0U) -
1882         tmpCycle);
1883 
1884     /* Calculate clock hold time. The time is equal to CLKHOLD+3 cycles of functional clock.
1885        So the min value is 3. */
1886     base->SCFGR2 =
1887         tmpReg | LPI2C_SCFGR2_CLKHOLD(
1888                      LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->clockHoldTime_ns, 3U,
1889                                              (LPI2C_SCFGR2_CLKHOLD_MASK >> LPI2C_SCFGR2_CLKHOLD_SHIFT) + 3U, 0U) -
1890                      3U);
1891 
1892     /* Save SCR to last so we don't enable slave until it is configured */
1893     base->SCR = LPI2C_SCR_FILTDZ(!slaveConfig->filterDozeEnable) | LPI2C_SCR_FILTEN(slaveConfig->filterEnable) |
1894                 LPI2C_SCR_SEN(slaveConfig->enableSlave);
1895 }
1896 
1897 /*!
1898  * brief Deinitializes the LPI2C slave peripheral.
1899  *
1900  * This function disables the LPI2C slave peripheral and gates the clock. It also performs a software
1901  * reset to restore the peripheral to reset conditions.
1902  *
1903  * param base The LPI2C peripheral base address.
1904  */
LPI2C_SlaveDeinit(LPI2C_Type * base)1905 void LPI2C_SlaveDeinit(LPI2C_Type *base)
1906 {
1907     LPI2C_SlaveReset(base);
1908 
1909 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1910 
1911     uint32_t instance = LPI2C_GetInstance(base);
1912 
1913     /* Gate the clock. */
1914     (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
1915 
1916 #if defined(LPI2C_PERIPH_CLOCKS)
1917     /* Gate the functional clock. */
1918     CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
1919 #endif
1920 
1921 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1922 }
1923 
1924 /*!
1925  * @brief Convert provided flags to status code, and clear any errors if present.
1926  * @param base The LPI2C peripheral base address.
1927  * @param status Current status flags value that will be checked.
1928  * @retval #kStatus_Success
1929  * @retval #kStatus_LPI2C_BitError
1930  * @retval #kStatus_LPI2C_FifoError
1931  */
LPI2C_SlaveCheckAndClearError(LPI2C_Type * base,uint32_t flags)1932 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags)
1933 {
1934     status_t result = kStatus_Success;
1935 
1936     flags &= (uint32_t)kLPI2C_SlaveErrorFlags;
1937     if (0U != flags)
1938     {
1939         /*
1940          * $Branch Coverage Justification$
1941          * It is hard to simulate bitError in automation test environment, need interference on bus.(will improve)
1942          */
1943         if (0U != (flags & (uint32_t)kLPI2C_SlaveBitErrFlag))
1944         {
1945             result = kStatus_LPI2C_BitError;
1946         }
1947         else if (0U != (flags & (uint32_t)kLPI2C_SlaveFifoErrFlag))
1948         {
1949             result = kStatus_LPI2C_FifoError;
1950         }
1951         else
1952         {
1953             ; /* Intentional empty */
1954         }
1955 
1956         /* Clear the errors. */
1957         LPI2C_SlaveClearStatusFlags(base, flags);
1958     }
1959     else
1960     {
1961         ; /* Intentional empty */
1962     }
1963 
1964     return result;
1965 }
1966 
1967 /*!
1968  * brief Performs a polling send transfer on the I2C bus.
1969  *
1970  * param base  The LPI2C peripheral base address.
1971  * param txBuff The pointer to the data to be transferred.
1972  * param txSize The length in bytes of the data to be transferred.
1973  * param[out] actualTxSize
1974  * return Error or success status returned by API.
1975  */
LPI2C_SlaveSend(LPI2C_Type * base,void * txBuff,size_t txSize,size_t * actualTxSize)1976 status_t LPI2C_SlaveSend(LPI2C_Type *base, void *txBuff, size_t txSize, size_t *actualTxSize)
1977 {
1978     status_t result  = kStatus_Success;
1979     uint8_t *buf     = (uint8_t *)txBuff;
1980     size_t remaining = txSize;
1981 
1982     assert(NULL != txBuff);
1983 
1984 #if I2C_RETRY_TIMES != 0U
1985     uint32_t waitTimes = I2C_RETRY_TIMES;
1986 #endif
1987 
1988     /* Clear stop flag. */
1989     LPI2C_SlaveClearStatusFlags(base,
1990                                 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1991 
1992     while (0U != remaining)
1993     {
1994         uint32_t flags;
1995 
1996         /* Wait until we can transmit. */
1997         do
1998         {
1999             /* Check for errors */
2000             flags  = LPI2C_SlaveGetStatusFlags(base);
2001             result = LPI2C_SlaveCheckAndClearError(base, flags);
2002             if (kStatus_Success != result)
2003             {
2004                 if (NULL != actualTxSize)
2005                 {
2006                     *actualTxSize = txSize - remaining;
2007                 }
2008                 break;
2009             }
2010 #if I2C_RETRY_TIMES != 0U
2011             waitTimes--;
2012         } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2013                                   (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2014                  (0U != waitTimes));
2015         if (0U == waitTimes)
2016         {
2017             result = kStatus_LPI2C_Timeout;
2018         }
2019 #else
2020         } while (0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2021                                  (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
2022 #endif
2023 
2024         if (kStatus_Success != result)
2025         {
2026             break;
2027         }
2028 
2029         /* Send a byte. */
2030         if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2031         {
2032             base->STDR = *buf++;
2033             --remaining;
2034         }
2035 
2036         /* Exit loop if we see a stop or restart in transfer*/
2037         /*
2038          * $Branch Coverage Justification$
2039          * $ref fsl_lpi2c_c_ref_3$
2040          */
2041         if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2042             (remaining != 0U))
2043         {
2044             LPI2C_SlaveClearStatusFlags(
2045                 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2046             break;
2047         }
2048     }
2049 
2050     if (NULL != actualTxSize)
2051     {
2052         *actualTxSize = txSize - remaining;
2053     }
2054 
2055     return result;
2056 }
2057 
2058 /*!
2059  * brief Performs a polling receive transfer on the I2C bus.
2060  *
2061  * param base  The LPI2C peripheral base address.
2062  * param rxBuff The pointer to the data to be transferred.
2063  * param rxSize The length in bytes of the data to be transferred.
2064  * param[out] actualRxSize
2065  * return Error or success status returned by API.
2066  */
LPI2C_SlaveReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize,size_t * actualRxSize)2067 status_t LPI2C_SlaveReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize, size_t *actualRxSize)
2068 {
2069     status_t result  = kStatus_Success;
2070     uint8_t *buf     = (uint8_t *)rxBuff;
2071     size_t remaining = rxSize;
2072 
2073     assert(NULL != rxBuff);
2074 
2075 #if I2C_RETRY_TIMES != 0U
2076     uint32_t waitTimes = I2C_RETRY_TIMES;
2077 #endif
2078 
2079     /* Clear stop flag. */
2080     LPI2C_SlaveClearStatusFlags(base,
2081                                 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2082 
2083     while (0U != remaining)
2084     {
2085         uint32_t flags;
2086 
2087         /* Wait until we can receive. */
2088         do
2089         {
2090             /* Check for errors */
2091             flags  = LPI2C_SlaveGetStatusFlags(base);
2092             result = LPI2C_SlaveCheckAndClearError(base, flags);
2093             if (kStatus_Success != result)
2094             {
2095                 if (NULL != actualRxSize)
2096                 {
2097                     *actualRxSize = rxSize - remaining;
2098                 }
2099                 break;
2100             }
2101 #if I2C_RETRY_TIMES != 0U
2102             waitTimes--;
2103         } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2104                                   (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2105                  (0U != waitTimes));
2106         if (0U == waitTimes)
2107         {
2108             result = kStatus_LPI2C_Timeout;
2109         }
2110 #else
2111         } while (0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2112                                  (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
2113 #endif
2114 
2115         if ((status_t)kStatus_Success != result)
2116         {
2117             break;
2118         }
2119 
2120         /* Receive a byte. */
2121         if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2122         {
2123             *buf++ = (uint8_t)(base->SRDR & LPI2C_SRDR_DATA_MASK);
2124             --remaining;
2125         }
2126 
2127         /* Exit loop if we see a stop or restart */
2128         /*
2129          * $Branch Coverage Justification$
2130          * $ref fsl_lpi2c_c_ref_3$
2131          */
2132         if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2133             (remaining != 0U))
2134         {
2135             LPI2C_SlaveClearStatusFlags(
2136                 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2137             break;
2138         }
2139     }
2140 
2141     if (NULL != actualRxSize)
2142     {
2143         *actualRxSize = rxSize - remaining;
2144     }
2145 
2146     return result;
2147 }
2148 
2149 /*!
2150  * brief Creates a new handle for the LPI2C slave non-blocking APIs.
2151  *
2152  * The creation of a handle is for use with the non-blocking APIs. Once a handle
2153  * is created, there is not a corresponding destroy handle. If the user wants to
2154  * terminate a transfer, the LPI2C_SlaveTransferAbort() API shall be called.
2155  *
2156  * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
2157  * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
2158  * enable the associated INTMUX IRQ in application.
2159 
2160  * param base The LPI2C peripheral base address.
2161  * param[out] handle Pointer to the LPI2C slave driver handle.
2162  * param callback User provided pointer to the asynchronous callback function.
2163  * param userData User provided pointer to the application callback data.
2164  */
LPI2C_SlaveTransferCreateHandle(LPI2C_Type * base,lpi2c_slave_handle_t * handle,lpi2c_slave_transfer_callback_t callback,void * userData)2165 void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
2166                                      lpi2c_slave_handle_t *handle,
2167                                      lpi2c_slave_transfer_callback_t callback,
2168                                      void *userData)
2169 {
2170     uint32_t instance;
2171 
2172     assert(NULL != handle);
2173 
2174     /* Clear out the handle. */
2175     (void)memset(handle, 0, sizeof(*handle));
2176 
2177     /* Look up instance number */
2178     instance = LPI2C_GetInstance(base);
2179 
2180     /* Save base and instance. */
2181     handle->callback = callback;
2182     handle->userData = userData;
2183 
2184     /* Save this handle for IRQ use. */
2185     s_lpi2cSlaveHandle[instance] = handle;
2186 
2187     /* Set irq handler. */
2188     s_lpi2cSlaveIsr = LPI2C_SlaveTransferHandleIRQ;
2189 
2190     /* Clear internal IRQ enables and enable NVIC IRQ. */
2191     LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2192     (void)EnableIRQ(kLpi2cIrqs[instance]);
2193 
2194     /* Nack by default. */
2195     base->STAR = LPI2C_STAR_TXNACK_MASK;
2196 }
2197 
2198 /*!
2199  * brief Starts accepting slave transfers.
2200  *
2201  * Call this API after calling I2C_SlaveInit() and LPI2C_SlaveTransferCreateHandle() to start processing
2202  * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
2203  * callback that was passed into the call to LPI2C_SlaveTransferCreateHandle(). The callback is always invoked
2204  * from the interrupt context.
2205  *
2206  * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
2207  * the OR'd combination of #lpi2c_slave_transfer_event_t enumerators for the events you wish to receive.
2208  * The #kLPI2C_SlaveTransmitEvent and #kLPI2C_SlaveReceiveEvent events are always enabled and do not need
2209  * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
2210  * receive events that are always enabled. In addition, the #kLPI2C_SlaveAllEvents constant is provided as
2211  * a convenient way to enable all events.
2212  *
2213  * param base The LPI2C peripheral base address.
2214  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2215  * param eventMask Bit mask formed by OR'ing together #lpi2c_slave_transfer_event_t enumerators to specify
2216  *      which events to send to the callback. Other accepted values are 0 to get a default set of
2217  *      only the transmit and receive events, and #kLPI2C_SlaveAllEvents to enable all events.
2218  *
2219  * retval #kStatus_Success Slave transfers were successfully started.
2220  * retval #kStatus_LPI2C_Busy Slave transfers have already been started on this handle.
2221  */
LPI2C_SlaveTransferNonBlocking(LPI2C_Type * base,lpi2c_slave_handle_t * handle,uint32_t eventMask)2222 status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask)
2223 {
2224     status_t result = kStatus_Success;
2225 
2226     assert(NULL != handle);
2227 
2228     /* Return busy if another transaction is in progress. */
2229     if (handle->isBusy)
2230     {
2231         result = kStatus_LPI2C_Busy;
2232     }
2233     else
2234     {
2235         /* Enable the slave function and disable the master function. */
2236         LPI2C_MasterEnable(base, false);
2237         LPI2C_SlaveEnable(base, true);
2238         /* Return an error if the bus is already in use not by us. */
2239         uint32_t status = LPI2C_SlaveGetStatusFlags(base);
2240         /*
2241          * $Branch Coverage Justification$
2242          * $ref fsl_lpi2c_c_ref_2$
2243          */
2244         if ((0U != (status & (uint32_t)kLPI2C_SlaveBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_SlaveBusyFlag)))
2245         {
2246             result = kStatus_LPI2C_Busy;
2247         }
2248     }
2249 
2250     if ((status_t)kStatus_Success == result)
2251     {
2252         /* Disable LPI2C IRQ sources while we configure stuff. */
2253         LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2254 
2255         /* Clear transfer in handle. */
2256         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2257 
2258         /* Record that we're busy. */
2259         handle->isBusy = true;
2260 
2261         /* Set up event mask. tx and rx are always enabled. */
2262         handle->eventMask = eventMask | (uint32_t)kLPI2C_SlaveTransmitEvent | (uint32_t)kLPI2C_SlaveReceiveEvent;
2263 
2264         /* Ack by default. */
2265         base->STAR = 0U;
2266 
2267         /* Clear all flags. */
2268         LPI2C_SlaveClearStatusFlags(base, (uint32_t)kLPI2C_SlaveClearFlags);
2269 
2270         /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
2271         LPI2C_SlaveEnableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2272     }
2273 
2274     return result;
2275 }
2276 
2277 /*!
2278  * brief Gets the slave transfer status during a non-blocking transfer.
2279  * param base The LPI2C peripheral base address.
2280  * param handle Pointer to i2c_slave_handle_t structure.
2281  * param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not
2282  *      required.
2283  * retval #kStatus_Success
2284  * retval #kStatus_NoTransferInProgress
2285  */
LPI2C_SlaveTransferGetCount(LPI2C_Type * base,lpi2c_slave_handle_t * handle,size_t * count)2286 status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count)
2287 {
2288     status_t status = kStatus_Success;
2289 
2290     assert(NULL != handle);
2291 
2292     if (count == NULL)
2293     {
2294         status = kStatus_InvalidArgument;
2295     }
2296 
2297     /* Catch when there is not an active transfer. */
2298     else if (!handle->isBusy)
2299     {
2300         *count = 0;
2301         status = kStatus_NoTransferInProgress;
2302     }
2303 
2304     /* For an active transfer, just return the count from the handle. */
2305     else
2306     {
2307         *count = handle->transferredCount;
2308     }
2309 
2310     return status;
2311 }
2312 
2313 /*!
2314  * brief Aborts the slave non-blocking transfers.
2315  * note This API could be called at any time to stop slave for handling the bus events.
2316  * param base The LPI2C peripheral base address.
2317  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2318  */
LPI2C_SlaveTransferAbort(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2319 void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2320 {
2321     assert(NULL != handle);
2322 
2323     /* Return idle if no transaction is in progress. */
2324     if (handle->isBusy)
2325     {
2326         /* Disable LPI2C IRQ sources. */
2327         LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2328 
2329         /* Nack by default. */
2330         base->STAR = LPI2C_STAR_TXNACK_MASK;
2331 
2332         /* Reset transfer info. */
2333         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2334 
2335         /* We're no longer busy. */
2336         handle->isBusy = false;
2337     }
2338 }
2339 
2340 /*!
2341  * brief Reusable routine to handle slave interrupts.
2342  * note This function does not need to be called unless you are reimplementing the
2343  *  non blocking API's interrupt handler routines to add special functionality.
2344  * param base The LPI2C peripheral base address.
2345  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2346  */
LPI2C_SlaveTransferHandleIRQ(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2347 void LPI2C_SlaveTransferHandleIRQ(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2348 {
2349     uint32_t flags;
2350     lpi2c_slave_transfer_t *xfer;
2351 
2352     /* Check for a valid handle in case of a spurious interrupt. */
2353     if (NULL != handle)
2354     {
2355         xfer = &handle->transfer;
2356 
2357         /* Get status flags. */
2358         flags = LPI2C_SlaveGetStatusFlags(base);
2359 
2360         if (0U != (flags & ((uint32_t)kLPI2C_SlaveBitErrFlag | (uint32_t)kLPI2C_SlaveFifoErrFlag)))
2361         {
2362             xfer->event            = kLPI2C_SlaveCompletionEvent;
2363             xfer->completionStatus = LPI2C_SlaveCheckAndClearError(base, flags);
2364 
2365             if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveCompletionEvent)) && (NULL != handle->callback))
2366             {
2367                 handle->callback(base, xfer, handle->userData);
2368             }
2369         }
2370         else
2371         {
2372             if (0U !=
2373                 (flags & (((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag) | ((uint32_t)kLPI2C_SlaveStopDetectFlag))))
2374             {
2375                 xfer->event            = (0U != (flags & (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)) ?
2376                                              kLPI2C_SlaveRepeatedStartEvent :
2377                                              kLPI2C_SlaveCompletionEvent;
2378                 xfer->receivedAddress  = 0U;
2379                 xfer->completionStatus = kStatus_Success;
2380                 xfer->transferredCount = handle->transferredCount;
2381 
2382                 if (xfer->event == kLPI2C_SlaveCompletionEvent)
2383                 {
2384                     handle->isBusy = false;
2385                 }
2386 
2387                 if (handle->wasTransmit)
2388                 {
2389                     /* Subtract one from the transmit count to offset the fact that LPI2C asserts the */
2390                     /* tx flag before it sees the nack from the master-receiver, thus causing one more */
2391                     /* count that the master actually receives. */
2392                     --xfer->transferredCount;
2393                     handle->wasTransmit = false;
2394                 }
2395 
2396                 /* Clear the flag. */
2397                 LPI2C_SlaveClearStatusFlags(base, flags & ((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag |
2398                                                            (uint32_t)kLPI2C_SlaveStopDetectFlag));
2399 
2400                 /* Revert to sending an Ack by default, in case we sent a Nack for receive. */
2401                 base->STAR = 0U;
2402 
2403                 if ((0U != (handle->eventMask & (uint32_t)xfer->event)) && (NULL != handle->callback))
2404                 {
2405                     handle->callback(base, xfer, handle->userData);
2406                 }
2407 
2408                 if (0U != (flags & (uint32_t)kLPI2C_SlaveStopDetectFlag))
2409                 {
2410                     /* Clean up transfer info on completion, after the callback has been invoked. */
2411                     (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2412                 }
2413             }
2414             if (0U != (flags & (uint32_t)kLPI2C_SlaveAddressValidFlag))
2415             {
2416                 xfer->event           = kLPI2C_SlaveAddressMatchEvent;
2417                 xfer->receivedAddress = (uint8_t)(base->SASR & LPI2C_SASR_RADDR_MASK);
2418 
2419                 /* Update handle status to busy because slave is addressed. */
2420                 handle->isBusy = true;
2421                 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveAddressMatchEvent)) && (NULL != handle->callback))
2422                 {
2423                     handle->callback(base, xfer, handle->userData);
2424                 }
2425             }
2426             if (0U != (flags & (uint32_t)kLPI2C_SlaveTransmitAckFlag))
2427             {
2428                 xfer->event = kLPI2C_SlaveTransmitAckEvent;
2429 
2430                 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveTransmitAckEvent)) && (NULL != handle->callback))
2431                 {
2432                     handle->callback(base, xfer, handle->userData);
2433                 }
2434             }
2435 
2436             /* Handle transmit and receive. */
2437             if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2438             {
2439                 handle->wasTransmit = true;
2440 
2441                 /* If we're out of data, invoke callback to get more. */
2442                 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2443                 {
2444                     xfer->event = kLPI2C_SlaveTransmitEvent;
2445                     if (NULL != handle->callback)
2446                     {
2447                         handle->callback(base, xfer, handle->userData);
2448                     }
2449 
2450                     /* Clear the transferred count now that we have a new buffer. */
2451                     handle->transferredCount = 0U;
2452                 }
2453 
2454                 /* Transmit a byte. */
2455                 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2456                 {
2457                     base->STDR = *xfer->data++;
2458                     --xfer->dataSize;
2459                     ++handle->transferredCount;
2460                 }
2461             }
2462             if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2463             {
2464                 /* If we're out of room in the buffer, invoke callback to get another. */
2465                 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2466                 {
2467                     xfer->event = kLPI2C_SlaveReceiveEvent;
2468                     if (NULL != handle->callback)
2469                     {
2470                         handle->callback(base, xfer, handle->userData);
2471                     }
2472 
2473                     /* Clear the transferred count now that we have a new buffer. */
2474                     handle->transferredCount = 0U;
2475                 }
2476 
2477                 /* Receive a byte. */
2478                 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2479                 {
2480                     *xfer->data++ = (uint8_t)base->SRDR;
2481                     --xfer->dataSize;
2482                     ++handle->transferredCount;
2483                 }
2484                 else
2485                 {
2486                     /* We don't have any room to receive more data, so send a nack. */
2487                     base->STAR = LPI2C_STAR_TXNACK_MASK;
2488                 }
2489             }
2490         }
2491     }
2492 }
2493 
2494 #if !(defined(FSL_FEATURE_I2C_HAS_NO_IRQ) && FSL_FEATURE_I2C_HAS_NO_IRQ)
2495 /*!
2496  * @brief Shared IRQ handler that can call both master and slave ISRs.
2497  *
2498  * The master and slave ISRs are called through function pointers in order to decouple
2499  * this code from the ISR functions. Without this, the linker would always pull in both
2500  * ISRs and every function they call, even if only the functional API was used.
2501  *
2502  * @param base The LPI2C peripheral base address.
2503  * @param instance The LPI2C peripheral instance number.
2504  */
LPI2C_CommonIRQHandler(LPI2C_Type * base,uint32_t instance)2505 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance)
2506 {
2507     /* Check for master IRQ. */
2508     if ((0U != (base->MCR & LPI2C_MCR_MEN_MASK)) && (NULL != s_lpi2cMasterIsr))
2509     {
2510         /* Master mode. */
2511         s_lpi2cMasterIsr(base, s_lpi2cMasterHandle[instance]);
2512     }
2513 
2514     /* Check for slave IRQ. */
2515     if ((0U != (base->SCR & LPI2C_SCR_SEN_MASK)) && (NULL != s_lpi2cSlaveIsr))
2516     {
2517         /* Slave mode. */
2518         s_lpi2cSlaveIsr(base, s_lpi2cSlaveHandle[instance]);
2519     }
2520     SDK_ISR_EXIT_BARRIER;
2521 }
2522 #endif
2523 
2524 #if defined(LPI2C0)
2525 /* Implementation of LPI2C0 handler named in startup code. */
2526 void LPI2C0_DriverIRQHandler(void);
LPI2C0_DriverIRQHandler(void)2527 void LPI2C0_DriverIRQHandler(void)
2528 {
2529     LPI2C_CommonIRQHandler(LPI2C0, 0U);
2530 }
2531 #endif
2532 
2533 #if defined(LPI2C1)
2534 /* Implementation of LPI2C1 handler named in startup code. */
2535 void LPI2C1_DriverIRQHandler(void);
LPI2C1_DriverIRQHandler(void)2536 void LPI2C1_DriverIRQHandler(void)
2537 {
2538     LPI2C_CommonIRQHandler(LPI2C1, 1U);
2539 }
2540 #endif
2541 
2542 #if defined(LPI2C2)
2543 /* Implementation of LPI2C2 handler named in startup code. */
2544 void LPI2C2_DriverIRQHandler(void);
LPI2C2_DriverIRQHandler(void)2545 void LPI2C2_DriverIRQHandler(void)
2546 {
2547     LPI2C_CommonIRQHandler(LPI2C2, 2U);
2548 }
2549 #endif
2550 
2551 #if defined(LPI2C3)
2552 /* Implementation of LPI2C3 handler named in startup code. */
2553 void LPI2C3_DriverIRQHandler(void);
LPI2C3_DriverIRQHandler(void)2554 void LPI2C3_DriverIRQHandler(void)
2555 {
2556     LPI2C_CommonIRQHandler(LPI2C3, 3U);
2557 }
2558 #endif
2559 
2560 #if defined(LPI2C4)
2561 /* Implementation of LPI2C4 handler named in startup code. */
2562 void LPI2C4_DriverIRQHandler(void);
LPI2C4_DriverIRQHandler(void)2563 void LPI2C4_DriverIRQHandler(void)
2564 {
2565     LPI2C_CommonIRQHandler(LPI2C4, 4U);
2566 }
2567 #endif
2568 
2569 #if defined(LPI2C5)
2570 /* Implementation of LPI2C5 handler named in startup code. */
2571 void LPI2C5_DriverIRQHandler(void);
LPI2C5_DriverIRQHandler(void)2572 void LPI2C5_DriverIRQHandler(void)
2573 {
2574     LPI2C_CommonIRQHandler(LPI2C5, 5U);
2575 }
2576 #endif
2577 
2578 #if defined(LPI2C6)
2579 /* Implementation of LPI2C6 handler named in startup code. */
2580 void LPI2C6_DriverIRQHandler(void);
LPI2C6_DriverIRQHandler(void)2581 void LPI2C6_DriverIRQHandler(void)
2582 {
2583     LPI2C_CommonIRQHandler(LPI2C6, 6U);
2584 }
2585 #endif
2586 
2587 #if defined(CM4_0__LPI2C)
2588 /* Implementation of CM4_0__LPI2C handler named in startup code. */
2589 void M4_0_LPI2C_DriverIRQHandler(void);
M4_0_LPI2C_DriverIRQHandler(void)2590 void M4_0_LPI2C_DriverIRQHandler(void)
2591 {
2592     LPI2C_CommonIRQHandler(CM4_0__LPI2C, LPI2C_GetInstance(CM4_0__LPI2C));
2593 }
2594 #endif
2595 
2596 #if defined(CM4__LPI2C)
2597 /* Implementation of CM4__LPI2C handler named in startup code. */
2598 void M4_LPI2C_DriverIRQHandler(void);
M4_LPI2C_DriverIRQHandler(void)2599 void M4_LPI2C_DriverIRQHandler(void)
2600 {
2601     LPI2C_CommonIRQHandler(CM4__LPI2C, LPI2C_GetInstance(CM4__LPI2C));
2602 }
2603 #endif
2604 
2605 #if defined(CM4_1__LPI2C)
2606 /* Implementation of CM4_1__LPI2C handler named in startup code. */
2607 void M4_1_LPI2C_DriverIRQHandler(void);
M4_1_LPI2C_DriverIRQHandler(void)2608 void M4_1_LPI2C_DriverIRQHandler(void)
2609 {
2610     LPI2C_CommonIRQHandler(CM4_1__LPI2C, LPI2C_GetInstance(CM4_1__LPI2C));
2611 }
2612 #endif
2613 
2614 #if defined(DMA__LPI2C0)
2615 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2616 void DMA_I2C0_INT_DriverIRQHandler(void);
DMA_I2C0_INT_DriverIRQHandler(void)2617 void DMA_I2C0_INT_DriverIRQHandler(void)
2618 {
2619     LPI2C_CommonIRQHandler(DMA__LPI2C0, LPI2C_GetInstance(DMA__LPI2C0));
2620 }
2621 #endif
2622 
2623 #if defined(DMA__LPI2C1)
2624 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2625 void DMA_I2C1_INT_DriverIRQHandler(void);
DMA_I2C1_INT_DriverIRQHandler(void)2626 void DMA_I2C1_INT_DriverIRQHandler(void)
2627 {
2628     LPI2C_CommonIRQHandler(DMA__LPI2C1, LPI2C_GetInstance(DMA__LPI2C1));
2629 }
2630 #endif
2631 
2632 #if defined(DMA__LPI2C2)
2633 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2634 void DMA_I2C2_INT_DriverIRQHandler(void);
DMA_I2C2_INT_DriverIRQHandler(void)2635 void DMA_I2C2_INT_DriverIRQHandler(void)
2636 {
2637     LPI2C_CommonIRQHandler(DMA__LPI2C2, LPI2C_GetInstance(DMA__LPI2C2));
2638 }
2639 #endif
2640 
2641 #if defined(DMA__LPI2C3)
2642 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2643 void DMA_I2C3_INT_DriverIRQHandler(void);
DMA_I2C3_INT_DriverIRQHandler(void)2644 void DMA_I2C3_INT_DriverIRQHandler(void)
2645 {
2646     LPI2C_CommonIRQHandler(DMA__LPI2C3, LPI2C_GetInstance(DMA__LPI2C3));
2647 }
2648 #endif
2649 
2650 #if defined(DMA__LPI2C4)
2651 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2652 void DMA_I2C4_INT_DriverIRQHandler(void);
DMA_I2C4_INT_DriverIRQHandler(void)2653 void DMA_I2C4_INT_DriverIRQHandler(void)
2654 {
2655     LPI2C_CommonIRQHandler(DMA__LPI2C4, LPI2C_GetInstance(DMA__LPI2C4));
2656 }
2657 #endif
2658 
2659 #if defined(ADMA__LPI2C0)
2660 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2661 void ADMA_I2C0_INT_DriverIRQHandler(void);
ADMA_I2C0_INT_DriverIRQHandler(void)2662 void ADMA_I2C0_INT_DriverIRQHandler(void)
2663 {
2664     LPI2C_CommonIRQHandler(ADMA__LPI2C0, LPI2C_GetInstance(ADMA__LPI2C0));
2665 }
2666 #endif
2667 
2668 #if defined(ADMA__LPI2C1)
2669 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2670 void ADMA_I2C1_INT_DriverIRQHandler(void);
ADMA_I2C1_INT_DriverIRQHandler(void)2671 void ADMA_I2C1_INT_DriverIRQHandler(void)
2672 {
2673     LPI2C_CommonIRQHandler(ADMA__LPI2C1, LPI2C_GetInstance(ADMA__LPI2C1));
2674 }
2675 #endif
2676 
2677 #if defined(ADMA__LPI2C2)
2678 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2679 void ADMA_I2C2_INT_DriverIRQHandler(void);
ADMA_I2C2_INT_DriverIRQHandler(void)2680 void ADMA_I2C2_INT_DriverIRQHandler(void)
2681 {
2682     LPI2C_CommonIRQHandler(ADMA__LPI2C2, LPI2C_GetInstance(ADMA__LPI2C2));
2683 }
2684 #endif
2685 
2686 #if defined(ADMA__LPI2C3)
2687 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2688 void ADMA_I2C3_INT_DriverIRQHandler(void);
ADMA_I2C3_INT_DriverIRQHandler(void)2689 void ADMA_I2C3_INT_DriverIRQHandler(void)
2690 {
2691     LPI2C_CommonIRQHandler(ADMA__LPI2C3, LPI2C_GetInstance(ADMA__LPI2C3));
2692 }
2693 #endif
2694 
2695 #if defined(ADMA__LPI2C4)
2696 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2697 void ADMA_I2C4_INT_DriverIRQHandler(void);
ADMA_I2C4_INT_DriverIRQHandler(void)2698 void ADMA_I2C4_INT_DriverIRQHandler(void)
2699 {
2700     LPI2C_CommonIRQHandler(ADMA__LPI2C4, LPI2C_GetInstance(ADMA__LPI2C4));
2701 }
2702 #endif
2703