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