Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL43Z/drivers/fsl_flexio_i2c_master.c
- Committer:
- <>
- Date:
- 2016-10-28
- Revision:
- 149:156823d33999
- Parent:
- targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_flexio_i2c_master.c@ 121:7f86b4238bec
File content as of revision 149:156823d33999:
/* * Copyright (c) 2015, Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * o Neither the name of Freescale Semiconductor, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "fsl_flexio_i2c_master.h" /******************************************************************************* * Definitions ******************************************************************************/ /*! @brief FLEXIO I2C transfer state */ enum _flexio_i2c_master_transfer_states { kFLEXIO_I2C_Idle = 0x0U, /*!< I2C bus idle */ kFLEXIO_I2C_CheckAddress = 0x1U, /*!< 7-bit address check state */ 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 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 check address state. */ handle->state = kFLEXIO_I2C_CheckAddress; /* Clear all status before transfer. */ FLEXIO_I2C_MasterClearStatusFlags(base, kFLEXIO_I2C_ReceiveNakFlag); /* Calculate whether need to send re-start. */ needRestart = (handle->transfer.subaddressSize != 0) && (handle->transfer.direction == kFLEXIO_I2C_Read); /* Calculate total byte count in a frame. */ byteCount = 1; if (!needRestart) { byteCount += handle->transfer.dataSize; } if (handle->transfer.subaddressSize != 0) { byteCount += handle->transfer.subaddressSize; /* Next state, send command byte. */ handle->state = kFLEXIO_I2C_SendCommand; } /* Configure data count. */ if (FLEXIO_I2C_MasterSetTransferCount(base, byteCount) != kStatus_Success) { return kStatus_InvalidArgument; } while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])))) { } /* Send address byte first. */ if (needRestart) { FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Write); } else { FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, handle->transfer.direction); } return kStatus_Success; } static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, uint32_t statusFlags) { if (statusFlags & kFLEXIO_I2C_ReceiveNakFlag) { /* Clear receive nak flag. */ FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]); if ((!((handle->state == kFLEXIO_I2C_SendData) && (handle->transfer.dataSize == 0U))) && (!(((handle->state == kFLEXIO_I2C_ReceiveData) || (handle->state == kFLEXIO_I2C_ReceiveDataBegin)) && (handle->transfer.dataSize == 1U)))) { FLEXIO_I2C_MasterReadByte(base); FLEXIO_I2C_MasterAbortStop(base); handle->state = kFLEXIO_I2C_Idle; return kStatus_FLEXIO_I2C_Nak; } } if (handle->state == kFLEXIO_I2C_CheckAddress) { if (handle->transfer.direction == kFLEXIO_I2C_Write) { /* Next state, send data. */ handle->state = kFLEXIO_I2C_SendData; } else { /* Next state, receive data begin. */ handle->state = kFLEXIO_I2C_ReceiveDataBegin; } } if ((statusFlags & kFLEXIO_I2C_RxFullFlag) && (handle->state != kFLEXIO_I2C_ReceiveData)) { FLEXIO_I2C_MasterReadByte(base); } switch (handle->state) { case kFLEXIO_I2C_SendCommand: if (statusFlags & kFLEXIO_I2C_TxEmptyFlag) { if (handle->transfer.subaddressSize > 0) { handle->transfer.subaddressSize--; FLEXIO_I2C_MasterWriteByte( base, ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize))); if (handle->transfer.subaddressSize == 0) { /* Load re-start in advance. */ if (handle->transfer.direction == kFLEXIO_I2C_Read) { while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])))) { } FLEXIO_I2C_MasterRepeatedStart(base); } } } else { if (handle->transfer.direction == kFLEXIO_I2C_Write) { /* Next state, send data. */ handle->state = kFLEXIO_I2C_SendData; /* Send first byte of data. */ if (handle->transfer.dataSize > 0) { FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data); handle->transfer.data++; handle->transfer.dataSize--; } } else { FLEXIO_I2C_MasterSetTransferCount(base, (handle->transfer.dataSize + 1)); FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Read); /* Next state, receive data begin. */ handle->state = kFLEXIO_I2C_ReceiveDataBegin; } } } break; /* Send command byte. */ case kFLEXIO_I2C_SendData: if (statusFlags & kFLEXIO_I2C_TxEmptyFlag) { /* Send one byte of data. */ if (handle->transfer.dataSize > 0) { FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data); handle->transfer.data++; handle->transfer.dataSize--; } else { FLEXIO_I2C_MasterStop(base); handle->state = kFLEXIO_I2C_Idle; } } break; case kFLEXIO_I2C_ReceiveDataBegin: if (statusFlags & kFLEXIO_I2C_TxEmptyFlag) { /* Read one byte of data. */ FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU); /* Send nak at the last receive byte. */ if (handle->transfer.dataSize == 1) { FLEXIO_I2C_MasterEnableAck(base, false); while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])))) { } FLEXIO_I2C_MasterStop(base); } else { FLEXIO_I2C_MasterEnableAck(base, true); } } else { handle->state = kFLEXIO_I2C_ReceiveData; } break; case kFLEXIO_I2C_ReceiveData: if (statusFlags & kFLEXIO_I2C_RxFullFlag) { *handle->transfer.data = FLEXIO_I2C_MasterReadByte(base); handle->transfer.data++; /* Receive one byte of data. */ if (handle->transfer.dataSize--) { if (handle->transfer.dataSize != 0) { FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU); } else { FLEXIO_I2C_MasterDisableInterrupts(base, kFLEXIO_I2C_RxFullInterruptEnable); handle->state = kFLEXIO_I2C_Idle; } /* Send nak at the last receive byte. */ if (handle->transfer.dataSize == 1) { FLEXIO_I2C_MasterEnableAck(base, false); while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])))) { } FLEXIO_I2C_MasterStop(base); } } } break; default: 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, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable); if (handle->completionCallback) { handle->completionCallback(base, handle, status, handle->userData); } } void FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz) { assert(base && masterConfig); flexio_shifter_config_t shifterConfig; flexio_timer_config_t timerConfig; uint32_t controlVal = 0; memset(&shifterConfig, 0, sizeof(shifterConfig)); memset(&timerConfig, 0, sizeof(timerConfig)); /* Ungate flexio clock. */ CLOCK_EnableClock(kCLOCK_Flexio0); FLEXIO_Reset(base->flexioBase); /* Do hardware configuration. */ /* 1. Configure the shifter 0 for tx. */ shifterConfig.timerSelect = base->timerIndex[1]; 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[1]; 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 for generating bit clock. */ 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_TimerModeDual8BitBaudBit; timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset; timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput; timerConfig.timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput; timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare; timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh; timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable; timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled; /* Set TIMCMP[7:0] = (baud rate divider / 2) - 1. */ timerConfig.timerCompare = (srcClock_Hz / masterConfig->baudRate_Bps) / 2 - 1; FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig); /* 4. Configure the timer 1 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 = 8 * 2 - 1; FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &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_DOZEN(masterConfig->enableInDoze) | FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) | FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster)); base->flexioBase->CTRL = controlVal; } void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base) { FLEXIO_Deinit(base->flexioBase); } void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig) { assert(masterConfig); masterConfig->enableMaster = true; masterConfig->enableInDoze = false; masterConfig->enableInDebug = true; masterConfig->enableFastAccess = false; /* Default baud rate at 100kbps. */ masterConfig->baudRate_Bps = 100000U; } uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base) { uint32_t status = 0; status = ((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]); status |= (((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1])) << 1U); status |= (((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1])) << 2U); return status; } void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask) { if (mask & kFLEXIO_I2C_TxEmptyFlag) { FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]); } if (mask & kFLEXIO_I2C_RxFullFlag) { FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]); } if (mask & kFLEXIO_I2C_ReceiveNakFlag) { FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]); } } void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask) { if (mask & kFLEXIO_I2C_TxEmptyInterruptEnable) { FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]); } if (mask & kFLEXIO_I2C_RxFullInterruptEnable) { FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]); } } void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask) { if (mask & kFLEXIO_I2C_TxEmptyInterruptEnable) { FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]); } if (mask & kFLEXIO_I2C_RxFullInterruptEnable) { FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]); } } void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) { uint16_t timerDiv = 0; uint16_t timerCmp = 0; FLEXIO_Type *flexioBase = base->flexioBase; /* Set TIMCMP[7:0] = (baud rate divider / 2) - 1.*/ timerDiv = srcClock_Hz / baudRate_Bps; timerDiv = timerDiv / 2 - 1U; timerCmp = flexioBase->TIMCMP[base->timerIndex[0]]; timerCmp &= 0xFF00; timerCmp |= timerDiv; flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp; } status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint8_t count) { if (count > 14U) { return kStatus_InvalidArgument; } uint16_t timerCmp = 0; uint32_t timerConfig = 0; FLEXIO_Type *flexioBase = base->flexioBase; timerCmp = flexioBase->TIMCMP[base->timerIndex[0]]; timerCmp &= 0x00FFU; timerCmp |= (count * 18 + 1U) << 8U; flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp; 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; } 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); } void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base) { /* Prepare for RESTART condition, no stop.*/ FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU); } void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base) { /* Prepare normal stop. */ FLEXIO_I2C_MasterSetTransferCount(base, 0x0U); FLEXIO_I2C_MasterWriteByte(base, 0x0U); } void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base) { uint32_t tmpConfig; /* Prepare abort stop. */ 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; } 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; } status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize) { assert(txBuff); assert(txSize); uint32_t status; while (txSize--) { FLEXIO_I2C_MasterWriteByte(base, *txBuff++); /* Wait until data transfer complete. */ while (!((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & kFLEXIO_I2C_RxFullFlag)) { } if (status & kFLEXIO_I2C_ReceiveNakFlag) { FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]); return kStatus_FLEXIO_I2C_Nak; } } return kStatus_Success; } void FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize) { assert(rxBuff); assert(rxSize); while (rxSize--) { /* Wait until data transfer complete. */ while (!(FLEXIO_I2C_MasterGetStatusFlags(base) & kFLEXIO_I2C_RxFullFlag)) { } *rxBuff++ = FLEXIO_I2C_MasterReadByte(base); } } 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); IRQn_Type flexio_irqs[] = FLEXIO_IRQS; /* Zero the handle. */ memset(handle, 0, sizeof(*handle)); /* Register callback and userData. */ handle->completionCallback = callback; handle->userData = userData; /* Enable interrupt in NVIC. */ EnableIRQ(flexio_irqs[0]); /* Save the context in global variables to support the double weak mechanism. */ return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2C_MasterTransferHandleIRQ); } status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, flexio_i2c_master_transfer_t *xfer) { assert(handle); assert(xfer); if (handle->state != kFLEXIO_I2C_Idle) { return kStatus_FLEXIO_I2C_Busy; } else { /* Set up transfer machine. */ FLEXIO_I2C_MasterTransferInitStateMachine(base, handle, xfer); /* Enable both tx empty and rxfull interrupt. */ FLEXIO_I2C_MasterEnableInterrupts(base, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable); return kStatus_Success; } } void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle) { assert(handle); /* Disable interrupts. */ FLEXIO_I2C_MasterDisableInterrupts(base, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable); /* Reset to idle state. */ handle->state = kFLEXIO_I2C_Idle; } status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count) { if (!count) { return kStatus_InvalidArgument; } *count = handle->transferSize - handle->transfer.dataSize; return kStatus_Success; } 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 == kFLEXIO_I2C_Idle) { FLEXIO_I2C_MasterTransferComplete(base, handle, result); } }