Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:00

0001 /*
0002  * Copyright (c) 2015, Freescale Semiconductor, Inc.
0003  * Copyright 2016-2022 NXP
0004  * All rights reserved.
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_lpi2c.h"
0010 #include <stdlib.h>
0011 #include <string.h>
0012 
0013 /*******************************************************************************
0014  * Definitions
0015  ******************************************************************************/
0016 
0017 /* Component ID definition, used by tools. */
0018 #ifndef FSL_COMPONENT_ID
0019 #define FSL_COMPONENT_ID "platform.drivers.lpi2c"
0020 #endif
0021 
0022 /* ! @brief LPI2C master fifo commands. */
0023 enum
0024 {
0025     kTxDataCmd = LPI2C_MTDR_CMD(0x0U), /*!< Transmit DATA[7:0] */
0026     kRxDataCmd = LPI2C_MTDR_CMD(0X1U), /*!< Receive (DATA[7:0] + 1) bytes */
0027     kStopCmd   = LPI2C_MTDR_CMD(0x2U), /*!< Generate STOP condition */
0028     kStartCmd  = LPI2C_MTDR_CMD(0x4U), /*!< Generate(repeated) START and transmit address in DATA[[7:0] */
0029 };
0030 
0031 /*!
0032  * @brief Default watermark values.
0033  *
0034  * The default watermarks are set to zero.
0035  */
0036 enum
0037 {
0038     kDefaultTxWatermark = 0,
0039     kDefaultRxWatermark = 0,
0040 };
0041 
0042 /*! @brief States for the state machine used by transactional APIs. */
0043 enum
0044 {
0045     kIdleState = 0,
0046     kSendCommandState,
0047     kIssueReadCommandState,
0048     kTransferDataState,
0049     kStopState,
0050     kWaitForCompletionState,
0051 };
0052 
0053 /*
0054  * <! Structure definition for variables that passed as parameters in LPI2C_RunTransferStateMachine.
0055  * The structure is private.
0056  */
0057 typedef struct _lpi2c_state_machine_param
0058 {
0059     bool state_complete;
0060     size_t rxCount;
0061     size_t txCount;
0062     uint32_t status;
0063 } lpi2c_state_machine_param_t;
0064 
0065 /*! @brief Typedef for slave interrupt handler. */
0066 typedef void (*lpi2c_slave_isr_t)(LPI2C_Type *base, lpi2c_slave_handle_t *handle);
0067 
0068 /*******************************************************************************
0069  * Prototypes
0070  ******************************************************************************/
0071 static uint32_t LPI2C_GetCyclesForWidth(
0072     uint32_t sourceClock_Hz, uint32_t width_ns, uint32_t minCycles, uint32_t maxCycles, uint32_t prescaler);
0073 
0074 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base);
0075 
0076 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone);
0077 
0078 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle);
0079 
0080 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags);
0081 
0082 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance);
0083 
0084 /*!
0085  * @brief introduce function LPI2C_TransferStateMachineSendCommandState.
0086  * This function was deal with Send Command State.
0087  *
0088  * @param base The I2C peripheral base address.
0089  * @param handle Master nonblocking driver handle.
0090  * @param variable_set Pass the address of the parent function variable.
0091  */
0092 static void LPI2C_TransferStateMachineSendCommand(LPI2C_Type *base,
0093                                                   lpi2c_master_handle_t *handle,
0094                                                   lpi2c_state_machine_param_t *stateParams);
0095 
0096 /*!
0097  * @brief introduce function LPI2C_TransferStateMachineIssueReadCommandState.
0098  * This function was deal with Issue Read Command State.
0099  *
0100  * @param base The I2C peripheral base address.
0101  * @param handle Master nonblocking driver handle.
0102  * @param stateParams Pass the address of the parent function variable.
0103  */
0104 static void LPI2C_TransferStateMachineReadCommand(LPI2C_Type *base,
0105                                                   lpi2c_master_handle_t *handle,
0106                                                   lpi2c_state_machine_param_t *stateParams);
0107 
0108 /*!
0109  * @brief introduce function LPI2C_TransferStateMachineTransferDataState.
0110  * This function was deal with init Transfer Data State.
0111  *
0112  * @param base The I2C peripheral base address.
0113  * @param handle Master nonblocking driver handle.
0114  * @param stateParams Pass the address of the parent function variable.
0115  */
0116 static void LPI2C_TransferStateMachineTransferData(LPI2C_Type *base,
0117                                                    lpi2c_master_handle_t *handle,
0118                                                    lpi2c_state_machine_param_t *stateParams);
0119 
0120 /*!
0121  * @brief introduce function LPI2C_TransferStateMachineStopState.
0122  * This function was deal with Stop State.
0123  *
0124  * @param base The I2C peripheral base address.
0125  * @param handle Master nonblocking driver handle.
0126  * @param stateParams Pass the address of the parent function variable.
0127  * @param[out] isDone Set to true if the transfer has completed.
0128  */
0129 static void LPI2C_TransferStateMachineStopState(LPI2C_Type *base,
0130                                                 lpi2c_master_handle_t *handle,
0131                                                 lpi2c_state_machine_param_t *stateParams,
0132                                                 bool *isDone);
0133 
0134 /*!
0135  * @brief introduce function LPI2C_TransferStateMachineWaitState.
0136  * This function was deal with Wait For Completion State.
0137  *
0138  * @param base The I2C peripheral base address.
0139  * @param handle Master nonblocking driver handle.
0140  * @param stateParams Pass the address of the parent function variable.
0141  * @param[out] isDone Set to true if the transfer has completed.
0142  */
0143 static void LPI2C_TransferStateMachineWaitState(LPI2C_Type *base,
0144                                                 lpi2c_master_handle_t *handle,
0145                                                 lpi2c_state_machine_param_t *stateParams,
0146                                                 bool *isDone);
0147 
0148 /*******************************************************************************
0149  * Variables
0150  ******************************************************************************/
0151 
0152 /*! @brief Array to map LPI2C instance number to base pointer. */
0153 static LPI2C_Type *const kLpi2cBases[] = LPI2C_BASE_PTRS;
0154 
0155 /*! @brief Array to map LPI2C instance number to IRQ number, used internally for LPI2C master interrupt and EDMA
0156 transactional APIs. */
0157 IRQn_Type const kLpi2cIrqs[] = LPI2C_IRQS;
0158 
0159 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0160 /*! @brief Array to map LPI2C instance number to clock gate enum. */
0161 static clock_ip_name_t const kLpi2cClocks[] = LPI2C_CLOCKS;
0162 
0163 #if defined(LPI2C_PERIPH_CLOCKS)
0164 /*! @brief Array to map LPI2C instance number to pheripheral clock gate enum. */
0165 static const clock_ip_name_t kLpi2cPeriphClocks[] = LPI2C_PERIPH_CLOCKS;
0166 #endif
0167 
0168 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0169 
0170 /*! @brief Pointer to master IRQ handler for each instance, used internally for LPI2C master interrupt and EDMA
0171 transactional APIs. */
0172 lpi2c_master_isr_t s_lpi2cMasterIsr;
0173 
0174 /*! @brief Pointers to master handles for each instance, used internally for LPI2C master interrupt and EDMA
0175 transactional APIs. */
0176 void *s_lpi2cMasterHandle[ARRAY_SIZE(kLpi2cBases)];
0177 
0178 /*! @brief Pointer to slave IRQ handler for each instance. */
0179 static lpi2c_slave_isr_t s_lpi2cSlaveIsr;
0180 
0181 /*! @brief Pointers to slave handles for each instance. */
0182 static lpi2c_slave_handle_t *s_lpi2cSlaveHandle[ARRAY_SIZE(kLpi2cBases)];
0183 
0184 /*******************************************************************************
0185  * Code
0186  ******************************************************************************/
0187 
0188 /*!
0189  * brief Returns an instance number given a base address.
0190  *
0191  * If an invalid base address is passed, debug builds will assert. Release builds will just return
0192  * instance number 0.
0193  *
0194  * param base The LPI2C peripheral base address.
0195  * return LPI2C instance number starting from 0.
0196  */
0197 uint32_t LPI2C_GetInstance(LPI2C_Type *base)
0198 {
0199     uint32_t instance;
0200     for (instance = 0U; instance < ARRAY_SIZE(kLpi2cBases); ++instance)
0201     {
0202         if (kLpi2cBases[instance] == base)
0203         {
0204             break;
0205         }
0206     }
0207 
0208     assert(instance < ARRAY_SIZE(kLpi2cBases));
0209     return instance;
0210 }
0211 
0212 /*!
0213  * @brief Computes a cycle count for a given time in nanoseconds.
0214  * @param sourceClock_Hz LPI2C functional clock frequency in Hertz.
0215  * @param width_ns Desired with in nanoseconds.
0216  * @param minCycles Minimum cycle count.
0217  * @param maxCycles Maximum cycle count.
0218  * @param prescaler LPI2C prescaler setting. If the cycle period is not affected by the prescaler value, set it to 0.
0219  */
0220 static uint32_t LPI2C_GetCyclesForWidth(
0221     uint32_t sourceClock_Hz, uint32_t width_ns, uint32_t minCycles, uint32_t maxCycles, uint32_t prescaler)
0222 {
0223     assert(sourceClock_Hz > 0U);
0224 
0225     uint32_t divider = 1U;
0226 
0227     while (prescaler != 0U)
0228     {
0229         divider *= 2U;
0230         prescaler--;
0231     }
0232 
0233     uint32_t busCycle_ns = 1000000U / (sourceClock_Hz / divider / 1000U);
0234     /* Calculate the cycle count, round up the calculated value. */
0235     uint32_t cycles = (width_ns * 10U / busCycle_ns + 5U) / 10U;
0236 
0237     /* If the calculated value is smaller than the minimum value, use the minimum value */
0238     if (cycles < minCycles)
0239     {
0240         cycles = minCycles;
0241     }
0242     /* If the calculated value is larger than the maximum value, use the maxmum value */
0243     if (cycles > maxCycles)
0244     {
0245         cycles = maxCycles;
0246     }
0247 
0248     return cycles;
0249 }
0250 
0251 /*!
0252  * @brief Convert provided flags to status code, and clear any errors if present.
0253  * @param base The LPI2C peripheral base address.
0254  * @param status Current status flags value that will be checked.
0255  * @retval #kStatus_Success
0256  * @retval #kStatus_LPI2C_PinLowTimeout
0257  * @retval #kStatus_LPI2C_ArbitrationLost
0258  * @retval #kStatus_LPI2C_Nak
0259  * @retval #kStatus_LPI2C_FifoError
0260  */
0261 /* Not static so it can be used from fsl_lpi2c_edma.c. */
0262 status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status)
0263 {
0264     status_t result = kStatus_Success;
0265 
0266     /* Check for error. These errors cause a stop to automatically be sent. We must */
0267     /* clear the errors before a new transfer can start. */
0268     status &= (uint32_t)kLPI2C_MasterErrorFlags;
0269     if (0U != status)
0270     {
0271         /* Select the correct error code. Ordered by severity, with bus issues first. */
0272         if (0U != (status & (uint32_t)kLPI2C_MasterPinLowTimeoutFlag))
0273         {
0274             result = kStatus_LPI2C_PinLowTimeout;
0275         }
0276         else if (0U != (status & (uint32_t)kLPI2C_MasterArbitrationLostFlag))
0277         {
0278             result = kStatus_LPI2C_ArbitrationLost;
0279         }
0280         else if (0U != (status & (uint32_t)kLPI2C_MasterNackDetectFlag))
0281         {
0282             result = kStatus_LPI2C_Nak;
0283         }
0284         else if (0U != (status & (uint32_t)kLPI2C_MasterFifoErrFlag))
0285         {
0286             result = kStatus_LPI2C_FifoError;
0287         }
0288         else
0289         {
0290             ; /* Intentional empty */
0291         }
0292 
0293         /* Clear the flags. */
0294         LPI2C_MasterClearStatusFlags(base, status);
0295 
0296         /* Reset fifos. These flags clear automatically. */
0297         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
0298     }
0299     else
0300     {
0301         ; /* Intentional empty */
0302     }
0303 
0304     return result;
0305 }
0306 
0307 /*!
0308  * @brief Wait until there is room in the tx fifo.
0309  * @param base The LPI2C peripheral base address.
0310  * @retval #kStatus_Success
0311  * @retval #kStatus_LPI2C_PinLowTimeout
0312  * @retval #kStatus_LPI2C_ArbitrationLost
0313  * @retval #kStatus_LPI2C_Nak
0314  * @retval #kStatus_LPI2C_FifoError
0315  */
0316 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base)
0317 {
0318     status_t result = kStatus_Success;
0319     uint32_t status;
0320     size_t txCount;
0321     size_t txFifoSize = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
0322 
0323 #if I2C_RETRY_TIMES != 0U
0324     uint32_t waitTimes = I2C_RETRY_TIMES;
0325 #endif
0326     do
0327     {
0328         /* Get the number of words in the tx fifo and compute empty slots. */
0329         LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
0330         txCount = txFifoSize - txCount;
0331 
0332         /* Check for error flags. */
0333         status = LPI2C_MasterGetStatusFlags(base);
0334         result = LPI2C_MasterCheckAndClearError(base, status);
0335         if (kStatus_Success != result)
0336         {
0337             break;
0338         }
0339 #if I2C_RETRY_TIMES != 0U
0340         waitTimes--;
0341     } while ((0U == txCount) && (0U != waitTimes));
0342 
0343     if (0U == waitTimes)
0344     {
0345         result = kStatus_LPI2C_Timeout;
0346     }
0347 #else
0348     } while (0U == txCount);
0349 #endif
0350 
0351     return result;
0352 }
0353 
0354 /*!
0355  * @brief Make sure the bus isn't already busy.
0356  *
0357  * A busy bus is allowed if we are the one driving it.
0358  *
0359  * @param base The LPI2C peripheral base address.
0360  * @retval #kStatus_Success
0361  * @retval #kStatus_LPI2C_Busy
0362  */
0363 /* Not static so it can be used from fsl_lpi2c_edma.c. */
0364 status_t LPI2C_CheckForBusyBus(LPI2C_Type *base)
0365 {
0366     status_t ret = kStatus_Success;
0367 
0368     uint32_t status = LPI2C_MasterGetStatusFlags(base);
0369     if ((0U != (status & (uint32_t)kLPI2C_MasterBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_MasterBusyFlag)))
0370     {
0371         ret = kStatus_LPI2C_Busy;
0372     }
0373 
0374     return ret;
0375 }
0376 
0377 /*!
0378  * brief Provides a default configuration for the LPI2C master peripheral.
0379  *
0380  * This function provides the following default configuration for the LPI2C master peripheral:
0381  * code
0382  *  masterConfig->enableMaster            = true;
0383  *  masterConfig->debugEnable             = false;
0384  *  masterConfig->ignoreAck               = false;
0385  *  masterConfig->pinConfig               = kLPI2C_2PinOpenDrain;
0386  *  masterConfig->baudRate_Hz             = 100000U;
0387  *  masterConfig->busIdleTimeout_ns       = 0U;
0388  *  masterConfig->pinLowTimeout_ns        = 0U;
0389  *  masterConfig->sdaGlitchFilterWidth_ns = 0U;
0390  *  masterConfig->sclGlitchFilterWidth_ns = 0U;
0391  *  masterConfig->hostRequest.enable      = false;
0392  *  masterConfig->hostRequest.source      = kLPI2C_HostRequestExternalPin;
0393  *  masterConfig->hostRequest.polarity    = kLPI2C_HostRequestPinActiveHigh;
0394  * endcode
0395  *
0396  * After calling this function, you can override any settings in order to customize the configuration,
0397  * prior to initializing the master driver with LPI2C_MasterInit().
0398  *
0399  * param[out] masterConfig User provided configuration structure for default values. Refer to #lpi2c_master_config_t.
0400  */
0401 void LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t *masterConfig)
0402 {
0403     /* Initializes the configure structure to zero. */
0404     (void)memset(masterConfig, 0, sizeof(*masterConfig));
0405 
0406     masterConfig->enableMaster            = true;
0407     masterConfig->debugEnable             = false;
0408     masterConfig->enableDoze              = true;
0409     masterConfig->ignoreAck               = false;
0410     masterConfig->pinConfig               = kLPI2C_2PinOpenDrain;
0411     masterConfig->baudRate_Hz             = 100000U;
0412     masterConfig->busIdleTimeout_ns       = 0U; /* Set to 0 to disable the function */
0413     masterConfig->pinLowTimeout_ns        = 0U; /* Set to 0 to disable the function */
0414     masterConfig->sdaGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
0415     masterConfig->sclGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
0416     masterConfig->hostRequest.enable      = false;
0417     masterConfig->hostRequest.source      = kLPI2C_HostRequestExternalPin;
0418     masterConfig->hostRequest.polarity    = kLPI2C_HostRequestPinActiveHigh;
0419 }
0420 
0421 /*!
0422  * brief Initializes the LPI2C master peripheral.
0423  *
0424  * This function enables the peripheral clock and initializes the LPI2C master peripheral as described by the user
0425  * provided configuration. A software reset is performed prior to configuration.
0426  *
0427  * param base The LPI2C peripheral base address.
0428  * param masterConfig User provided peripheral configuration. Use LPI2C_MasterGetDefaultConfig() to get a set of
0429  * defaults
0430  *      that you can override.
0431  * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the baud rate divisors,
0432  *      filter widths, and timeout periods.
0433  */
0434 void LPI2C_MasterInit(LPI2C_Type *base, const lpi2c_master_config_t *masterConfig, uint32_t sourceClock_Hz)
0435 {
0436     uint32_t prescaler;
0437     uint32_t cycles;
0438     uint32_t cfgr2;
0439     uint32_t value;
0440 
0441 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0442 
0443     uint32_t instance = LPI2C_GetInstance(base);
0444 
0445     /* Ungate the clock. */
0446     (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
0447 #if defined(LPI2C_PERIPH_CLOCKS)
0448     /* Ungate the functional clock in initialize function. */
0449     CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
0450 #endif
0451 
0452 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0453 
0454     /* Reset peripheral before configuring it. */
0455     LPI2C_MasterReset(base);
0456 
0457     /* Doze bit: 0 is enable, 1 is disable */
0458     base->MCR = LPI2C_MCR_DBGEN(masterConfig->debugEnable) | LPI2C_MCR_DOZEN(!(masterConfig->enableDoze));
0459 
0460     /* host request */
0461     value = base->MCFGR0;
0462     value &= (~(LPI2C_MCFGR0_HREN_MASK | LPI2C_MCFGR0_HRPOL_MASK | LPI2C_MCFGR0_HRSEL_MASK));
0463     value |= LPI2C_MCFGR0_HREN(masterConfig->hostRequest.enable) |
0464              LPI2C_MCFGR0_HRPOL(masterConfig->hostRequest.polarity) |
0465              LPI2C_MCFGR0_HRSEL(masterConfig->hostRequest.source);
0466     base->MCFGR0 = value;
0467 
0468     /* pin config and ignore ack */
0469     value = base->MCFGR1;
0470     value &= ~(LPI2C_MCFGR1_PINCFG_MASK | LPI2C_MCFGR1_IGNACK_MASK);
0471     value |= LPI2C_MCFGR1_PINCFG(masterConfig->pinConfig);
0472     value |= LPI2C_MCFGR1_IGNACK(masterConfig->ignoreAck);
0473     base->MCFGR1 = value;
0474 
0475     LPI2C_MasterSetWatermarks(base, (size_t)kDefaultTxWatermark, (size_t)kDefaultRxWatermark);
0476 
0477     /* Configure glitch filters. */
0478     cfgr2 = base->MCFGR2;
0479     if (0U != (masterConfig->sdaGlitchFilterWidth_ns))
0480     {
0481         /* Calculate SDA filter width. The width is equal to FILTSDA cycles of functional clock.
0482            And set FILTSDA to 0 disables the fileter, so the min value is 1. */
0483         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sdaGlitchFilterWidth_ns, 1U,
0484                                          (LPI2C_MCFGR2_FILTSDA_MASK >> LPI2C_MCFGR2_FILTSDA_SHIFT), 0U);
0485         cfgr2 &= ~LPI2C_MCFGR2_FILTSDA_MASK;
0486         cfgr2 |= LPI2C_MCFGR2_FILTSDA(cycles);
0487     }
0488     if (0U != masterConfig->sclGlitchFilterWidth_ns)
0489     {
0490         /* Calculate SDL filter width. The width is equal to FILTSCL cycles of functional clock.
0491            And set FILTSCL to 0 disables the fileter, so the min value is 1. */
0492         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sclGlitchFilterWidth_ns, 1U,
0493                                          (LPI2C_MCFGR2_FILTSCL_MASK >> LPI2C_MCFGR2_FILTSCL_SHIFT), 0U);
0494         cfgr2 &= ~LPI2C_MCFGR2_FILTSCL_MASK;
0495         cfgr2 |= LPI2C_MCFGR2_FILTSCL(cycles);
0496     }
0497     base->MCFGR2 = cfgr2;
0498 
0499     /* Configure baudrate after the SDA/SCL glitch filter setting,
0500        since the baudrate calculation needs them as parameter. */
0501     LPI2C_MasterSetBaudRate(base, sourceClock_Hz, masterConfig->baudRate_Hz);
0502 
0503     /* Configure bus idle and pin low timeouts after baudrate setting,
0504        since the timeout calculation needs prescaler as parameter. */
0505     prescaler = (base->MCFGR1 & LPI2C_MCFGR1_PRESCALE_MASK) >> LPI2C_MCFGR1_PRESCALE_SHIFT;
0506 
0507     if (0U != (masterConfig->busIdleTimeout_ns))
0508     {
0509         /* Calculate bus idle timeout value. The value is equal to BUSIDLE cycles of functional clock divided by
0510            prescaler. And set BUSIDLE to 0 disables the fileter, so the min value is 1. */
0511         cycles       = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->busIdleTimeout_ns, 1U,
0512                                          (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
0513         base->MCFGR2 = (base->MCFGR2 & (~LPI2C_MCFGR2_BUSIDLE_MASK)) | LPI2C_MCFGR2_BUSIDLE(cycles);
0514     }
0515     if (0U != masterConfig->pinLowTimeout_ns)
0516     {
0517         /* Calculate bus pin low timeout value. The value is equal to PINLOW cycles of functional clock divided by
0518            prescaler. And set PINLOW to 0 disables the fileter, so the min value is 1. */
0519         cycles       = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->pinLowTimeout_ns / 256U, 1U,
0520                                          (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
0521         base->MCFGR3 = (base->MCFGR3 & ~LPI2C_MCFGR3_PINLOW_MASK) | LPI2C_MCFGR3_PINLOW(cycles);
0522     }
0523 
0524     LPI2C_MasterEnable(base, masterConfig->enableMaster);
0525 }
0526 
0527 /*!
0528  * brief Deinitializes the LPI2C master peripheral.
0529  *
0530  * This function disables the LPI2C master peripheral and gates the clock. It also performs a software
0531  * reset to restore the peripheral to reset conditions.
0532  *
0533  * param base The LPI2C peripheral base address.
0534  */
0535 void LPI2C_MasterDeinit(LPI2C_Type *base)
0536 {
0537     /* Restore to reset state. */
0538     LPI2C_MasterReset(base);
0539 
0540 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0541 
0542     uint32_t instance = LPI2C_GetInstance(base);
0543 
0544     /* Gate clock. */
0545     (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
0546 #if defined(LPI2C_PERIPH_CLOCKS)
0547     /* Gate the functional clock. */
0548     CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
0549 #endif
0550 
0551 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0552 }
0553 
0554 /*!
0555  * brief Configures LPI2C master data match feature.
0556  *
0557  * param base The LPI2C peripheral base address.
0558  * param matchConfig Settings for the data match feature.
0559  */
0560 void LPI2C_MasterConfigureDataMatch(LPI2C_Type *base, const lpi2c_data_match_config_t *matchConfig)
0561 {
0562     /* Disable master mode. */
0563     bool wasEnabled = (0U != ((base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT));
0564     LPI2C_MasterEnable(base, false);
0565 
0566     base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_MATCFG_MASK) | LPI2C_MCFGR1_MATCFG(matchConfig->matchMode);
0567     base->MCFGR0 = (base->MCFGR0 & ~LPI2C_MCFGR0_RDMO_MASK) | LPI2C_MCFGR0_RDMO(matchConfig->rxDataMatchOnly);
0568     base->MDMR   = LPI2C_MDMR_MATCH0(matchConfig->match0) | LPI2C_MDMR_MATCH1(matchConfig->match1);
0569 
0570     /* Restore master mode. */
0571     if (wasEnabled)
0572     {
0573         LPI2C_MasterEnable(base, true);
0574     }
0575 }
0576 
0577 /*!
0578  * brief Sets the I2C bus frequency for master transactions.
0579  *
0580  * The LPI2C master is automatically disabled and re-enabled as necessary to configure the baud
0581  * rate. Do not call this function during a transfer, or the transfer is aborted.
0582  *
0583  * note Please note that the second parameter is the clock frequency of LPI2C module, the third
0584  * parameter means user configured bus baudrate, this implementation is different from other I2C drivers
0585  * which use baudrate configuration as second parameter and source clock frequency as third parameter.
0586  *
0587  * param base The LPI2C peripheral base address.
0588  * param sourceClock_Hz LPI2C functional clock frequency in Hertz.
0589  * param baudRate_Hz Requested bus frequency in Hertz.
0590  */
0591 void LPI2C_MasterSetBaudRate(LPI2C_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Hz)
0592 {
0593     bool wasEnabled;
0594     uint8_t filtScl = (uint8_t)((base->MCFGR2 & LPI2C_MCFGR2_FILTSCL_MASK) >> LPI2C_MCFGR2_FILTSCL_SHIFT);
0595 
0596     uint8_t divider     = 1U;
0597     uint8_t bestDivider = 1U;
0598     uint8_t prescale    = 0U;
0599     uint8_t bestPre     = 0U;
0600 
0601     uint8_t clkCycle;
0602     uint8_t bestclkCycle = 0U;
0603 
0604     uint32_t absError  = 0U;
0605     uint32_t bestError = 0xffffffffu;
0606     uint32_t computedRate;
0607 
0608     uint32_t tmpReg = 0U;
0609 
0610     /* Disable master mode. */
0611     wasEnabled = (0U != ((base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT));
0612     LPI2C_MasterEnable(base, false);
0613 
0614     /* Baud rate = (sourceClock_Hz / 2 ^ prescale) / (CLKLO + 1 + CLKHI + 1 + SCL_LATENCY)
0615      * SCL_LATENCY = ROUNDDOWN((2 + FILTSCL) / (2 ^ prescale))
0616      */
0617     for (prescale = 0U; prescale <= 7U; prescale++)
0618     {
0619         /* Calculate the clkCycle, clkCycle = CLKLO + CLKHI, divider = 2 ^ prescale */
0620         clkCycle = (uint8_t)((10U * sourceClock_Hz / divider / baudRate_Hz + 5U) / 10U - (2U + filtScl) / divider - 2U);
0621         /* According to register description, The max value for CLKLO and CLKHI is 63.
0622            however to meet the I2C specification of tBUF, CLKHI should be less than
0623            clkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / divider + 1U. Refer to the comment of the tmpHigh's
0624            calculation for details. So we have:
0625            CLKHI < clkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / divider + 1U,
0626            clkCycle = CLKHI + CLKLO and
0627            sourceClock_Hz / baudRate_Hz / divider = clkCycle + 2 + ROUNDDOWN((2 + FILTSCL) / divider),
0628            we can come up with: CLKHI < 0.92 x CLKLO - ROUNDDOWN(2 + FILTSCL) / divider
0629            so the max boundary of CLKHI should be 0.92 x 63 - ROUNDDOWN(2 + FILTSCL) / divider,
0630            and the max boundary of clkCycle is 1.92 x 63 - ROUNDDOWN(2 + FILTSCL) / divider. */
0631         if (clkCycle > (120U - (2U + filtScl) / divider))
0632         {
0633             divider *= 2U;
0634             continue;
0635         }
0636         /* Calculate the computed baudrate and compare it with the desired baudrate */
0637         computedRate = (sourceClock_Hz / (uint32_t)divider) /
0638                        ((uint32_t)clkCycle + 2U + (2U + (uint32_t)filtScl) / (uint32_t)divider);
0639         absError = baudRate_Hz > computedRate ? baudRate_Hz - computedRate : computedRate - baudRate_Hz;
0640         if (absError < bestError)
0641         {
0642             bestPre      = prescale;
0643             bestDivider  = divider;
0644             bestclkCycle = clkCycle;
0645             bestError    = absError;
0646 
0647             /* If the error is 0, then we can stop searching because we won't find a better match. */
0648             if (absError == 0U)
0649             {
0650                 break;
0651             }
0652         }
0653         divider *= 2U;
0654     }
0655 
0656     /* SCL low time tLO should be larger than or equal to SCL high time tHI:
0657        tLO = ((CLKLO + 1) x (2 ^ PRESCALE)) >= tHI = ((CLKHI + 1 + SCL_LATENCY) x (2 ^ PRESCALE)),
0658        which is CLKLO >= CLKHI + (2U + filtScl) / bestDivider.
0659        Also since bestclkCycle = CLKLO + CLKHI, bestDivider = 2 ^ PRESCALE
0660        which makes CLKHI <= (bestclkCycle - (2U + filtScl) / bestDivider) / 2U.
0661 
0662        The max tBUF should be at least 0.52 times of the SCL clock cycle:
0663        tBUF = ((CLKLO + 1) x (2 ^ PRESCALE) / sourceClock_Hz) > (0.52 / baudRate_Hz),
0664        plus bestDivider = 2 ^ PRESCALE, bestclkCycle = CLKLO + CLKHI we can come up with
0665        CLKHI <= (bestclkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / bestDivider + 1U).
0666        In this case to get a safe CLKHI calculation, we can assume:
0667     */
0668     uint8_t tmpHigh = (bestclkCycle - (2U + filtScl) / bestDivider) / 2U;
0669     while (tmpHigh > (bestclkCycle - 52U * sourceClock_Hz / baudRate_Hz / bestDivider / 100U + 1U))
0670     {
0671         tmpHigh = tmpHigh - 1U;
0672     }
0673 
0674     /* Calculate DATAVD and SETHOLD.
0675        To meet the timing requirement of I2C spec for standard mode, fast mode and fast mode plus: */
0676     /* 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:
0677        tHD:STA = ((SETHOLD + 1) x (2 ^ PRESCALE) / sourceClock_Hz) > (0.5 / baudRate_Hz), bestDivider = 2 ^ PRESCALE */
0678     uint8_t tmpHold = (uint8_t)(sourceClock_Hz / baudRate_Hz / bestDivider / 2U) - 1U;
0679 
0680     /* 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:
0681        tVD:DAT = ((DATAVD + 1) x (2 ^ PRESCALE) / sourceClock_Hz) < (0.25 / baudRate_Hz), bestDivider = 2 ^ PRESCALE */
0682     uint8_t tmpDataVd = (uint8_t)(sourceClock_Hz / baudRate_Hz / bestDivider / 4U) - 1U;
0683 
0684     /* The min tSU:DAT should be at least 0.05 times of the SCL clock cycle:
0685        tSU:DAT = ((2 + FILTSDA + 2 ^ PRESCALE) / sourceClock_Hz) >= (0.05 / baud),
0686        plus bestDivider = 2 ^ PRESCALE, we can come up with:
0687        FILTSDA >= (0.05 x sourceClock_Hz / baudRate_Hz - bestDivider - 2) */
0688     if ((sourceClock_Hz / baudRate_Hz / 20U) > (bestDivider + 2U))
0689     {
0690         /* Read out the FILTSDA configuration, if it is smaller than expected, change the setting. */
0691         uint8_t filtSda = (uint8_t)((base->MCFGR2 & LPI2C_MCFGR2_FILTSDA_MASK) >> LPI2C_MCFGR2_FILTSDA_SHIFT);
0692         if (filtSda < (sourceClock_Hz / baudRate_Hz / 20U - bestDivider - 2U))
0693         {
0694             filtSda = (uint8_t)(sourceClock_Hz / baudRate_Hz / 20U) - bestDivider - 2U;
0695         }
0696         base->MCFGR2 = (base->MCFGR2 & ~LPI2C_MCFGR2_FILTSDA_MASK) | LPI2C_MCFGR2_FILTSDA(filtSda);
0697     }
0698 
0699     /* Set CLKHI, CLKLO, SETHOLD, DATAVD value. */
0700     tmpReg = LPI2C_MCCR0_CLKHI((uint32_t)tmpHigh) |
0701              LPI2C_MCCR0_CLKLO((uint32_t)((uint32_t)bestclkCycle - (uint32_t)tmpHigh)) |
0702              LPI2C_MCCR0_SETHOLD((uint32_t)tmpHold) | LPI2C_MCCR0_DATAVD((uint32_t)tmpDataVd);
0703     base->MCCR0 = tmpReg;
0704 
0705     /* Set PRESCALE value. */
0706     base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_PRESCALE_MASK) | LPI2C_MCFGR1_PRESCALE(bestPre);
0707 
0708     /* Restore master mode. */
0709     if (wasEnabled)
0710     {
0711         LPI2C_MasterEnable(base, true);
0712     }
0713 }
0714 
0715 /*!
0716  * brief Sends a START signal and slave address on the I2C bus.
0717  *
0718  * This function is used to initiate a new master mode transfer. First, the bus state is checked to ensure
0719  * that another master is not occupying the bus. Then a START signal is transmitted, followed by the
0720  * 7-bit address specified in the a address parameter. Note that this function does not actually wait
0721  * until the START and address are successfully sent on the bus before returning.
0722  *
0723  * param base The LPI2C peripheral base address.
0724  * param address 7-bit slave device address, in bits [6:0].
0725  * param dir Master transfer direction, either #kLPI2C_Read or #kLPI2C_Write. This parameter is used to set
0726  *      the R/w bit (bit 0) in the transmitted slave address.
0727  * retval #kStatus_Success START signal and address were successfully enqueued in the transmit FIFO.
0728  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
0729  */
0730 status_t LPI2C_MasterStart(LPI2C_Type *base, uint8_t address, lpi2c_direction_t dir)
0731 {
0732     /* Return an error if the bus is already in use not by us. */
0733     status_t result = LPI2C_CheckForBusyBus(base);
0734     if (kStatus_Success == result)
0735     {
0736         /* Clear all flags. */
0737         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
0738 
0739         /* Turn off auto-stop option. */
0740         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
0741 
0742         /* Wait until there is room in the fifo. */
0743         result = LPI2C_MasterWaitForTxReady(base);
0744         if (kStatus_Success == result)
0745         {
0746             /* Issue start command. */
0747             base->MTDR = (uint32_t)kStartCmd | (((uint32_t)address << 1U) | (uint32_t)dir);
0748         }
0749     }
0750 
0751     return result;
0752 }
0753 
0754 /*!
0755  * brief Sends a STOP signal on the I2C bus.
0756  *
0757  * This function does not return until the STOP signal is seen on the bus, or an error occurs.
0758  *
0759  * param base The LPI2C peripheral base address.
0760  * retval #kStatus_Success The STOP signal was successfully sent on the bus and the transaction terminated.
0761  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
0762  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
0763  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
0764  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
0765  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
0766  */
0767 status_t LPI2C_MasterStop(LPI2C_Type *base)
0768 {
0769     /* Wait until there is room in the fifo. */
0770     status_t result = LPI2C_MasterWaitForTxReady(base);
0771     if (kStatus_Success == result)
0772     {
0773         /* Send the STOP signal */
0774         base->MTDR = (uint32_t)kStopCmd;
0775 
0776         /* Wait for the stop detected flag to set, indicating the transfer has completed on the bus. */
0777         /* Also check for errors while waiting. */
0778 #if I2C_RETRY_TIMES != 0U
0779         uint32_t waitTimes = I2C_RETRY_TIMES;
0780 #endif
0781 
0782 #if I2C_RETRY_TIMES != 0U
0783         while ((result == kStatus_Success) && (0U != waitTimes))
0784         {
0785             waitTimes--;
0786 #else
0787         while (result == kStatus_Success)
0788         {
0789 #endif
0790             uint32_t status = LPI2C_MasterGetStatusFlags(base);
0791 
0792             /* Check for error flags. */
0793             result = LPI2C_MasterCheckAndClearError(base, status);
0794 
0795             /* Check if the stop was sent successfully. */
0796             if ((0U != (status & (uint32_t)kLPI2C_MasterStopDetectFlag)) &&
0797                 (0U != (status & (uint32_t)kLPI2C_MasterTxReadyFlag)))
0798             {
0799                 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterStopDetectFlag);
0800                 break;
0801             }
0802         }
0803 
0804 #if I2C_RETRY_TIMES != 0U
0805         if (0U == waitTimes)
0806         {
0807             result = kStatus_LPI2C_Timeout;
0808         }
0809 #endif
0810     }
0811 
0812     return result;
0813 }
0814 
0815 /*!
0816  * brief Performs a polling receive transfer on the I2C bus.
0817  *
0818  * param base  The LPI2C peripheral base address.
0819  * param rxBuff The pointer to the data to be transferred.
0820  * param rxSize The length in bytes of the data to be transferred.
0821  * retval #kStatus_Success Data was received successfully.
0822  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
0823  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
0824  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
0825  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
0826  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
0827  */
0828 status_t LPI2C_MasterReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize)
0829 {
0830     assert(NULL != rxBuff);
0831 
0832     status_t result = kStatus_Success;
0833     uint8_t *buf;
0834     size_t tmpRxSize = rxSize;
0835 #if I2C_RETRY_TIMES != 0U
0836     uint32_t waitTimes;
0837 #endif
0838 
0839     /* Check transfer data size. */
0840     if (rxSize > ((size_t)256 * (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base)))
0841     {
0842         return kStatus_InvalidArgument;
0843     }
0844 
0845     /* Handle empty read. */
0846     if (rxSize != 0U)
0847     {
0848         /* Wait until there is room in the command fifo. */
0849         result = LPI2C_MasterWaitForTxReady(base);
0850         if (kStatus_Success == result)
0851         {
0852             /* Issue command to receive data. A single write to MTDR can issue read operation of 0xFFU + 1 byte of data
0853                at most, so when the rxSize is larger than 0x100U, push multiple read commands to MTDR until rxSize is
0854                reached. */
0855             while (tmpRxSize != 0U)
0856             {
0857                 if (tmpRxSize > 256U)
0858                 {
0859                     base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
0860                     tmpRxSize -= 256U;
0861                 }
0862                 else
0863                 {
0864                     base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
0865                     tmpRxSize  = 0U;
0866                 }
0867             }
0868 
0869             /* Receive data */
0870             buf = (uint8_t *)rxBuff;
0871             while (0U != (rxSize--))
0872             {
0873 #if I2C_RETRY_TIMES != 0U
0874                 waitTimes = I2C_RETRY_TIMES;
0875 #endif
0876                 /* Read LPI2C receive fifo register. The register includes a flag to indicate whether */
0877                 /* the FIFO is empty, so we can both get the data and check if we need to keep reading */
0878                 /* using a single register read. */
0879                 uint32_t value = 0U;
0880                 do
0881                 {
0882                     /* Check for errors. */
0883                     result = LPI2C_MasterCheckAndClearError(base, LPI2C_MasterGetStatusFlags(base));
0884                     if (kStatus_Success != result)
0885                     {
0886                         break;
0887                     }
0888 
0889                     value = base->MRDR;
0890 #if I2C_RETRY_TIMES != 0U
0891                     waitTimes--;
0892                 } while ((0U != (value & LPI2C_MRDR_RXEMPTY_MASK)) && (0U != waitTimes));
0893                 if (0U == waitTimes)
0894                 {
0895                     result = kStatus_LPI2C_Timeout;
0896                 }
0897 #else
0898                 } while (0U != (value & LPI2C_MRDR_RXEMPTY_MASK));
0899 #endif
0900                 if ((status_t)kStatus_Success != result)
0901                 {
0902                     break;
0903                 }
0904 
0905                 *buf++ = (uint8_t)(value & LPI2C_MRDR_DATA_MASK);
0906             }
0907         }
0908     }
0909 
0910     return result;
0911 }
0912 
0913 /*!
0914  * brief Performs a polling send transfer on the I2C bus.
0915  *
0916  * Sends up to a txSize number of bytes to the previously addressed slave device. The slave may
0917  * reply with a NAK to any byte in order to terminate the transfer early. If this happens, this
0918  * function returns #kStatus_LPI2C_Nak.
0919  *
0920  * param base  The LPI2C peripheral base address.
0921  * param txBuff The pointer to the data to be transferred.
0922  * param txSize The length in bytes of the data to be transferred.
0923  * retval #kStatus_Success Data was sent successfully.
0924  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
0925  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
0926  * retval #kStatus_LPI2C_FifoError FIFO under run or over run.
0927  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
0928  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
0929  */
0930 status_t LPI2C_MasterSend(LPI2C_Type *base, void *txBuff, size_t txSize)
0931 {
0932     status_t result = kStatus_Success;
0933     uint8_t *buf    = (uint8_t *)txBuff;
0934 
0935     assert(NULL != txBuff);
0936 
0937     /* Send data buffer */
0938     while (0U != (txSize--))
0939     {
0940         /* Wait until there is room in the fifo. This also checks for errors. */
0941         result = LPI2C_MasterWaitForTxReady(base);
0942         if (kStatus_Success != result)
0943         {
0944             break;
0945         }
0946 
0947         /* Write byte into LPI2C master data register. */
0948         base->MTDR = *buf++;
0949     }
0950 
0951     return result;
0952 }
0953 
0954 /*!
0955  * brief Performs a master polling transfer on the I2C bus.
0956  *
0957  * note The API does not return until the transfer succeeds or fails due
0958  * to error happens during transfer.
0959  *
0960  * param base The LPI2C peripheral base address.
0961  * param transfer Pointer to the transfer structure.
0962  * retval #kStatus_Success Data was received successfully.
0963  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
0964  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
0965  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
0966  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
0967  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
0968  */
0969 status_t LPI2C_MasterTransferBlocking(LPI2C_Type *base, lpi2c_master_transfer_t *transfer)
0970 {
0971     assert(NULL != transfer);
0972     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
0973 
0974     status_t result = kStatus_Success;
0975     uint16_t commandBuffer[7];
0976     uint32_t cmdCount = 0U;
0977 
0978     /* Check transfer data size in read operation. */
0979     if ((transfer->direction == kLPI2C_Read) &&
0980         (transfer->dataSize > ((size_t)256 * (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
0981     {
0982         return kStatus_InvalidArgument;
0983     }
0984 
0985     /* Enable the master function and disable the slave function. */
0986     LPI2C_MasterEnable(base, true);
0987     LPI2C_SlaveEnable(base, false);
0988 
0989     /* Return an error if the bus is already in use not by us. */
0990     result = LPI2C_CheckForBusyBus(base);
0991     if (kStatus_Success == result)
0992     {
0993         /* Clear all flags. */
0994         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
0995 
0996         /* Turn off auto-stop option. */
0997         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
0998 
0999         lpi2c_direction_t direction = (0U != transfer->subaddressSize) ? kLPI2C_Write : transfer->direction;
1000         if (0U == (transfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1001         {
1002             commandBuffer[cmdCount++] =
1003                 (uint16_t)kStartCmd |
1004                 (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)direction);
1005         }
1006 
1007         /* Subaddress, MSB first. */
1008         if (0U != transfer->subaddressSize)
1009         {
1010             uint32_t subaddressRemaining = transfer->subaddressSize;
1011             while (0U != subaddressRemaining--)
1012             {
1013                 uint8_t subaddressByte    = (uint8_t)((transfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1014                 commandBuffer[cmdCount++] = subaddressByte;
1015             }
1016         }
1017 
1018         /* Reads need special handling. */
1019         if ((0U != transfer->dataSize) && (transfer->direction == kLPI2C_Read))
1020         {
1021             /* Need to send repeated start if switching directions to read. */
1022             if (direction == kLPI2C_Write)
1023             {
1024                 commandBuffer[cmdCount++] =
1025                     (uint16_t)kStartCmd |
1026                     (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1027             }
1028         }
1029 
1030         /* Send command buffer */
1031         uint32_t index = 0U;
1032         while (0U != cmdCount--)
1033         {
1034             /* Wait until there is room in the fifo. This also checks for errors. */
1035             result = LPI2C_MasterWaitForTxReady(base);
1036             if (kStatus_Success != result)
1037             {
1038                 break;
1039             }
1040 
1041             /* Write byte into LPI2C master data register. */
1042             base->MTDR = commandBuffer[index];
1043             index++;
1044         }
1045 
1046         if (kStatus_Success == result)
1047         {
1048             /* Transmit data. */
1049             if ((transfer->direction == kLPI2C_Write) && (transfer->dataSize > 0U))
1050             {
1051                 /* Send Data. */
1052                 result = LPI2C_MasterSend(base, transfer->data, transfer->dataSize);
1053             }
1054 
1055             /* Receive Data. */
1056             if ((transfer->direction == kLPI2C_Read) && (transfer->dataSize > 0U))
1057             {
1058                 result = LPI2C_MasterReceive(base, transfer->data, transfer->dataSize);
1059             }
1060 
1061             if (kStatus_Success == result)
1062             {
1063                 if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1064                 {
1065                     result = LPI2C_MasterStop(base);
1066                 }
1067             }
1068         }
1069     }
1070 
1071     return result;
1072 }
1073 
1074 /*!
1075  * brief Creates a new handle for the LPI2C master non-blocking APIs.
1076  *
1077  * The creation of a handle is for use with the non-blocking APIs. Once a handle
1078  * is created, there is not a corresponding destroy handle. If the user wants to
1079  * terminate a transfer, the LPI2C_MasterTransferAbort() API shall be called.
1080  *
1081  *
1082  * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
1083  * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
1084  * enable the associated INTMUX IRQ in application.
1085  *
1086  * param base The LPI2C peripheral base address.
1087  * param[out] handle Pointer to the LPI2C master driver handle.
1088  * param callback User provided pointer to the asynchronous callback function.
1089  * param userData User provided pointer to the application callback data.
1090  */
1091 void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
1092                                       lpi2c_master_handle_t *handle,
1093                                       lpi2c_master_transfer_callback_t callback,
1094                                       void *userData)
1095 {
1096     uint32_t instance;
1097 
1098     assert(NULL != handle);
1099 
1100     /* Clear out the handle. */
1101     (void)memset(handle, 0, sizeof(*handle));
1102 
1103     /* Look up instance number */
1104     instance = LPI2C_GetInstance(base);
1105 
1106     /* Save base and instance. */
1107     handle->completionCallback = callback;
1108     handle->userData           = userData;
1109 
1110     /* Save this handle for IRQ use. */
1111     s_lpi2cMasterHandle[instance] = handle;
1112 
1113     /* Set irq handler. */
1114     s_lpi2cMasterIsr = LPI2C_MasterTransferHandleIRQ;
1115 
1116     /* Clear internal IRQ enables and enable NVIC IRQ. */
1117     LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1118 
1119     /* Enable NVIC IRQ, this only enables the IRQ directly connected to the NVIC.
1120      In some cases the LPI2C IRQ is configured through INTMUX, user needs to enable
1121      INTMUX IRQ in application code. */
1122     (void)EnableIRQ(kLpi2cIrqs[instance]);
1123 }
1124 
1125 static void LPI2C_TransferStateMachineSendCommand(LPI2C_Type *base,
1126                                                   lpi2c_master_handle_t *handle,
1127                                                   lpi2c_state_machine_param_t *stateParams)
1128 {
1129     assert(stateParams != NULL);
1130     uint16_t sendval;
1131 
1132     /* Make sure there is room in the tx fifo for the next command. */
1133     if (0U == (stateParams->txCount)--)
1134     {
1135         stateParams->state_complete = true;
1136         return;
1137     }
1138 
1139     /* Issue command. buf is a uint8_t* pointing at the uint16 command array. */
1140     sendval    = ((uint16_t)handle->buf[0]) | (((uint16_t)handle->buf[1]) << 8U);
1141     base->MTDR = sendval;
1142     handle->buf++;
1143     handle->buf++;
1144 
1145     /* Count down until all commands are sent. */
1146     if (--handle->remainingBytes == 0U)
1147     {
1148         /* Choose next state and set up buffer pointer and count. */
1149         if (0U != handle->transfer.dataSize)
1150         {
1151             /* Either a send or receive transfer is next. */
1152             handle->state          = (uint8_t)kTransferDataState;
1153             handle->buf            = (uint8_t *)handle->transfer.data;
1154             handle->remainingBytes = (uint16_t)handle->transfer.dataSize;
1155             if (handle->transfer.direction == kLPI2C_Read)
1156             {
1157                 /* Disable TX interrupt */
1158                 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1159                 /* Issue command to receive data. A single write to MTDR can issue read operation of
1160                     0xFFU + 1 byte of data at most, so when the dataSize is larger than 0x100U, push
1161                     multiple read commands to MTDR until dataSize is reached. */
1162                 size_t tmpRxSize = handle->transfer.dataSize;
1163                 while (tmpRxSize != 0U)
1164                 {
1165                     LPI2C_MasterGetFifoCounts(base, NULL, &stateParams->txCount);
1166                     while ((size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base) == stateParams->txCount)
1167                     {
1168                         LPI2C_MasterGetFifoCounts(base, NULL, &stateParams->txCount);
1169                     }
1170 
1171                     if (tmpRxSize > 256U)
1172                     {
1173                         base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
1174                         tmpRxSize -= 256U;
1175                     }
1176                     else
1177                     {
1178                         base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
1179                         tmpRxSize  = 0U;
1180                     }
1181                 }
1182             }
1183         }
1184         else
1185         {
1186             /* No transfer, so move to stop state. */
1187             handle->state = (uint8_t)kStopState;
1188         }
1189     }
1190 }
1191 
1192 static void LPI2C_TransferStateMachineReadCommand(LPI2C_Type *base,
1193                                                   lpi2c_master_handle_t *handle,
1194                                                   lpi2c_state_machine_param_t *stateParams)
1195 {
1196     assert(stateParams != NULL);
1197 
1198     /* Make sure there is room in the tx fifo for the read command. */
1199     if (0U == (stateParams->txCount)--)
1200     {
1201         stateParams->state_complete = true;
1202         return;
1203     }
1204 
1205     base->MTDR = (uint32_t)kRxDataCmd | LPI2C_MTDR_DATA(handle->transfer.dataSize - 1U);
1206 
1207     /* Move to transfer state. */
1208     handle->state = (uint8_t)kTransferDataState;
1209     if (handle->transfer.direction == kLPI2C_Read)
1210     {
1211         /* Disable TX interrupt */
1212         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1213     }
1214 }
1215 
1216 static void LPI2C_TransferStateMachineTransferData(LPI2C_Type *base,
1217                                                    lpi2c_master_handle_t *handle,
1218                                                    lpi2c_state_machine_param_t *stateParams)
1219 {
1220     assert(stateParams != NULL);
1221 
1222     if (handle->transfer.direction == kLPI2C_Write)
1223     {
1224         /* Make sure there is room in the tx fifo. */
1225         if (0U == stateParams->txCount--)
1226         {
1227             stateParams->state_complete = true;
1228             return;
1229         }
1230 
1231         /* Put byte to send in fifo. */
1232         base->MTDR = *(handle->buf)++;
1233     }
1234     else
1235     {
1236         /* XXX handle receive sizes > 256, use kIssueReadCommandState */
1237         /* Make sure there is data in the rx fifo. */
1238         if (0U == stateParams->rxCount--)
1239         {
1240             stateParams->state_complete = true;
1241             return;
1242         }
1243 
1244         /* Read byte from fifo. */
1245         *(handle->buf)++ = (uint8_t)(base->MRDR & LPI2C_MRDR_DATA_MASK);
1246     }
1247 
1248     /* Move to stop when the transfer is done. */
1249     if (--handle->remainingBytes == 0U)
1250     {
1251         if (handle->transfer.direction == kLPI2C_Write)
1252         {
1253             stateParams->state_complete = true;
1254         }
1255         handle->state = (uint8_t)kStopState;
1256     }
1257 }
1258 
1259 static void LPI2C_TransferStateMachineStopState(LPI2C_Type *base,
1260                                                 lpi2c_master_handle_t *handle,
1261                                                 lpi2c_state_machine_param_t *stateParams,
1262                                                 bool *isDone)
1263 {
1264     assert(stateParams != NULL);
1265 
1266     /* Only issue a stop transition if the caller requested it. */
1267     if ((handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1268     {
1269         /* Make sure there is room in the tx fifo for the stop command. */
1270         if (0U == (stateParams->txCount)--)
1271         {
1272             stateParams->state_complete = true;
1273             return;
1274         }
1275 
1276         base->MTDR = (uint32_t)kStopCmd;
1277     }
1278     else
1279     {
1280         /* If all data is read and no stop flag is required to send, we are done. */
1281         if (handle->transfer.direction == kLPI2C_Read)
1282         {
1283             *isDone = true;
1284         }
1285         stateParams->state_complete = true;
1286     }
1287     handle->state = (uint8_t)kWaitForCompletionState;
1288 }
1289 
1290 static void LPI2C_TransferStateMachineWaitState(LPI2C_Type *base,
1291                                                 lpi2c_master_handle_t *handle,
1292                                                 lpi2c_state_machine_param_t *stateParams,
1293                                                 bool *isDone)
1294 {
1295     assert(stateParams != NULL);
1296 
1297     if ((handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1298     {
1299         /* We stay in this state until the stop state is detected. */
1300         if (0U != ((stateParams->status) & (uint32_t)kLPI2C_MasterStopDetectFlag))
1301         {
1302             *isDone = true;
1303         }
1304     }
1305     else
1306     {
1307         /* If all data is pushed to FIFO and no stop flag is required to send, we need to make sure they
1308             are all send out to bus. */
1309         if ((handle->transfer.direction == kLPI2C_Write) && ((base->MFSR & LPI2C_MFSR_TXCOUNT_MASK) == 0U))
1310         {
1311             /* We stay in this state until the data is sent out to bus. */
1312             *isDone = true;
1313         }
1314     }
1315     stateParams->state_complete = true;
1316 }
1317 
1318 /*!
1319  * @brief Execute states until FIFOs are exhausted.
1320  * @param handle Master nonblocking driver handle.
1321  * @param[out] isDone Set to true if the transfer has completed.
1322  * @retval #kStatus_Success
1323  * @retval #kStatus_LPI2C_PinLowTimeout
1324  * @retval #kStatus_LPI2C_ArbitrationLost
1325  * @retval #kStatus_LPI2C_Nak
1326  * @retval #kStatus_LPI2C_FifoError
1327  */
1328 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone)
1329 {
1330     assert(NULL != base && NULL != handle && NULL != isDone);
1331 
1332     status_t result = kStatus_Success;
1333     lpi2c_state_machine_param_t stateParams;
1334     (void)memset(&stateParams, 0, sizeof(stateParams));
1335 
1336     stateParams.state_complete = false;
1337 
1338     /* Set default isDone return value. */
1339     *isDone = false;
1340 
1341     /* Check for errors. */
1342     stateParams.status = LPI2C_MasterGetStatusFlags(base);
1343 
1344     /* Get fifo counts. */
1345     LPI2C_MasterGetFifoCounts(base, &stateParams.rxCount, &stateParams.txCount);
1346 
1347     /* For the last byte, nack flag is expected.
1348        Do not check and clear kLPI2C_MasterNackDetectFlag for the last byte,
1349        in case FIFO is emptied when stop command has not been sent. */
1350     if (handle->remainingBytes == 0U)
1351     {
1352         /* When data size is not zero which means it is not only one byte of address is sent, and */
1353         /* when the txfifo is empty, or have one byte which is the stop command, then the nack status can be ignored. */
1354         if (((handle->transfer).dataSize != 0U) &&
1355             ((stateParams.txCount == 0U) ||
1356              (((stateParams.txCount) == 1U) && (handle->state == (uint8_t)kWaitForCompletionState) &&
1357               (((handle->transfer).flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U))))
1358         {
1359             (stateParams.status) &= ~(uint32_t)kLPI2C_MasterNackDetectFlag;
1360         }
1361     }
1362 
1363     result = LPI2C_MasterCheckAndClearError(base, stateParams.status);
1364 
1365     if (kStatus_Success == result)
1366     {
1367         /* Compute room in tx fifo */
1368         stateParams.txCount = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base) - stateParams.txCount;
1369 
1370         while (!stateParams.state_complete)
1371         {
1372             /* Execute the state. */
1373             switch (handle->state)
1374             {
1375                 case (uint8_t)kSendCommandState:
1376                     LPI2C_TransferStateMachineSendCommand(base, handle, &stateParams);
1377                     break;
1378 
1379                 case (uint8_t)kIssueReadCommandState:
1380                     LPI2C_TransferStateMachineReadCommand(base, handle, &stateParams);
1381                     break;
1382 
1383                 case (uint8_t)kTransferDataState:
1384                     LPI2C_TransferStateMachineTransferData(base, handle, &stateParams);
1385                     break;
1386 
1387                 case (uint8_t)kStopState:
1388                     LPI2C_TransferStateMachineStopState(base, handle, &stateParams, isDone);
1389                     break;
1390 
1391                 case (uint8_t)kWaitForCompletionState:
1392                     LPI2C_TransferStateMachineWaitState(base, handle, &stateParams, isDone);
1393                     break;
1394                 default:
1395                     assert(false);
1396                     break;
1397             }
1398         }
1399     }
1400     return result;
1401 }
1402 
1403 /*!
1404  * @brief Prepares the transfer state machine and fills in the command buffer.
1405  * @param handle Master nonblocking driver handle.
1406  */
1407 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle)
1408 {
1409     lpi2c_master_transfer_t *xfer = &handle->transfer;
1410 
1411     /* Handle no start option. */
1412     if (0U != (xfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1413     {
1414         if (xfer->direction == kLPI2C_Read)
1415         {
1416             /* Need to issue read command first. */
1417             handle->state = (uint8_t)kIssueReadCommandState;
1418         }
1419         else
1420         {
1421             /* Start immediately in the data transfer state. */
1422             handle->state = (uint8_t)kTransferDataState;
1423         }
1424 
1425         handle->buf            = (uint8_t *)xfer->data;
1426         handle->remainingBytes = (uint16_t)xfer->dataSize;
1427     }
1428     else
1429     {
1430         uint16_t *cmd     = (uint16_t *)&handle->commandBuffer;
1431         uint32_t cmdCount = 0U;
1432 
1433         /* Initial direction depends on whether a subaddress was provided, and of course the actual */
1434         /* data transfer direction. */
1435         lpi2c_direction_t direction = (0U != xfer->subaddressSize) ? kLPI2C_Write : xfer->direction;
1436 
1437         /* Start command. */
1438         cmd[cmdCount++] =
1439             (uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
1440 
1441         /* Subaddress, MSB first. */
1442         if (0U != xfer->subaddressSize)
1443         {
1444             uint32_t subaddressRemaining = xfer->subaddressSize;
1445             while (0U != (subaddressRemaining--))
1446             {
1447                 uint8_t subaddressByte = (uint8_t)((xfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1448                 cmd[cmdCount++]        = subaddressByte;
1449             }
1450         }
1451 
1452         /* Reads need special handling. */
1453         if ((0U != xfer->dataSize) && (xfer->direction == kLPI2C_Read))
1454         {
1455             /* Need to send repeated start if switching directions to read. */
1456             if (direction == kLPI2C_Write)
1457             {
1458                 cmd[cmdCount++] = (uint16_t)kStartCmd |
1459                                   (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1460             }
1461         }
1462 
1463         /* Set up state machine for transferring the commands. */
1464         handle->state          = (uint8_t)kSendCommandState;
1465         handle->remainingBytes = (uint16_t)cmdCount;
1466         handle->buf            = (uint8_t *)&handle->commandBuffer;
1467     }
1468 }
1469 
1470 /*!
1471  * brief Performs a non-blocking transaction on the I2C bus.
1472  *
1473  * param base The LPI2C peripheral base address.
1474  * param handle Pointer to the LPI2C master driver handle.
1475  * param transfer The pointer to the transfer descriptor.
1476  * retval #kStatus_Success The transaction was started successfully.
1477  * retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or a non-blocking
1478  *      transaction is already in progress.
1479  */
1480 status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
1481                                          lpi2c_master_handle_t *handle,
1482                                          lpi2c_master_transfer_t *transfer)
1483 {
1484     assert(NULL != handle);
1485     assert(NULL != transfer);
1486     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1487 
1488     status_t result;
1489 
1490     /* Check transfer data size in read operation. */
1491     if ((transfer->direction == kLPI2C_Read) &&
1492         (transfer->dataSize > (256U * (uint32_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1493     {
1494         return kStatus_InvalidArgument;
1495     }
1496 
1497     /* Return busy if another transaction is in progress. */
1498     if (handle->state != (uint8_t)kIdleState)
1499     {
1500         result = kStatus_LPI2C_Busy;
1501     }
1502     else
1503     {
1504         result = LPI2C_CheckForBusyBus(base);
1505     }
1506 
1507     if ((status_t)kStatus_Success == result)
1508     {
1509         /* Enable the master function and disable the slave function. */
1510         LPI2C_MasterEnable(base, true);
1511         LPI2C_SlaveEnable(base, false);
1512 
1513         /* Disable LPI2C IRQ sources while we configure stuff. */
1514         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1515 
1516         /* Reset FIFO in case there are data. */
1517         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1518 
1519         /* Save transfer into handle. */
1520         handle->transfer = *transfer;
1521 
1522         /* Generate commands to send. */
1523         LPI2C_InitTransferStateMachine(handle);
1524 
1525         /* Clear all flags. */
1526         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1527 
1528         /* Turn off auto-stop option. */
1529         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1530 
1531         /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
1532         LPI2C_MasterEnableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1533     }
1534 
1535     return result;
1536 }
1537 
1538 /*!
1539  * brief Returns number of bytes transferred so far.
1540  * param base The LPI2C peripheral base address.
1541  * param handle Pointer to the LPI2C master driver handle.
1542  * param[out] count Number of bytes transferred so far by the non-blocking transaction.
1543  * retval #kStatus_Success
1544  * retval #kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1545  */
1546 status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count)
1547 {
1548     status_t result = kStatus_Success;
1549 
1550     assert(NULL != handle);
1551 
1552     if (NULL == count)
1553     {
1554         result = kStatus_InvalidArgument;
1555     }
1556 
1557     /* Catch when there is not an active transfer. */
1558     else if (handle->state == (uint8_t)kIdleState)
1559     {
1560         *count = 0;
1561         result = kStatus_NoTransferInProgress;
1562     }
1563     else
1564     {
1565         uint8_t state;
1566         uint16_t remainingBytes;
1567         uint32_t dataSize;
1568 
1569         /* Cache some fields with IRQs disabled. This ensures all field values */
1570         /* are synchronized with each other during an ongoing transfer. */
1571         uint32_t irqs = LPI2C_MasterGetEnabledInterrupts(base);
1572         LPI2C_MasterDisableInterrupts(base, irqs);
1573         state          = handle->state;
1574         remainingBytes = handle->remainingBytes;
1575         dataSize       = handle->transfer.dataSize;
1576         LPI2C_MasterEnableInterrupts(base, irqs);
1577 
1578         /* Get transfer count based on current transfer state. */
1579         switch (state)
1580         {
1581             case (uint8_t)kIdleState:
1582             case (uint8_t)kSendCommandState:
1583             case (uint8_t)
1584                 kIssueReadCommandState: /* XXX return correct value for this state when >256 reads are supported */
1585                 *count = 0;
1586                 break;
1587 
1588             case (uint8_t)kTransferDataState:
1589                 *count = dataSize - remainingBytes;
1590                 break;
1591 
1592             case (uint8_t)kStopState:
1593             case (uint8_t)kWaitForCompletionState:
1594             default:
1595                 *count = dataSize;
1596                 break;
1597         }
1598     }
1599 
1600     return result;
1601 }
1602 
1603 /*!
1604  * brief Terminates a non-blocking LPI2C master transmission early.
1605  *
1606  * note It is not safe to call this function from an IRQ handler that has a higher priority than the
1607  *      LPI2C peripheral's IRQ priority.
1608  *
1609  * param base The LPI2C peripheral base address.
1610  * param handle Pointer to the LPI2C master driver handle.
1611  * retval #kStatus_Success A transaction was successfully aborted.
1612  * retval #kStatus_LPI2C_Idle There is not a non-blocking transaction currently in progress.
1613  */
1614 void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1615 {
1616     if (handle->state != (uint8_t)kIdleState)
1617     {
1618         /* Disable internal IRQ enables. */
1619         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1620 
1621         /* Reset fifos. */
1622         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1623 
1624         /* If master is still busy and has not send out stop signal yet. */
1625         if ((LPI2C_MasterGetStatusFlags(base) & ((uint32_t)kLPI2C_MasterStopDetectFlag |
1626                                                  (uint32_t)kLPI2C_MasterBusyFlag)) == (uint32_t)kLPI2C_MasterBusyFlag)
1627         {
1628             /* Send a stop command to finalize the transfer. */
1629             base->MTDR = (uint32_t)kStopCmd;
1630         }
1631 
1632         /* Reset handle. */
1633         handle->state = (uint8_t)kIdleState;
1634     }
1635 }
1636 
1637 /*!
1638  * brief Reusable routine to handle master interrupts.
1639  * note This function does not need to be called unless you are reimplementing the
1640  *  nonblocking API's interrupt handler routines to add special functionality.
1641  * param base The LPI2C peripheral base address.
1642  * param lpi2cMasterHandle Pointer to the LPI2C master driver handle.
1643  */
1644 void LPI2C_MasterTransferHandleIRQ(LPI2C_Type *base, void *lpi2cMasterHandle)
1645 {
1646     assert(lpi2cMasterHandle != NULL);
1647 
1648     lpi2c_master_handle_t *handle = (lpi2c_master_handle_t *)lpi2cMasterHandle;
1649     bool isDone                   = false;
1650     status_t result;
1651 
1652     /* Don't do anything if we don't have a valid handle. */
1653     if (NULL != handle)
1654     {
1655         if (handle->state != (uint8_t)kIdleState)
1656         {
1657             result = LPI2C_RunTransferStateMachine(base, handle, &isDone);
1658 
1659             if ((result != kStatus_Success) || isDone)
1660             {
1661                 /* Handle error, terminate xfer */
1662                 if (result != kStatus_Success)
1663                 {
1664                     LPI2C_MasterTransferAbort(base, handle);
1665                 }
1666 
1667                 /* Disable internal IRQ enables. */
1668                 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1669 
1670                 /* Set handle to idle state. */
1671                 handle->state = (uint8_t)kIdleState;
1672 
1673                 /* Invoke callback. */
1674                 if (NULL != handle->completionCallback)
1675                 {
1676                     handle->completionCallback(base, handle, result, handle->userData);
1677                 }
1678             }
1679         }
1680     }
1681 }
1682 
1683 /*!
1684  * brief Provides a default configuration for the LPI2C slave peripheral.
1685  *
1686  * This function provides the following default configuration for the LPI2C slave peripheral:
1687  * code
1688  *  slaveConfig->enableSlave               = true;
1689  *  slaveConfig->address0                  = 0U;
1690  *  slaveConfig->address1                  = 0U;
1691  *  slaveConfig->addressMatchMode          = kLPI2C_MatchAddress0;
1692  *  slaveConfig->filterDozeEnable          = true;
1693  *  slaveConfig->filterEnable              = true;
1694  *  slaveConfig->enableGeneralCall         = false;
1695  *  slaveConfig->sclStall.enableAck        = false;
1696  *  slaveConfig->sclStall.enableTx         = true;
1697  *  slaveConfig->sclStall.enableRx         = true;
1698  *  slaveConfig->sclStall.enableAddress    = true;
1699  *  slaveConfig->ignoreAck                 = false;
1700  *  slaveConfig->enableReceivedAddressRead = false;
1701  *  slaveConfig->sdaGlitchFilterWidth_ns   = 0;
1702  *  slaveConfig->sclGlitchFilterWidth_ns   = 0;
1703  *  slaveConfig->dataValidDelay_ns         = 0;
1704  *  slaveConfig->clockHoldTime_ns          = 0;
1705  * endcode
1706  *
1707  * After calling this function, override any settings  to customize the configuration,
1708  * prior to initializing the master driver with LPI2C_SlaveInit(). Be sure to override at least the a
1709  * address0 member of the configuration structure with the desired slave address.
1710  *
1711  * param[out] slaveConfig User provided configuration structure that is set to default values. Refer to
1712  *      #lpi2c_slave_config_t.
1713  */
1714 void LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t *slaveConfig)
1715 {
1716     /* Initializes the configure structure to zero. */
1717     (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
1718 
1719     slaveConfig->enableSlave               = true;
1720     slaveConfig->address0                  = 0U;
1721     slaveConfig->address1                  = 0U;
1722     slaveConfig->addressMatchMode          = kLPI2C_MatchAddress0;
1723     slaveConfig->filterDozeEnable          = true;
1724     slaveConfig->filterEnable              = true;
1725     slaveConfig->enableGeneralCall         = false;
1726     slaveConfig->sclStall.enableAck        = false;
1727     slaveConfig->sclStall.enableTx         = true;
1728     slaveConfig->sclStall.enableRx         = true;
1729     slaveConfig->sclStall.enableAddress    = false;
1730     slaveConfig->ignoreAck                 = false;
1731     slaveConfig->enableReceivedAddressRead = false;
1732     slaveConfig->sdaGlitchFilterWidth_ns   = 0U; /* Set to 0 to disable the function */
1733     slaveConfig->sclGlitchFilterWidth_ns   = 0U; /* Set to 0 to disable the function */
1734     slaveConfig->dataValidDelay_ns         = 0U;
1735     /* When enabling the slave tx SCL stall, set the default clock hold time to 250ns according
1736        to I2C spec for standard mode baudrate(100k). User can manually change it to 100ns or 50ns
1737        for fast-mode(400k) or fast-mode+(1m). */
1738     slaveConfig->clockHoldTime_ns = 250U;
1739 }
1740 
1741 /*!
1742  * brief Initializes the LPI2C slave peripheral.
1743  *
1744  * This function enables the peripheral clock and initializes the LPI2C slave peripheral as described by the user
1745  * provided configuration.
1746  *
1747  * param base The LPI2C peripheral base address.
1748  * param slaveConfig User provided peripheral configuration. Use LPI2C_SlaveGetDefaultConfig() to get a set of defaults
1749  *      that you can override.
1750  * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the filter widths,
1751  *      data valid delay, and clock hold time.
1752  */
1753 void LPI2C_SlaveInit(LPI2C_Type *base, const lpi2c_slave_config_t *slaveConfig, uint32_t sourceClock_Hz)
1754 {
1755     uint32_t tmpReg;
1756     uint32_t tmpCycle;
1757 
1758 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1759 
1760     uint32_t instance = LPI2C_GetInstance(base);
1761 
1762     /* Ungate the clock. */
1763     (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
1764 #if defined(LPI2C_PERIPH_CLOCKS)
1765     /* Ungate the functional clock in initialize function. */
1766     CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
1767 #endif
1768 
1769 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1770 
1771     /* Restore to reset conditions. */
1772     LPI2C_SlaveReset(base);
1773 
1774     /* Configure peripheral. */
1775     base->SAMR = LPI2C_SAMR_ADDR0(slaveConfig->address0) | LPI2C_SAMR_ADDR1(slaveConfig->address1);
1776 
1777     base->SCFGR1 =
1778         LPI2C_SCFGR1_ADDRCFG(slaveConfig->addressMatchMode) | LPI2C_SCFGR1_IGNACK(slaveConfig->ignoreAck) |
1779         LPI2C_SCFGR1_RXCFG(slaveConfig->enableReceivedAddressRead) | LPI2C_SCFGR1_GCEN(slaveConfig->enableGeneralCall) |
1780         LPI2C_SCFGR1_ACKSTALL(slaveConfig->sclStall.enableAck) | LPI2C_SCFGR1_TXDSTALL(slaveConfig->sclStall.enableTx) |
1781         LPI2C_SCFGR1_RXSTALL(slaveConfig->sclStall.enableRx) |
1782         LPI2C_SCFGR1_ADRSTALL(slaveConfig->sclStall.enableAddress);
1783 
1784     /* Calculate SDA filter width. The width is equal to FILTSDA+3 cycles of functional clock.
1785        And set FILTSDA to 0 disables the fileter, so the min value is 4. */
1786     tmpReg = LPI2C_SCFGR2_FILTSDA(
1787         LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sdaGlitchFilterWidth_ns, 4U,
1788                                 (LPI2C_SCFGR2_FILTSDA_MASK >> LPI2C_SCFGR2_FILTSDA_SHIFT) + 3U, 0U) -
1789         3U);
1790 
1791     /* Calculate SDL filter width. The width is equal to FILTSCL+3 cycles of functional clock.
1792        And set FILTSCL to 0 disables the fileter, so the min value is 4. */
1793     tmpCycle = LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sclGlitchFilterWidth_ns, 4U,
1794                                        (LPI2C_SCFGR2_FILTSCL_MASK >> LPI2C_SCFGR2_FILTSCL_SHIFT) + 3U, 0U);
1795     tmpReg |= LPI2C_SCFGR2_FILTSCL(tmpCycle - 3U);
1796 
1797     /* Calculate data valid time. The time is equal to FILTSCL+DATAVD+3 cycles of functional clock.
1798        So the min value is FILTSCL+3. */
1799     tmpReg |= LPI2C_SCFGR2_DATAVD(
1800         LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->dataValidDelay_ns, tmpCycle,
1801                                 tmpCycle + (LPI2C_SCFGR2_DATAVD_MASK >> LPI2C_SCFGR2_DATAVD_SHIFT), 0U) -
1802         tmpCycle);
1803 
1804     /* Calculate clock hold time. The time is equal to CLKHOLD+3 cycles of functional clock.
1805        So the min value is 3. */
1806     base->SCFGR2 =
1807         tmpReg | LPI2C_SCFGR2_CLKHOLD(
1808                      LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->clockHoldTime_ns, 3U,
1809                                              (LPI2C_SCFGR2_CLKHOLD_MASK >> LPI2C_SCFGR2_CLKHOLD_SHIFT) + 3U, 0U) -
1810                      3U);
1811 
1812     /* Save SCR to last so we don't enable slave until it is configured */
1813     base->SCR = LPI2C_SCR_FILTDZ(!slaveConfig->filterDozeEnable) | LPI2C_SCR_FILTEN(slaveConfig->filterEnable) |
1814                 LPI2C_SCR_SEN(slaveConfig->enableSlave);
1815 }
1816 
1817 /*!
1818  * brief Deinitializes the LPI2C slave peripheral.
1819  *
1820  * This function disables the LPI2C slave peripheral and gates the clock. It also performs a software
1821  * reset to restore the peripheral to reset conditions.
1822  *
1823  * param base The LPI2C peripheral base address.
1824  */
1825 void LPI2C_SlaveDeinit(LPI2C_Type *base)
1826 {
1827     LPI2C_SlaveReset(base);
1828 
1829 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1830 
1831     uint32_t instance = LPI2C_GetInstance(base);
1832 
1833     /* Gate the clock. */
1834     (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
1835 
1836 #if defined(LPI2C_PERIPH_CLOCKS)
1837     /* Gate the functional clock. */
1838     CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
1839 #endif
1840 
1841 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1842 }
1843 
1844 /*!
1845  * @brief Convert provided flags to status code, and clear any errors if present.
1846  * @param base The LPI2C peripheral base address.
1847  * @param status Current status flags value that will be checked.
1848  * @retval #kStatus_Success
1849  * @retval #kStatus_LPI2C_BitError
1850  * @retval #kStatus_LPI2C_FifoError
1851  */
1852 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags)
1853 {
1854     status_t result = kStatus_Success;
1855 
1856     flags &= (uint32_t)kLPI2C_SlaveErrorFlags;
1857     if (0U != flags)
1858     {
1859         if (0U != (flags & (uint32_t)kLPI2C_SlaveBitErrFlag))
1860         {
1861             result = kStatus_LPI2C_BitError;
1862         }
1863         else if (0U != (flags & (uint32_t)kLPI2C_SlaveFifoErrFlag))
1864         {
1865             result = kStatus_LPI2C_FifoError;
1866         }
1867         else
1868         {
1869             ; /* Intentional empty */
1870         }
1871 
1872         /* Clear the errors. */
1873         LPI2C_SlaveClearStatusFlags(base, flags);
1874     }
1875     else
1876     {
1877         ; /* Intentional empty */
1878     }
1879 
1880     return result;
1881 }
1882 
1883 /*!
1884  * brief Performs a polling send transfer on the I2C bus.
1885  *
1886  * param base  The LPI2C peripheral base address.
1887  * param txBuff The pointer to the data to be transferred.
1888  * param txSize The length in bytes of the data to be transferred.
1889  * param[out] actualTxSize
1890  * return Error or success status returned by API.
1891  */
1892 status_t LPI2C_SlaveSend(LPI2C_Type *base, void *txBuff, size_t txSize, size_t *actualTxSize)
1893 {
1894     status_t result  = kStatus_Success;
1895     uint8_t *buf     = (uint8_t *)txBuff;
1896     size_t remaining = txSize;
1897 
1898     assert(NULL != txBuff);
1899 
1900 #if I2C_RETRY_TIMES != 0U
1901     uint32_t waitTimes = I2C_RETRY_TIMES;
1902 #endif
1903 
1904     /* Clear stop flag. */
1905     LPI2C_SlaveClearStatusFlags(base,
1906                                 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1907 
1908     while (0U != remaining)
1909     {
1910         uint32_t flags;
1911 
1912         /* Wait until we can transmit. */
1913         do
1914         {
1915             /* Check for errors */
1916             flags  = LPI2C_SlaveGetStatusFlags(base);
1917             result = LPI2C_SlaveCheckAndClearError(base, flags);
1918             if (kStatus_Success != result)
1919             {
1920                 if (NULL != actualTxSize)
1921                 {
1922                     *actualTxSize = txSize - remaining;
1923                 }
1924                 break;
1925             }
1926 #if I2C_RETRY_TIMES != 0U
1927             waitTimes--;
1928         } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1929                                   (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1930                  (0U != waitTimes));
1931         if (0U == waitTimes)
1932         {
1933             result = kStatus_LPI2C_Timeout;
1934         }
1935 #else
1936         } while (0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1937                                  (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
1938 #endif
1939 
1940         if (kStatus_Success != result)
1941         {
1942             break;
1943         }
1944 
1945         /* Send a byte. */
1946         if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
1947         {
1948             base->STDR = *buf++;
1949             --remaining;
1950         }
1951 
1952         /* Exit loop if we see a stop or restart in transfer*/
1953         if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1954             (remaining != 0U))
1955         {
1956             LPI2C_SlaveClearStatusFlags(
1957                 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1958             break;
1959         }
1960     }
1961 
1962     if (NULL != actualTxSize)
1963     {
1964         *actualTxSize = txSize - remaining;
1965     }
1966 
1967     return result;
1968 }
1969 
1970 /*!
1971  * brief Performs a polling receive transfer on the I2C bus.
1972  *
1973  * param base  The LPI2C peripheral base address.
1974  * param rxBuff The pointer to the data to be transferred.
1975  * param rxSize The length in bytes of the data to be transferred.
1976  * param[out] actualRxSize
1977  * return Error or success status returned by API.
1978  */
1979 status_t LPI2C_SlaveReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize, size_t *actualRxSize)
1980 {
1981     status_t result  = kStatus_Success;
1982     uint8_t *buf     = (uint8_t *)rxBuff;
1983     size_t remaining = rxSize;
1984 
1985     assert(NULL != rxBuff);
1986 
1987 #if I2C_RETRY_TIMES != 0U
1988     uint32_t waitTimes = I2C_RETRY_TIMES;
1989 #endif
1990 
1991     /* Clear stop flag. */
1992     LPI2C_SlaveClearStatusFlags(base,
1993                                 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1994 
1995     while (0U != remaining)
1996     {
1997         uint32_t flags;
1998 
1999         /* Wait until we can receive. */
2000         do
2001         {
2002             /* Check for errors */
2003             flags  = LPI2C_SlaveGetStatusFlags(base);
2004             result = LPI2C_SlaveCheckAndClearError(base, flags);
2005             if (kStatus_Success != result)
2006             {
2007                 if (NULL != actualRxSize)
2008                 {
2009                     *actualRxSize = rxSize - remaining;
2010                 }
2011                 break;
2012             }
2013 #if I2C_RETRY_TIMES != 0U
2014             waitTimes--;
2015         } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2016                                   (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2017                  (0U != waitTimes));
2018         if (0U == waitTimes)
2019         {
2020             result = kStatus_LPI2C_Timeout;
2021         }
2022 #else
2023         } while (0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2024                                  (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
2025 #endif
2026 
2027         if ((status_t)kStatus_Success != result)
2028         {
2029             break;
2030         }
2031 
2032         /* Receive a byte. */
2033         if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2034         {
2035             *buf++ = (uint8_t)(base->SRDR & LPI2C_SRDR_DATA_MASK);
2036             --remaining;
2037         }
2038 
2039         /* Exit loop if we see a stop or restart */
2040         if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2041             (remaining != 0U))
2042         {
2043             LPI2C_SlaveClearStatusFlags(
2044                 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2045             break;
2046         }
2047     }
2048 
2049     if (NULL != actualRxSize)
2050     {
2051         *actualRxSize = rxSize - remaining;
2052     }
2053 
2054     return result;
2055 }
2056 
2057 /*!
2058  * brief Creates a new handle for the LPI2C slave non-blocking APIs.
2059  *
2060  * The creation of a handle is for use with the non-blocking APIs. Once a handle
2061  * is created, there is not a corresponding destroy handle. If the user wants to
2062  * terminate a transfer, the LPI2C_SlaveTransferAbort() API shall be called.
2063  *
2064  * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
2065  * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
2066  * enable the associated INTMUX IRQ in application.
2067 
2068  * param base The LPI2C peripheral base address.
2069  * param[out] handle Pointer to the LPI2C slave driver handle.
2070  * param callback User provided pointer to the asynchronous callback function.
2071  * param userData User provided pointer to the application callback data.
2072  */
2073 void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
2074                                      lpi2c_slave_handle_t *handle,
2075                                      lpi2c_slave_transfer_callback_t callback,
2076                                      void *userData)
2077 {
2078     uint32_t instance;
2079 
2080     assert(NULL != handle);
2081 
2082     /* Clear out the handle. */
2083     (void)memset(handle, 0, sizeof(*handle));
2084 
2085     /* Look up instance number */
2086     instance = LPI2C_GetInstance(base);
2087 
2088     /* Save base and instance. */
2089     handle->callback = callback;
2090     handle->userData = userData;
2091 
2092     /* Save this handle for IRQ use. */
2093     s_lpi2cSlaveHandle[instance] = handle;
2094 
2095     /* Set irq handler. */
2096     s_lpi2cSlaveIsr = LPI2C_SlaveTransferHandleIRQ;
2097 
2098     /* Clear internal IRQ enables and enable NVIC IRQ. */
2099     LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2100     (void)EnableIRQ(kLpi2cIrqs[instance]);
2101 
2102     /* Nack by default. */
2103     base->STAR = LPI2C_STAR_TXNACK_MASK;
2104 }
2105 
2106 /*!
2107  * brief Starts accepting slave transfers.
2108  *
2109  * Call this API after calling I2C_SlaveInit() and LPI2C_SlaveTransferCreateHandle() to start processing
2110  * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
2111  * callback that was passed into the call to LPI2C_SlaveTransferCreateHandle(). The callback is always invoked
2112  * from the interrupt context.
2113  *
2114  * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
2115  * the OR'd combination of #lpi2c_slave_transfer_event_t enumerators for the events you wish to receive.
2116  * The #kLPI2C_SlaveTransmitEvent and #kLPI2C_SlaveReceiveEvent events are always enabled and do not need
2117  * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
2118  * receive events that are always enabled. In addition, the #kLPI2C_SlaveAllEvents constant is provided as
2119  * a convenient way to enable all events.
2120  *
2121  * param base The LPI2C peripheral base address.
2122  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2123  * param eventMask Bit mask formed by OR'ing together #lpi2c_slave_transfer_event_t enumerators to specify
2124  *      which events to send to the callback. Other accepted values are 0 to get a default set of
2125  *      only the transmit and receive events, and #kLPI2C_SlaveAllEvents to enable all events.
2126  *
2127  * retval #kStatus_Success Slave transfers were successfully started.
2128  * retval #kStatus_LPI2C_Busy Slave transfers have already been started on this handle.
2129  */
2130 status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask)
2131 {
2132     status_t result = kStatus_Success;
2133 
2134     assert(NULL != handle);
2135 
2136     /* Return busy if another transaction is in progress. */
2137     if (handle->isBusy)
2138     {
2139         result = kStatus_LPI2C_Busy;
2140     }
2141     else
2142     {
2143         /* Enable the slave function and disable the master function. */
2144         LPI2C_MasterEnable(base, false);
2145         LPI2C_SlaveEnable(base, true);
2146         /* Return an error if the bus is already in use not by us. */
2147         uint32_t status = LPI2C_SlaveGetStatusFlags(base);
2148         if ((0U != (status & (uint32_t)kLPI2C_SlaveBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_SlaveBusyFlag)))
2149         {
2150             result = kStatus_LPI2C_Busy;
2151         }
2152     }
2153 
2154     if ((status_t)kStatus_Success == result)
2155     {
2156         /* Disable LPI2C IRQ sources while we configure stuff. */
2157         LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2158 
2159         /* Clear transfer in handle. */
2160         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2161 
2162         /* Record that we're busy. */
2163         handle->isBusy = true;
2164 
2165         /* Set up event mask. tx and rx are always enabled. */
2166         handle->eventMask = eventMask | (uint32_t)kLPI2C_SlaveTransmitEvent | (uint32_t)kLPI2C_SlaveReceiveEvent;
2167 
2168         /* Ack by default. */
2169         base->STAR = 0U;
2170 
2171         /* Clear all flags. */
2172         LPI2C_SlaveClearStatusFlags(base, (uint32_t)kLPI2C_SlaveClearFlags);
2173 
2174         /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
2175         LPI2C_SlaveEnableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2176     }
2177 
2178     return result;
2179 }
2180 
2181 /*!
2182  * brief Gets the slave transfer status during a non-blocking transfer.
2183  * param base The LPI2C peripheral base address.
2184  * param handle Pointer to i2c_slave_handle_t structure.
2185  * param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not
2186  *      required.
2187  * retval #kStatus_Success
2188  * retval #kStatus_NoTransferInProgress
2189  */
2190 status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count)
2191 {
2192     status_t status = kStatus_Success;
2193 
2194     assert(NULL != handle);
2195 
2196     if (count == NULL)
2197     {
2198         status = kStatus_InvalidArgument;
2199     }
2200 
2201     /* Catch when there is not an active transfer. */
2202     else if (!handle->isBusy)
2203     {
2204         *count = 0;
2205         status = kStatus_NoTransferInProgress;
2206     }
2207 
2208     /* For an active transfer, just return the count from the handle. */
2209     else
2210     {
2211         *count = handle->transferredCount;
2212     }
2213 
2214     return status;
2215 }
2216 
2217 /*!
2218  * brief Aborts the slave non-blocking transfers.
2219  * note This API could be called at any time to stop slave for handling the bus events.
2220  * param base The LPI2C peripheral base address.
2221  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2222  * retval #kStatus_Success
2223  * retval #kStatus_LPI2C_Idle
2224  */
2225 void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2226 {
2227     assert(NULL != handle);
2228 
2229     /* Return idle if no transaction is in progress. */
2230     if (handle->isBusy)
2231     {
2232         /* Disable LPI2C IRQ sources. */
2233         LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2234 
2235         /* Nack by default. */
2236         base->STAR = LPI2C_STAR_TXNACK_MASK;
2237 
2238         /* Reset transfer info. */
2239         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2240 
2241         /* We're no longer busy. */
2242         handle->isBusy = false;
2243     }
2244 }
2245 
2246 /*!
2247  * brief Reusable routine to handle slave interrupts.
2248  * note This function does not need to be called unless you are reimplementing the
2249  *  non blocking API's interrupt handler routines to add special functionality.
2250  * param base The LPI2C peripheral base address.
2251  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2252  */
2253 void LPI2C_SlaveTransferHandleIRQ(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2254 {
2255     uint32_t flags;
2256     lpi2c_slave_transfer_t *xfer;
2257 
2258     /* Check for a valid handle in case of a spurious interrupt. */
2259     if (NULL != handle)
2260     {
2261         xfer = &handle->transfer;
2262 
2263         /* Get status flags. */
2264         flags = LPI2C_SlaveGetStatusFlags(base);
2265 
2266         if (0U != (flags & ((uint32_t)kLPI2C_SlaveBitErrFlag | (uint32_t)kLPI2C_SlaveFifoErrFlag)))
2267         {
2268             xfer->event            = kLPI2C_SlaveCompletionEvent;
2269             xfer->completionStatus = LPI2C_SlaveCheckAndClearError(base, flags);
2270 
2271             if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveCompletionEvent)) && (NULL != handle->callback))
2272             {
2273                 handle->callback(base, xfer, handle->userData);
2274             }
2275         }
2276         else
2277         {
2278             if (0U !=
2279                 (flags & (((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag) | ((uint32_t)kLPI2C_SlaveStopDetectFlag))))
2280             {
2281                 xfer->event = (0U != (flags & (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)) ?
2282                                   kLPI2C_SlaveRepeatedStartEvent :
2283                                   kLPI2C_SlaveCompletionEvent;
2284                 xfer->receivedAddress  = 0U;
2285                 xfer->completionStatus = kStatus_Success;
2286                 xfer->transferredCount = handle->transferredCount;
2287 
2288                 if (xfer->event == kLPI2C_SlaveCompletionEvent)
2289                 {
2290                     handle->isBusy = false;
2291                 }
2292 
2293                 if (handle->wasTransmit)
2294                 {
2295                     /* Subtract one from the transmit count to offset the fact that LPI2C asserts the */
2296                     /* tx flag before it sees the nack from the master-receiver, thus causing one more */
2297                     /* count that the master actually receives. */
2298                     --xfer->transferredCount;
2299                     handle->wasTransmit = false;
2300                 }
2301 
2302                 /* Clear the flag. */
2303                 LPI2C_SlaveClearStatusFlags(base, flags & ((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag |
2304                                                            (uint32_t)kLPI2C_SlaveStopDetectFlag));
2305 
2306                 /* Revert to sending an Ack by default, in case we sent a Nack for receive. */
2307                 base->STAR = 0U;
2308 
2309                 if ((0U != (handle->eventMask & (uint32_t)xfer->event)) && (NULL != handle->callback))
2310                 {
2311                     handle->callback(base, xfer, handle->userData);
2312                 }
2313 
2314                 if (0U != (flags & (uint32_t)kLPI2C_SlaveStopDetectFlag))
2315                 {
2316                     /* Clean up transfer info on completion, after the callback has been invoked. */
2317                     (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2318                 }
2319             }
2320             if (0U != (flags & (uint32_t)kLPI2C_SlaveAddressValidFlag))
2321             {
2322                 xfer->event           = kLPI2C_SlaveAddressMatchEvent;
2323                 xfer->receivedAddress = (uint8_t)(base->SASR & LPI2C_SASR_RADDR_MASK);
2324 
2325                 /* Update handle status to busy because slave is addressed. */
2326                 handle->isBusy = true;
2327                 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveAddressMatchEvent)) && (NULL != handle->callback))
2328                 {
2329                     handle->callback(base, xfer, handle->userData);
2330                 }
2331             }
2332             if (0U != (flags & (uint32_t)kLPI2C_SlaveTransmitAckFlag))
2333             {
2334                 xfer->event = kLPI2C_SlaveTransmitAckEvent;
2335 
2336                 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveTransmitAckEvent)) && (NULL != handle->callback))
2337                 {
2338                     handle->callback(base, xfer, handle->userData);
2339                 }
2340             }
2341 
2342             /* Handle transmit and receive. */
2343             if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2344             {
2345                 handle->wasTransmit = true;
2346 
2347                 /* If we're out of data, invoke callback to get more. */
2348                 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2349                 {
2350                     xfer->event = kLPI2C_SlaveTransmitEvent;
2351                     if (NULL != handle->callback)
2352                     {
2353                         handle->callback(base, xfer, handle->userData);
2354                     }
2355 
2356                     /* Clear the transferred count now that we have a new buffer. */
2357                     handle->transferredCount = 0U;
2358                 }
2359 
2360                 /* Transmit a byte. */
2361                 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2362                 {
2363                     base->STDR = *xfer->data++;
2364                     --xfer->dataSize;
2365                     ++handle->transferredCount;
2366                 }
2367             }
2368             if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2369             {
2370                 /* If we're out of room in the buffer, invoke callback to get another. */
2371                 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2372                 {
2373                     xfer->event = kLPI2C_SlaveReceiveEvent;
2374                     if (NULL != handle->callback)
2375                     {
2376                         handle->callback(base, xfer, handle->userData);
2377                     }
2378 
2379                     /* Clear the transferred count now that we have a new buffer. */
2380                     handle->transferredCount = 0U;
2381                 }
2382 
2383                 /* Receive a byte. */
2384                 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2385                 {
2386                     *xfer->data++ = (uint8_t)base->SRDR;
2387                     --xfer->dataSize;
2388                     ++handle->transferredCount;
2389                 }
2390                 else
2391                 {
2392                     /* We don't have any room to receive more data, so send a nack. */
2393                     base->STAR = LPI2C_STAR_TXNACK_MASK;
2394                 }
2395             }
2396         }
2397     }
2398 }
2399 
2400 #if !(defined(FSL_FEATURE_I2C_HAS_NO_IRQ) && FSL_FEATURE_I2C_HAS_NO_IRQ)
2401 /*!
2402  * @brief Shared IRQ handler that can call both master and slave ISRs.
2403  *
2404  * The master and slave ISRs are called through function pointers in order to decouple
2405  * this code from the ISR functions. Without this, the linker would always pull in both
2406  * ISRs and every function they call, even if only the functional API was used.
2407  *
2408  * @param base The LPI2C peripheral base address.
2409  * @param instance The LPI2C peripheral instance number.
2410  */
2411 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance)
2412 {
2413     /* Check for master IRQ. */
2414     if ((0U != (base->MCR & LPI2C_MCR_MEN_MASK)) && (NULL != s_lpi2cMasterIsr))
2415     {
2416         /* Master mode. */
2417         s_lpi2cMasterIsr(base, s_lpi2cMasterHandle[instance]);
2418     }
2419 
2420     /* Check for slave IRQ. */
2421     if ((0U != (base->SCR & LPI2C_SCR_SEN_MASK)) && (NULL != s_lpi2cSlaveIsr))
2422     {
2423         /* Slave mode. */
2424         s_lpi2cSlaveIsr(base, s_lpi2cSlaveHandle[instance]);
2425     }
2426     SDK_ISR_EXIT_BARRIER;
2427 }
2428 #endif
2429 
2430 #if defined(LPI2C0)
2431 /* Implementation of LPI2C0 handler named in startup code. */
2432 void LPI2C0_DriverIRQHandler(void);
2433 void LPI2C0_DriverIRQHandler(void)
2434 {
2435     LPI2C_CommonIRQHandler(LPI2C0, 0U);
2436 }
2437 #endif
2438 
2439 #if defined(LPI2C1)
2440 /* Implementation of LPI2C1 handler named in startup code. */
2441 void LPI2C1_DriverIRQHandler(void);
2442 void LPI2C1_DriverIRQHandler(void)
2443 {
2444     LPI2C_CommonIRQHandler(LPI2C1, 1U);
2445 }
2446 #endif
2447 
2448 #if defined(LPI2C2)
2449 /* Implementation of LPI2C2 handler named in startup code. */
2450 void LPI2C2_DriverIRQHandler(void);
2451 void LPI2C2_DriverIRQHandler(void)
2452 {
2453     LPI2C_CommonIRQHandler(LPI2C2, 2U);
2454 }
2455 #endif
2456 
2457 #if defined(LPI2C3)
2458 /* Implementation of LPI2C3 handler named in startup code. */
2459 void LPI2C3_DriverIRQHandler(void);
2460 void LPI2C3_DriverIRQHandler(void)
2461 {
2462     LPI2C_CommonIRQHandler(LPI2C3, 3U);
2463 }
2464 #endif
2465 
2466 #if defined(LPI2C4)
2467 /* Implementation of LPI2C4 handler named in startup code. */
2468 void LPI2C4_DriverIRQHandler(void);
2469 void LPI2C4_DriverIRQHandler(void)
2470 {
2471     LPI2C_CommonIRQHandler(LPI2C4, 4U);
2472 }
2473 #endif
2474 
2475 #if defined(LPI2C5)
2476 /* Implementation of LPI2C5 handler named in startup code. */
2477 void LPI2C5_DriverIRQHandler(void);
2478 void LPI2C5_DriverIRQHandler(void)
2479 {
2480     LPI2C_CommonIRQHandler(LPI2C5, 5U);
2481 }
2482 #endif
2483 
2484 #if defined(LPI2C6)
2485 /* Implementation of LPI2C6 handler named in startup code. */
2486 void LPI2C6_DriverIRQHandler(void);
2487 void LPI2C6_DriverIRQHandler(void)
2488 {
2489     LPI2C_CommonIRQHandler(LPI2C6, 6U);
2490 }
2491 #endif
2492 
2493 #if defined(CM4_0__LPI2C)
2494 /* Implementation of CM4_0__LPI2C handler named in startup code. */
2495 void M4_0_LPI2C_DriverIRQHandler(void);
2496 void M4_0_LPI2C_DriverIRQHandler(void)
2497 {
2498     LPI2C_CommonIRQHandler(CM4_0__LPI2C, LPI2C_GetInstance(CM4_0__LPI2C));
2499 }
2500 #endif
2501 
2502 #if defined(CM4__LPI2C)
2503 /* Implementation of CM4__LPI2C handler named in startup code. */
2504 void M4_LPI2C_DriverIRQHandler(void);
2505 void M4_LPI2C_DriverIRQHandler(void)
2506 {
2507     LPI2C_CommonIRQHandler(CM4__LPI2C, LPI2C_GetInstance(CM4__LPI2C));
2508 }
2509 #endif
2510 
2511 #if defined(CM4_1__LPI2C)
2512 /* Implementation of CM4_1__LPI2C handler named in startup code. */
2513 void M4_1_LPI2C_DriverIRQHandler(void);
2514 void M4_1_LPI2C_DriverIRQHandler(void)
2515 {
2516     LPI2C_CommonIRQHandler(CM4_1__LPI2C, LPI2C_GetInstance(CM4_1__LPI2C));
2517 }
2518 #endif
2519 
2520 #if defined(DMA__LPI2C0)
2521 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2522 void DMA_I2C0_INT_DriverIRQHandler(void);
2523 void DMA_I2C0_INT_DriverIRQHandler(void)
2524 {
2525     LPI2C_CommonIRQHandler(DMA__LPI2C0, LPI2C_GetInstance(DMA__LPI2C0));
2526 }
2527 #endif
2528 
2529 #if defined(DMA__LPI2C1)
2530 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2531 void DMA_I2C1_INT_DriverIRQHandler(void);
2532 void DMA_I2C1_INT_DriverIRQHandler(void)
2533 {
2534     LPI2C_CommonIRQHandler(DMA__LPI2C1, LPI2C_GetInstance(DMA__LPI2C1));
2535 }
2536 #endif
2537 
2538 #if defined(DMA__LPI2C2)
2539 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2540 void DMA_I2C2_INT_DriverIRQHandler(void);
2541 void DMA_I2C2_INT_DriverIRQHandler(void)
2542 {
2543     LPI2C_CommonIRQHandler(DMA__LPI2C2, LPI2C_GetInstance(DMA__LPI2C2));
2544 }
2545 #endif
2546 
2547 #if defined(DMA__LPI2C3)
2548 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2549 void DMA_I2C3_INT_DriverIRQHandler(void);
2550 void DMA_I2C3_INT_DriverIRQHandler(void)
2551 {
2552     LPI2C_CommonIRQHandler(DMA__LPI2C3, LPI2C_GetInstance(DMA__LPI2C3));
2553 }
2554 #endif
2555 
2556 #if defined(DMA__LPI2C4)
2557 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2558 void DMA_I2C4_INT_DriverIRQHandler(void);
2559 void DMA_I2C4_INT_DriverIRQHandler(void)
2560 {
2561     LPI2C_CommonIRQHandler(DMA__LPI2C4, LPI2C_GetInstance(DMA__LPI2C4));
2562 }
2563 #endif
2564 
2565 #if defined(ADMA__LPI2C0)
2566 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2567 void ADMA_I2C0_INT_DriverIRQHandler(void);
2568 void ADMA_I2C0_INT_DriverIRQHandler(void)
2569 {
2570     LPI2C_CommonIRQHandler(ADMA__LPI2C0, LPI2C_GetInstance(ADMA__LPI2C0));
2571 }
2572 #endif
2573 
2574 #if defined(ADMA__LPI2C1)
2575 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2576 void ADMA_I2C1_INT_DriverIRQHandler(void);
2577 void ADMA_I2C1_INT_DriverIRQHandler(void)
2578 {
2579     LPI2C_CommonIRQHandler(ADMA__LPI2C1, LPI2C_GetInstance(ADMA__LPI2C1));
2580 }
2581 #endif
2582 
2583 #if defined(ADMA__LPI2C2)
2584 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2585 void ADMA_I2C2_INT_DriverIRQHandler(void);
2586 void ADMA_I2C2_INT_DriverIRQHandler(void)
2587 {
2588     LPI2C_CommonIRQHandler(ADMA__LPI2C2, LPI2C_GetInstance(ADMA__LPI2C2));
2589 }
2590 #endif
2591 
2592 #if defined(ADMA__LPI2C3)
2593 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2594 void ADMA_I2C3_INT_DriverIRQHandler(void);
2595 void ADMA_I2C3_INT_DriverIRQHandler(void)
2596 {
2597     LPI2C_CommonIRQHandler(ADMA__LPI2C3, LPI2C_GetInstance(ADMA__LPI2C3));
2598 }
2599 #endif
2600 
2601 #if defined(ADMA__LPI2C4)
2602 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2603 void ADMA_I2C4_INT_DriverIRQHandler(void);
2604 void ADMA_I2C4_INT_DriverIRQHandler(void)
2605 {
2606     LPI2C_CommonIRQHandler(ADMA__LPI2C4, LPI2C_GetInstance(ADMA__LPI2C4));
2607 }
2608 #endif