123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260 |
- /*
- * 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));
- /* Delay at least one clock cycle so that the restart setup time is up to spec standard. */
- SDK_DelayAtLeastUs(1000000UL / base->baudrate, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
- 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);
- }
- }
|