summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_flexio_i2c_master.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_flexio_i2c_master.c')
-rw-r--r--bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_flexio_i2c_master.c1258
1 files changed, 1258 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_flexio_i2c_master.c b/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_flexio_i2c_master.c
new file mode 100644
index 0000000000..43b5bc1b88
--- /dev/null
+++ b/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_flexio_i2c_master.c
@@ -0,0 +1,1258 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_flexio_i2c_master.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.flexio_i2c_master"
+#endif
+
+/*! @brief FLEXIO I2C transfer state */
+enum _flexio_i2c_master_transfer_states
+{
+ kFLEXIO_I2C_Idle = 0x0U, /*!< I2C bus idle */
+ kFLEXIO_I2C_Start = 0x1U, /*!< I2C start phase */
+ kFLEXIO_I2C_SendCommand = 0x2U, /*!< Send command byte phase */
+ kFLEXIO_I2C_SendData = 0x3U, /*!< Send data transfer phase*/
+ kFLEXIO_I2C_ReceiveDataBegin = 0x4U, /*!< Receive data begin transfer phase*/
+ kFLEXIO_I2C_ReceiveData = 0x5U, /*!< Receive data transfer phase*/
+};
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*!
+ * @brief Set up master transfer, send slave address and decide the initial
+ * transfer state.
+ *
+ * @param base pointer to FLEXIO_I2C_Type structure
+ * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
+ * @param transfer pointer to flexio_i2c_master_transfer_t structure
+ */
+static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
+ flexio_i2c_master_handle_t *handle,
+ flexio_i2c_master_transfer_t *xfer);
+
+/*!
+ * @brief Master run transfer state machine to perform a byte of transfer.
+ *
+ * @param base pointer to FLEXIO_I2C_Type structure
+ * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
+ * @param statusFlags flexio i2c hardware status
+ * @retval kStatus_Success Successfully run state machine
+ * @retval kStatus_FLEXIO_I2C_Nak Receive Nak during transfer
+ */
+static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
+ flexio_i2c_master_handle_t *handle,
+ uint32_t statusFlags);
+
+/*!
+ * @brief Complete transfer, disable interrupt and call callback.
+ *
+ * @param base pointer to FLEXIO_I2C_Type structure
+ * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
+ * @param status flexio transfer status
+ */
+static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
+ flexio_i2c_master_handle_t *handle,
+ status_t status);
+
+/*******************************************************************************
+ * Codes
+ ******************************************************************************/
+
+static uint32_t FLEXIO_I2C_GetInstance(FLEXIO_I2C_Type *base)
+{
+ return FLEXIO_GetInstance(base->flexioBase);
+}
+
+static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
+ flexio_i2c_master_handle_t *handle,
+ flexio_i2c_master_transfer_t *xfer)
+{
+ bool needRestart;
+ uint32_t byteCount;
+
+ /* Init the handle member. */
+ handle->transfer.slaveAddress = xfer->slaveAddress;
+ handle->transfer.direction = xfer->direction;
+ handle->transfer.subaddress = xfer->subaddress;
+ handle->transfer.subaddressSize = xfer->subaddressSize;
+ handle->transfer.data = xfer->data;
+ handle->transfer.dataSize = xfer->dataSize;
+ handle->transfer.flags = xfer->flags;
+ handle->transferSize = xfer->dataSize;
+
+ /* Initial state, i2c start state. */
+ handle->state = (uint8_t)kFLEXIO_I2C_Start;
+
+ /* Clear all status before transfer. */
+ FLEXIO_I2C_MasterClearStatusFlags(base, (uint32_t)kFLEXIO_I2C_ReceiveNakFlag);
+
+ /* Calculate whether need to send re-start. */
+ needRestart = (handle->transfer.subaddressSize != 0U) && (handle->transfer.direction == kFLEXIO_I2C_Read);
+ handle->needRestart = needRestart;
+
+ /* Calculate total byte count in a frame. */
+ byteCount = 1U;
+
+ if (!needRestart)
+ {
+ byteCount += handle->transfer.dataSize;
+ }
+
+ if (handle->transfer.subaddressSize != 0U)
+ {
+ byteCount += handle->transfer.subaddressSize;
+ }
+
+ /* Configure data count. */
+ if (FLEXIO_I2C_MasterSetTransferCount(base, (uint16_t)byteCount) != kStatus_Success)
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* Configure timer1 disable condition. */
+ uint32_t tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[1]];
+ tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
+ tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPreTimerDisable);
+ base->flexioBase->TIMCFG[base->timerIndex[1]] = tmpConfig;
+
+#if I2C_RETRY_TIMES
+ uint32_t waitTimes = I2C_RETRY_TIMES;
+ while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
+ {
+ }
+#endif
+
+ return kStatus_Success;
+}
+
+static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
+ flexio_i2c_master_handle_t *handle,
+ uint32_t statusFlags)
+{
+#if I2C_RETRY_TIMES
+ uint32_t waitTimes = I2C_RETRY_TIMES;
+#endif
+
+ if ((statusFlags & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
+ {
+ /* Clear receive nak flag. */
+ FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
+
+ if ((!((handle->state == (uint8_t)kFLEXIO_I2C_SendData) && (handle->transfer.dataSize == 0U))) &&
+ (!(((handle->state == (uint8_t)kFLEXIO_I2C_ReceiveData) ||
+ (handle->state == (uint8_t)kFLEXIO_I2C_ReceiveDataBegin)) &&
+ (handle->transfer.dataSize == 1U))))
+ {
+ (void)FLEXIO_I2C_MasterReadByte(base);
+
+ FLEXIO_I2C_MasterAbortStop(base);
+
+ /* Delay one clk cycle to ensure the bus is idle. */
+ SDK_DelayAtLeastUs(1000000UL / base->baudrate, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
+
+ handle->state = (uint8_t)kFLEXIO_I2C_Idle;
+
+ return kStatus_FLEXIO_I2C_Nak;
+ }
+ }
+
+ if (((statusFlags & (uint8_t)kFLEXIO_I2C_RxFullFlag) != 0U) && (handle->state != (uint8_t)kFLEXIO_I2C_ReceiveData))
+ {
+ (void)FLEXIO_I2C_MasterReadByte(base);
+ }
+
+ switch (handle->state)
+ {
+ /* Initial state, i2c start state. */
+ case (uint8_t)kFLEXIO_I2C_Start:
+ /* Send address byte first. */
+ if (handle->needRestart)
+ {
+ FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Write);
+ }
+ else
+ {
+ FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, handle->transfer.direction);
+ }
+ if (handle->transfer.subaddressSize == 0U)
+ {
+ if (handle->transfer.direction == kFLEXIO_I2C_Write)
+ {
+ /* Next state, send data. */
+ handle->state = (uint8_t)kFLEXIO_I2C_SendData;
+ }
+ else
+ {
+ /* Next state, receive data begin. */
+ handle->state = (uint8_t)kFLEXIO_I2C_ReceiveDataBegin;
+ }
+ }
+ else
+ {
+ /* Next state, send command byte. */
+ handle->state = (uint8_t)kFLEXIO_I2C_SendCommand;
+ }
+ break;
+
+ /* Check address only needed for transfer with subaddress */
+ case (uint8_t)kFLEXIO_I2C_SendCommand:
+ if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
+ {
+ if (handle->transfer.subaddressSize > 0U)
+ {
+ handle->transfer.subaddressSize--;
+ FLEXIO_I2C_MasterWriteByte(
+ base, ((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize)));
+
+ if (handle->transfer.subaddressSize == 0U)
+ {
+ /* Load re-start in advance. */
+ if (handle->transfer.direction == kFLEXIO_I2C_Read)
+ {
+#if I2C_RETRY_TIMES
+ while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) &
+ (1UL << base->shifterIndex[0]))) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U ==
+ (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
+ {
+ }
+#endif
+ FLEXIO_I2C_MasterRepeatedStart(base);
+ }
+ }
+ }
+ else
+ {
+ if (handle->transfer.direction == kFLEXIO_I2C_Write)
+ {
+ /* Send first byte of data. */
+ if (handle->transfer.dataSize > 0U)
+ {
+ /* Next state, send data. */
+ handle->state = (uint8_t)kFLEXIO_I2C_SendData;
+
+ FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
+ handle->transfer.data++;
+ handle->transfer.dataSize--;
+ }
+ else
+ {
+ FLEXIO_I2C_MasterStop(base);
+
+#if I2C_RETRY_TIMES
+ while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
+ {
+ }
+#endif
+ (void)FLEXIO_I2C_MasterReadByte(base);
+
+ handle->state = (uint8_t)kFLEXIO_I2C_Idle;
+ }
+ }
+ else
+ {
+ (void)FLEXIO_I2C_MasterSetTransferCount(base, (uint16_t)(handle->transfer.dataSize + 1U));
+ FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Read);
+
+ /* Next state, receive data begin. */
+ handle->state = (uint8_t)kFLEXIO_I2C_ReceiveDataBegin;
+ }
+ }
+ }
+ break;
+
+ /* Send command byte. */
+ case (uint8_t)kFLEXIO_I2C_SendData:
+ if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
+ {
+ /* Send one byte of data. */
+ if (handle->transfer.dataSize > 0U)
+ {
+ FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
+
+ handle->transfer.data++;
+ handle->transfer.dataSize--;
+ }
+ else
+ {
+ FLEXIO_I2C_MasterStop(base);
+
+#if I2C_RETRY_TIMES
+ while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
+ {
+ }
+#endif
+ (void)FLEXIO_I2C_MasterReadByte(base);
+
+ handle->state = (uint8_t)kFLEXIO_I2C_Idle;
+ }
+ }
+ break;
+
+ case (uint8_t)kFLEXIO_I2C_ReceiveDataBegin:
+ if ((statusFlags & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
+ {
+ handle->state = (uint8_t)kFLEXIO_I2C_ReceiveData;
+ /* Send nak at the last receive byte. */
+ if (handle->transfer.dataSize == 1U)
+ {
+ FLEXIO_I2C_MasterEnableAck(base, false);
+#if I2C_RETRY_TIMES
+ while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
+ {
+ }
+#endif
+ FLEXIO_I2C_MasterStop(base);
+ }
+ else
+ {
+ FLEXIO_I2C_MasterEnableAck(base, true);
+ }
+ }
+ else if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
+ {
+ /* Read one byte of data. */
+ FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
+ }
+ else
+ {
+ ; /* Avoid MISRA 2012 rule 15.7 */
+ }
+ break;
+
+ case (uint8_t)kFLEXIO_I2C_ReceiveData:
+ if ((statusFlags & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
+ {
+ *handle->transfer.data = FLEXIO_I2C_MasterReadByte(base);
+ handle->transfer.data++;
+ if (0U != handle->transfer.dataSize--)
+ {
+ if (handle->transfer.dataSize == 0U)
+ {
+ FLEXIO_I2C_MasterDisableInterrupts(base, (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
+ handle->state = (uint8_t)kFLEXIO_I2C_Idle;
+ /* Return nak if ReceiveNakFlag is not set */
+ if ((statusFlags & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) == 0U)
+ {
+ return kStatus_FLEXIO_I2C_Nak;
+ }
+ }
+
+ /* Send nak at the last receive byte. */
+ if (handle->transfer.dataSize == 1U)
+ {
+ FLEXIO_I2C_MasterEnableAck(base, false);
+#if I2C_RETRY_TIMES
+ while (
+ (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
+ {
+ }
+#endif
+ FLEXIO_I2C_MasterStop(base);
+ }
+ }
+ }
+ else if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
+ {
+ if (handle->transfer.dataSize > 1U)
+ {
+ FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
+ }
+ }
+ else
+ {
+ ; /* Avoid MISRA 2012 rule 15.7 */
+ }
+ break;
+
+ default:
+ /* Add comment to avoid MISRA violation */
+ break;
+ }
+
+ return kStatus_Success;
+}
+
+static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
+ flexio_i2c_master_handle_t *handle,
+ status_t status)
+{
+ FLEXIO_I2C_MasterDisableInterrupts(
+ base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
+
+ if (handle->completionCallback != NULL)
+ {
+ handle->completionCallback(base, handle, status, handle->userData);
+ }
+}
+
+#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
+/*!
+ * brief Make sure the bus isn't already pulled down.
+ *
+ * Check the FLEXIO pin status to see whether either of SDA and SCL pin is pulled down.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure..
+ * retval kStatus_Success
+ * retval kStatus_FLEXIO_I2C_Busy
+ */
+status_t FLEXIO_I2C_CheckForBusyBus(FLEXIO_I2C_Type *base)
+{
+ uint32_t mask;
+ /* If in certain loops the SDA/SCL is continuously pulled down, then return bus busy status. */
+ /* The loop count is determined by maximum CPU clock frequency */
+ for (uint32_t i = 0U; i < SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 600000U; ++i)
+ {
+ mask = 1UL << base->SDAPinIndex | 1UL << base->SCLPinIndex;
+ if ((FLEXIO_ReadPinInput(base->flexioBase) & mask) == mask)
+ {
+ return kStatus_Success;
+ }
+ }
+ return kStatus_FLEXIO_I2C_Busy;
+}
+#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
+
+/*!
+ * brief Ungates the FlexIO clock, resets the FlexIO module, and configures the FlexIO I2C
+ * hardware configuration.
+ *
+ * Example
+ code
+ FLEXIO_I2C_Type base = {
+ .flexioBase = FLEXIO,
+ .SDAPinIndex = 0,
+ .SCLPinIndex = 1,
+ .shifterIndex = {0,1},
+ .timerIndex = {0,1}
+ };
+ flexio_i2c_master_config_t config = {
+ .enableInDoze = false,
+ .enableInDebug = true,
+ .enableFastAccess = false,
+ .baudRate_Bps = 100000
+ };
+ FLEXIO_I2C_MasterInit(base, &config, srcClock_Hz);
+ endcode
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param masterConfig Pointer to flexio_i2c_master_config_t structure.
+ * param srcClock_Hz FlexIO source clock in Hz.
+ * retval kStatus_Success Initialization successful
+ * retval kStatus_InvalidArgument The source clock exceed upper range limitation
+*/
+status_t FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
+{
+ assert((base != NULL) && (masterConfig != NULL));
+
+ flexio_shifter_config_t shifterConfig;
+ flexio_timer_config_t timerConfig;
+ uint32_t controlVal = 0;
+ uint16_t timerDiv = 0;
+ status_t result = kStatus_Success;
+
+ (void)memset(&shifterConfig, 0, sizeof(shifterConfig));
+ (void)memset(&timerConfig, 0, sizeof(timerConfig));
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+ /* Ungate flexio clock. */
+ CLOCK_EnableClock(s_flexioClocks[FLEXIO_I2C_GetInstance(base)]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+
+ /* Do hardware configuration. */
+ /* 1. Configure the shifter 0 for tx. */
+ shifterConfig.timerSelect = base->timerIndex[2];
+ shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
+ shifterConfig.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection;
+ shifterConfig.pinSelect = base->SDAPinIndex;
+ shifterConfig.pinPolarity = kFLEXIO_PinActiveLow;
+ shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
+ shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
+ shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
+ shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
+
+ FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
+
+ /* 2. Configure the shifter 1 for rx. */
+ shifterConfig.timerSelect = base->timerIndex[2];
+ shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
+ shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
+ shifterConfig.pinSelect = base->SDAPinIndex;
+ shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
+ shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
+ shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
+ shifterConfig.shifterStop = kFLEXIO_ShifterStopBitLow;
+ shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
+
+ FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
+
+ /*3. Configure the timer 0 and timer 1 for generating bit clock. */
+ /* timer 1 is used to config baudrate */
+ timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
+ timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
+ timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
+ timerConfig.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection;
+ timerConfig.pinSelect = base->SCLPinIndex;
+ timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
+ timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
+ timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
+ timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
+ timerConfig.timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput;
+ timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
+ timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
+ timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
+ timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
+
+ /* Set TIMCMP = (baud rate divider / 2) - 1. */
+ timerDiv = (uint16_t)(srcClock_Hz / masterConfig->baudRate_Bps) / 2U - 1U;
+ /* Calculate and assign the actual baudrate. */
+ base->baudrate = srcClock_Hz / (2U * ((uint32_t)timerDiv + 1U));
+
+ timerConfig.timerCompare = timerDiv;
+
+ FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
+
+ /* timer 0 is used to config total shift clock edges */
+ timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
+ timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
+ timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
+ timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
+ timerConfig.pinSelect = base->SCLPinIndex;
+ timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
+ timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
+ timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
+ timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
+ timerConfig.timerReset = kFLEXIO_TimerResetNever;
+ timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
+ timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
+ timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
+ timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
+
+ /* Set TIMCMP when confinguring transfer bytes. */
+ FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
+
+ /* 4. Configure the timer 2 for controlling shifters. */
+ timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
+ timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
+ timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
+ timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
+ timerConfig.pinSelect = base->SCLPinIndex;
+ timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
+ timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
+ timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
+ timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
+ timerConfig.timerReset = kFLEXIO_TimerResetNever;
+ timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
+ timerConfig.timerEnable = kFLEXIO_TimerEnableOnPrevTimerEnable;
+ timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerCompare;
+ timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
+
+ /* Set TIMCMP[15:0] = (number of bits x 2) - 1. */
+ timerConfig.timerCompare = 8U * 2U - 1U;
+
+ FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[2], &timerConfig);
+
+ /* Configure FLEXIO I2C Master. */
+ controlVal = base->flexioBase->CTRL;
+ controlVal &=
+ ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
+ controlVal |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) |
+ FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
+ if (!masterConfig->enableInDoze)
+ {
+ controlVal |= FLEXIO_CTRL_DOZEN_MASK;
+ }
+
+ base->flexioBase->CTRL = controlVal;
+ /* Disable internal IRQs. */
+ FLEXIO_I2C_MasterDisableInterrupts(
+ base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
+ return result;
+}
+
+/*!
+ * brief De-initializes the FlexIO I2C master peripheral. Calling this API Resets the FlexIO I2C master
+ * shifer and timer config, module can't work unless the FLEXIO_I2C_MasterInit is called.
+ *
+ * param base pointer to FLEXIO_I2C_Type structure.
+ */
+void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base)
+{
+ base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = 0;
+ base->flexioBase->SHIFTCTL[base->shifterIndex[0]] = 0;
+ base->flexioBase->SHIFTCFG[base->shifterIndex[1]] = 0;
+ base->flexioBase->SHIFTCTL[base->shifterIndex[1]] = 0;
+ base->flexioBase->TIMCFG[base->timerIndex[0]] = 0;
+ base->flexioBase->TIMCMP[base->timerIndex[0]] = 0;
+ base->flexioBase->TIMCTL[base->timerIndex[0]] = 0;
+ base->flexioBase->TIMCFG[base->timerIndex[1]] = 0;
+ base->flexioBase->TIMCMP[base->timerIndex[1]] = 0;
+ base->flexioBase->TIMCTL[base->timerIndex[1]] = 0;
+ base->flexioBase->TIMCFG[base->timerIndex[2]] = 0;
+ base->flexioBase->TIMCMP[base->timerIndex[2]] = 0;
+ base->flexioBase->TIMCTL[base->timerIndex[2]] = 0;
+ /* Clear the shifter flag. */
+ base->flexioBase->SHIFTSTAT = (1UL << base->shifterIndex[0]);
+ base->flexioBase->SHIFTSTAT = (1UL << base->shifterIndex[1]);
+ /* Clear the timer flag. */
+ base->flexioBase->TIMSTAT = (1UL << base->timerIndex[0]);
+ base->flexioBase->TIMSTAT = (1UL << base->timerIndex[1]);
+ base->flexioBase->TIMSTAT = (1UL << base->timerIndex[2]);
+}
+
+/*!
+ * brief Gets the default configuration to configure the FlexIO module. The configuration
+ * can be used directly for calling the FLEXIO_I2C_MasterInit().
+ *
+ * Example:
+ code
+ flexio_i2c_master_config_t config;
+ FLEXIO_I2C_MasterGetDefaultConfig(&config);
+ endcode
+ * param masterConfig Pointer to flexio_i2c_master_config_t structure.
+*/
+void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig)
+{
+ assert(masterConfig != NULL);
+
+ /* Initializes the configure structure to zero. */
+ (void)memset(masterConfig, 0, sizeof(*masterConfig));
+
+ masterConfig->enableMaster = true;
+ masterConfig->enableInDoze = false;
+ masterConfig->enableInDebug = true;
+ masterConfig->enableFastAccess = false;
+
+ /* Default baud rate at 100kbps. */
+ masterConfig->baudRate_Bps = 100000U;
+}
+
+/*!
+ * brief Gets the FlexIO I2C master status flags.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure
+ * return Status flag, use status flag to AND #_flexio_i2c_master_status_flags can get the related status.
+ */
+
+uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base)
+{
+ uint32_t status = 0;
+
+ status =
+ ((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])) >> base->shifterIndex[0]);
+ status |=
+ (((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1]))
+ << 1U);
+ status |=
+ (((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1]))
+ << 2U);
+
+ return status;
+}
+
+/*!
+ * brief Clears the FlexIO I2C master status flags.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param mask Status flag.
+ * The parameter can be any combination of the following values:
+ * arg kFLEXIO_I2C_RxFullFlag
+ * arg kFLEXIO_I2C_ReceiveNakFlag
+ */
+
+void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask)
+{
+ if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
+ {
+ FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[0]);
+ }
+
+ if ((mask & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
+ {
+ FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
+ }
+
+ if ((mask & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
+ {
+ FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
+ }
+}
+
+/*!
+ * brief Enables the FlexIO i2c master interrupt requests.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param mask Interrupt source.
+ * Currently only one interrupt request source:
+ * arg kFLEXIO_I2C_TransferCompleteInterruptEnable
+ */
+void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
+{
+ if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable) != 0U)
+ {
+ FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
+ }
+ if ((mask & (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable) != 0U)
+ {
+ FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
+ }
+}
+
+/*!
+ * brief Disables the FlexIO I2C master interrupt requests.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param mask Interrupt source.
+ */
+void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
+{
+ if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable) != 0U)
+ {
+ FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
+ }
+ if ((mask & (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable) != 0U)
+ {
+ FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
+ }
+}
+
+/*!
+ * brief Sets the FlexIO I2C master transfer baudrate.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure
+ * param baudRate_Bps the baud rate value in HZ
+ * param srcClock_Hz source clock in HZ
+ */
+void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
+{
+ uint16_t timerDiv = 0;
+ FLEXIO_Type *flexioBase = base->flexioBase;
+
+ /* Set TIMCMP = (baud rate divider / 2) - 1.*/
+ timerDiv = (uint16_t)((srcClock_Hz / baudRate_Bps) / 2U - 1U);
+
+ flexioBase->TIMCMP[base->timerIndex[1]] = timerDiv;
+
+ /* Calculate and assign the actual baudrate. */
+ base->baudrate = srcClock_Hz / (2U * ((uint32_t)timerDiv + 1U));
+}
+
+/*!
+ * brief Sets the number of bytes to be transferred from a start signal to a stop signal.
+ *
+ * note Call this API before a transfer begins because the timer generates a number of clocks according
+ * to the number of bytes that need to be transferred.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param count Number of bytes need to be transferred from a start signal to a re-start/stop signal
+ * retval kStatus_Success Successfully configured the count.
+ * retval kStatus_InvalidArgument Input argument is invalid.
+ */
+status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint16_t count)
+{
+ /* Calculate whether the transfer count is larger than the max value compare register can achieve */
+ if (count > ((0xFFFFUL - 1UL) / (16UL + 1UL + 1UL)))
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ uint32_t timerConfig = 0U;
+ FLEXIO_Type *flexioBase = base->flexioBase;
+
+ flexioBase->TIMCMP[base->timerIndex[0]] = (uint32_t)count * 18U + 1U;
+ timerConfig = flexioBase->TIMCFG[base->timerIndex[0]];
+ timerConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
+ timerConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare);
+ flexioBase->TIMCFG[base->timerIndex[0]] = timerConfig;
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Sends START + 7-bit address to the bus.
+ *
+ * note This API should be called when the transfer configuration is ready to send a START signal
+ * and 7-bit address to the bus. This is a non-blocking API, which returns directly after the address
+ * is put into the data register but the address transfer is not finished on the bus. Ensure that
+ * the kFLEXIO_I2C_RxFullFlag status is asserted before calling this API.
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param address 7-bit address.
+ * param direction transfer direction.
+ * This parameter is one of the values in flexio_i2c_direction_t:
+ * arg kFLEXIO_I2C_Write: Transmit
+ * arg kFLEXIO_I2C_Read: Receive
+ */
+
+void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction)
+{
+ uint32_t data;
+
+ data = ((uint32_t)address) << 1U | ((direction == kFLEXIO_I2C_Read) ? 1U : 0U);
+
+ FLEXIO_I2C_MasterWriteByte(base, data);
+}
+
+/*!
+ * brief Sends the repeated start signal on the bus.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ */
+void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base)
+{
+ /* Prepare for RESTART condition, no stop.*/
+ FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
+}
+
+/*!
+ * brief Sends the stop signal on the bus.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ */
+void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base)
+{
+ /* Prepare normal stop. */
+ (void)FLEXIO_I2C_MasterSetTransferCount(base, 0x0U);
+ FLEXIO_I2C_MasterWriteByte(base, 0x0U);
+}
+
+/*!
+ * brief Sends the stop signal when transfer is still on-going.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ */
+void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base)
+{
+ uint32_t tmpConfig;
+
+ /* Prepare abort stop. */
+ /* Disable timer 0. */
+ tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[0]];
+ tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
+ tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPinBothEdge);
+ base->flexioBase->TIMCFG[base->timerIndex[0]] = tmpConfig;
+
+ /* Disable timer 1. */
+ tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[1]];
+ tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
+ tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPinBothEdge);
+ base->flexioBase->TIMCFG[base->timerIndex[1]] = tmpConfig;
+}
+
+/*!
+ * brief Configures the sent ACK/NAK for the following byte.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param enable True to configure send ACK, false configure to send NAK.
+ */
+void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable)
+{
+ uint32_t tmpConfig = 0;
+
+ tmpConfig = base->flexioBase->SHIFTCFG[base->shifterIndex[0]];
+ tmpConfig &= ~FLEXIO_SHIFTCFG_SSTOP_MASK;
+ if (enable)
+ {
+ tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitLow);
+ }
+ else
+ {
+ tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitHigh);
+ }
+ base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = tmpConfig;
+}
+
+/*!
+ * brief Sends a buffer of data in bytes.
+ *
+ * note This function blocks via polling until all bytes have been sent.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param txBuff The data bytes to send.
+ * param txSize The number of data bytes to send.
+ * retval kStatus_Success Successfully write data.
+ * retval kStatus_FLEXIO_I2C_Nak Receive NAK during writing data.
+ * retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
+ */
+status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize)
+{
+ assert(txBuff != NULL);
+ assert(txSize != 0U);
+
+ uint32_t status;
+#if I2C_RETRY_TIMES
+ uint32_t waitTimes = I2C_RETRY_TIMES;
+#endif
+
+ while (0U != txSize--)
+ {
+ FLEXIO_I2C_MasterWriteByte(base, *txBuff++);
+
+ /* Wait until data transfer complete. */
+#if I2C_RETRY_TIMES
+ waitTimes = I2C_RETRY_TIMES;
+ while ((0U == ((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U == ((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
+ {
+ }
+#endif
+
+ if ((status & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
+ {
+ FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
+ return kStatus_FLEXIO_I2C_Nak;
+ }
+ }
+ return kStatus_Success;
+}
+
+/*!
+ * brief Receives a buffer of bytes.
+ *
+ * note This function blocks via polling until all bytes have been received.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param rxBuff The buffer to store the received bytes.
+ * param rxSize The number of data bytes to be received.
+ * retval kStatus_Success Successfully read data.
+ * retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
+ */
+status_t FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize)
+{
+ assert(rxBuff != NULL);
+ assert(rxSize != 0U);
+
+#if I2C_RETRY_TIMES
+ uint32_t waitTimes = I2C_RETRY_TIMES;
+#endif
+
+ while (0U != rxSize--)
+ {
+ /* Wait until data transfer complete. */
+#if I2C_RETRY_TIMES
+ waitTimes = I2C_RETRY_TIMES;
+ while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
+ {
+ }
+#endif
+ *rxBuff++ = FLEXIO_I2C_MasterReadByte(base);
+ }
+ return kStatus_Success;
+}
+
+/*!
+ * brief Performs a master polling transfer on the I2C bus.
+ *
+ * note The API does not return until the transfer succeeds or fails due
+ * to receiving NAK.
+ *
+ * param base pointer to FLEXIO_I2C_Type structure.
+ * param xfer pointer to flexio_i2c_master_transfer_t structure.
+ * return status of status_t.
+ */
+status_t FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type *base, flexio_i2c_master_transfer_t *xfer)
+{
+ assert(xfer != NULL);
+
+#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
+ /* Return an error if the bus is already in use not by us.*/
+ status_t status = FLEXIO_I2C_CheckForBusyBus(base);
+ if (status != kStatus_Success)
+ {
+ return status;
+ }
+#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
+
+ flexio_i2c_master_handle_t tmpHandle;
+ uint32_t statusFlags;
+ status_t result = kStatus_Success;
+#if I2C_RETRY_TIMES
+ uint32_t waitTimes = I2C_RETRY_TIMES;
+#endif
+
+ /* Zero the handle. */
+ (void)memset(&tmpHandle, 0, sizeof(tmpHandle));
+
+ /* Set up transfer machine. */
+ result = FLEXIO_I2C_MasterTransferInitStateMachine(base, &tmpHandle, xfer);
+ if (result != kStatus_Success)
+ {
+ return result;
+ }
+
+ do
+ {
+ /* Wait either tx empty or rx full flag is asserted. */
+#if I2C_RETRY_TIMES
+ waitTimes = I2C_RETRY_TIMES;
+ while ((0U == ((statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base)) &
+ ((uint32_t)kFLEXIO_I2C_TxEmptyFlag | (uint32_t)kFLEXIO_I2C_RxFullFlag))) &&
+ (0U != --waitTimes))
+ {
+ }
+ if (0U == waitTimes)
+ {
+ return kStatus_FLEXIO_I2C_Timeout;
+ }
+#else
+ while (0U == ((statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base)) &
+ ((uint32_t)kFLEXIO_I2C_TxEmptyFlag | (uint32_t)kFLEXIO_I2C_RxFullFlag)))
+ {
+ }
+#endif
+ FLEXIO_ClearTimerStatusFlags(base->flexioBase, ((1UL << base->timerIndex[0]) | (1UL << base->timerIndex[1])));
+ result = FLEXIO_I2C_MasterTransferRunStateMachine(base, &tmpHandle, statusFlags);
+
+ } while ((tmpHandle.state != (uint8_t)kFLEXIO_I2C_Idle) && (result == kStatus_Success));
+
+ /* Timer disable on timer compare, wait until bit clock TSF set, which means timer disable and stop has been sent.
+ */
+ while (0U == (FLEXIO_GetTimerStatusFlags(base->flexioBase) & (1UL << base->timerIndex[1])))
+ {
+ }
+
+ return result;
+}
+
+/*!
+ * brief Initializes the I2C handle which is used in transactional functions.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param handle Pointer to flexio_i2c_master_handle_t structure to store the transfer state.
+ * param callback Pointer to user callback function.
+ * param userData User param passed to the callback function.
+ * retval kStatus_Success Successfully create the handle.
+ * retval kStatus_OutOfRange The FlexIO type/handle/isr table out of range.
+ */
+status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
+ flexio_i2c_master_handle_t *handle,
+ flexio_i2c_master_transfer_callback_t callback,
+ void *userData)
+{
+ assert(handle != NULL);
+
+ IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
+
+ /* Zero the handle. */
+ (void)memset(handle, 0, sizeof(*handle));
+
+ /* Register callback and userData. */
+ handle->completionCallback = callback;
+ handle->userData = userData;
+
+ /* Clear pending NVIC IRQ before enable NVIC IRQ. */
+ NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_I2C_GetInstance(base)]);
+ (void)EnableIRQ(flexio_irqs[FLEXIO_I2C_GetInstance(base)]);
+
+ /* Save the context in global variables to support the double weak mechanism. */
+ return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2C_MasterTransferHandleIRQ);
+}
+
+/*!
+ * brief Performs a master interrupt non-blocking transfer on the I2C bus.
+ *
+ * note The API returns immediately after the transfer initiates.
+ * Call FLEXIO_I2C_MasterTransferGetCount to poll the transfer status to check whether
+ * the transfer is finished. If the return status is not kStatus_FLEXIO_I2C_Busy, the transfer
+ * is finished.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure
+ * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
+ * param xfer pointer to flexio_i2c_master_transfer_t structure
+ * retval kStatus_Success Successfully start a transfer.
+ * retval kStatus_FLEXIO_I2C_Busy FlexIO I2C is not idle, is running another transfer.
+ */
+status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
+ flexio_i2c_master_handle_t *handle,
+ flexio_i2c_master_transfer_t *xfer)
+{
+ assert(handle != NULL);
+ assert(xfer != NULL);
+
+ status_t result = kStatus_Success;
+
+#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
+ /* Return an error if the bus is already in use not by us.*/
+ result = FLEXIO_I2C_CheckForBusyBus(base);
+ if (result != kStatus_Success)
+ {
+ return result;
+ }
+#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
+
+ if (handle->state != (uint8_t)kFLEXIO_I2C_Idle)
+ {
+ return kStatus_FLEXIO_I2C_Busy;
+ }
+ else
+ {
+ /* Set up transfer machine. */
+ result = FLEXIO_I2C_MasterTransferInitStateMachine(base, handle, xfer);
+ if (result != kStatus_Success)
+ {
+ return result;
+ }
+
+ /* Enable both tx empty and rxfull interrupt. */
+ FLEXIO_I2C_MasterEnableInterrupts(
+ base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
+
+ return kStatus_Success;
+ }
+}
+
+/*!
+ * brief Aborts an interrupt non-blocking transfer early.
+ *
+ * note This API can be called at any time when an interrupt non-blocking transfer initiates
+ * to abort the transfer early.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure
+ * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
+ */
+void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle)
+{
+ assert(handle != NULL);
+
+ /* Disable interrupts. */
+ FLEXIO_I2C_MasterDisableInterrupts(
+ base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
+
+ /* Reset to idle state. */
+ handle->state = (uint8_t)kFLEXIO_I2C_Idle;
+}
+
+/*!
+ * brief Gets the master transfer status during a interrupt non-blocking transfer.
+ *
+ * param base Pointer to FLEXIO_I2C_Type structure.
+ * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state.
+ * param count Number of bytes transferred so far by the non-blocking transaction.
+ * retval kStatus_InvalidArgument count is Invalid.
+ * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
+ * retval kStatus_Success Successfully return the count.
+ */
+status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count)
+{
+ if (NULL == count)
+ {
+ return kStatus_InvalidArgument;
+ }
+
+ /* Catch when there is not an active transfer. */
+ if (handle->state == (uint8_t)kFLEXIO_I2C_Idle)
+ {
+ *count = 0;
+ return kStatus_NoTransferInProgress;
+ }
+
+ *count = handle->transferSize - handle->transfer.dataSize;
+
+ return kStatus_Success;
+}
+
+/*!
+ * brief Master interrupt handler.
+ *
+ * param i2cType Pointer to FLEXIO_I2C_Type structure
+ * param i2cHandle Pointer to flexio_i2c_master_transfer_t structure
+ */
+void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle)
+{
+ FLEXIO_I2C_Type *base = (FLEXIO_I2C_Type *)i2cType;
+ flexio_i2c_master_handle_t *handle = (flexio_i2c_master_handle_t *)i2cHandle;
+ uint32_t statusFlags;
+ status_t result;
+
+ statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base);
+
+ result = FLEXIO_I2C_MasterTransferRunStateMachine(base, handle, statusFlags);
+
+ if (handle->state == (uint8_t)kFLEXIO_I2C_Idle)
+ {
+ FLEXIO_I2C_MasterTransferComplete(base, handle, result);
+ }
+}