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_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_i2c.c@180:d79f997829d6, 2017-12-18 (annotated)
- Committer:
- Anythingconnected
- Date:
- Mon Dec 18 10:14:27 2017 +0000
- Revision:
- 180:d79f997829d6
- Parent:
- 154:37f96f9d4de2
Getting byte by byte read to work
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 154:37f96f9d4de2 | 1 | /* |
<> | 154:37f96f9d4de2 | 2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. |
<> | 154:37f96f9d4de2 | 3 | * All rights reserved. |
<> | 154:37f96f9d4de2 | 4 | * |
<> | 154:37f96f9d4de2 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
<> | 154:37f96f9d4de2 | 6 | * are permitted provided that the following conditions are met: |
<> | 154:37f96f9d4de2 | 7 | * |
<> | 154:37f96f9d4de2 | 8 | * o Redistributions of source code must retain the above copyright notice, this list |
<> | 154:37f96f9d4de2 | 9 | * of conditions and the following disclaimer. |
<> | 154:37f96f9d4de2 | 10 | * |
<> | 154:37f96f9d4de2 | 11 | * o Redistributions in binary form must reproduce the above copyright notice, this |
<> | 154:37f96f9d4de2 | 12 | * list of conditions and the following disclaimer in the documentation and/or |
<> | 154:37f96f9d4de2 | 13 | * other materials provided with the distribution. |
<> | 154:37f96f9d4de2 | 14 | * |
<> | 154:37f96f9d4de2 | 15 | * o Neither the name of Freescale Semiconductor, Inc. nor the names of its |
<> | 154:37f96f9d4de2 | 16 | * contributors may be used to endorse or promote products derived from this |
<> | 154:37f96f9d4de2 | 17 | * software without specific prior written permission. |
<> | 154:37f96f9d4de2 | 18 | * |
<> | 154:37f96f9d4de2 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
<> | 154:37f96f9d4de2 | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
<> | 154:37f96f9d4de2 | 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
<> | 154:37f96f9d4de2 | 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
<> | 154:37f96f9d4de2 | 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
<> | 154:37f96f9d4de2 | 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
<> | 154:37f96f9d4de2 | 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
<> | 154:37f96f9d4de2 | 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
<> | 154:37f96f9d4de2 | 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
<> | 154:37f96f9d4de2 | 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
<> | 154:37f96f9d4de2 | 29 | */ |
<> | 154:37f96f9d4de2 | 30 | #include "fsl_i2c.h" |
<> | 154:37f96f9d4de2 | 31 | |
<> | 154:37f96f9d4de2 | 32 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 33 | * Definitions |
<> | 154:37f96f9d4de2 | 34 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 35 | |
<> | 154:37f96f9d4de2 | 36 | /*! @brief i2c transfer state. */ |
<> | 154:37f96f9d4de2 | 37 | enum _i2c_transfer_states |
<> | 154:37f96f9d4de2 | 38 | { |
<> | 154:37f96f9d4de2 | 39 | kIdleState = 0x0U, /*!< I2C bus idle. */ |
<> | 154:37f96f9d4de2 | 40 | kCheckAddressState = 0x1U, /*!< 7-bit address check state. */ |
<> | 154:37f96f9d4de2 | 41 | kSendCommandState = 0x2U, /*!< Send command byte phase. */ |
<> | 154:37f96f9d4de2 | 42 | kSendDataState = 0x3U, /*!< Send data transfer phase. */ |
<> | 154:37f96f9d4de2 | 43 | kReceiveDataBeginState = 0x4U, /*!< Receive data transfer phase begin. */ |
<> | 154:37f96f9d4de2 | 44 | kReceiveDataState = 0x5U, /*!< Receive data transfer phase. */ |
<> | 154:37f96f9d4de2 | 45 | }; |
<> | 154:37f96f9d4de2 | 46 | |
<> | 154:37f96f9d4de2 | 47 | /*! @brief Common sets of flags used by the driver. */ |
<> | 154:37f96f9d4de2 | 48 | enum _i2c_flag_constants |
<> | 154:37f96f9d4de2 | 49 | { |
<> | 154:37f96f9d4de2 | 50 | /*! All flags which are cleared by the driver upon starting a transfer. */ |
<> | 154:37f96f9d4de2 | 51 | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT |
<> | 154:37f96f9d4de2 | 52 | kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag | kI2C_StartDetectFlag | kI2C_StopDetectFlag, |
<> | 154:37f96f9d4de2 | 53 | kIrqFlags = kI2C_GlobalInterruptEnable | kI2C_StartStopDetectInterruptEnable, |
<> | 154:37f96f9d4de2 | 54 | #elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 55 | kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag | kI2C_StopDetectFlag, |
<> | 154:37f96f9d4de2 | 56 | kIrqFlags = kI2C_GlobalInterruptEnable | kI2C_StopDetectInterruptEnable, |
<> | 154:37f96f9d4de2 | 57 | #else |
<> | 154:37f96f9d4de2 | 58 | kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag, |
<> | 154:37f96f9d4de2 | 59 | kIrqFlags = kI2C_GlobalInterruptEnable, |
<> | 154:37f96f9d4de2 | 60 | #endif |
<> | 154:37f96f9d4de2 | 61 | |
<> | 154:37f96f9d4de2 | 62 | }; |
<> | 154:37f96f9d4de2 | 63 | |
<> | 154:37f96f9d4de2 | 64 | /*! @brief Typedef for interrupt handler. */ |
<> | 154:37f96f9d4de2 | 65 | typedef void (*i2c_isr_t)(I2C_Type *base, void *i2cHandle); |
<> | 154:37f96f9d4de2 | 66 | |
<> | 154:37f96f9d4de2 | 67 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 68 | * Prototypes |
<> | 154:37f96f9d4de2 | 69 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 70 | |
<> | 154:37f96f9d4de2 | 71 | /*! |
<> | 154:37f96f9d4de2 | 72 | * @brief Get instance number for I2C module. |
<> | 154:37f96f9d4de2 | 73 | * |
<> | 154:37f96f9d4de2 | 74 | * @param base I2C peripheral base address. |
<> | 154:37f96f9d4de2 | 75 | */ |
<> | 154:37f96f9d4de2 | 76 | uint32_t I2C_GetInstance(I2C_Type *base); |
<> | 154:37f96f9d4de2 | 77 | |
<> | 154:37f96f9d4de2 | 78 | /*! |
<> | 154:37f96f9d4de2 | 79 | * @brief Set SCL/SDA hold time, this API receives SCL stop hold time, calculate the |
<> | 154:37f96f9d4de2 | 80 | * closest SCL divider and MULT value for the SDA hold time, SCL start and SCL stop |
<> | 154:37f96f9d4de2 | 81 | * hold time. To reduce the ROM size, SDA/SCL hold value mapping table is not provided, |
<> | 154:37f96f9d4de2 | 82 | * assume SCL divider = SCL stop hold value *2 to get the closest SCL divider value and MULT |
<> | 154:37f96f9d4de2 | 83 | * value, then the related SDA hold time, SCL start and SCL stop hold time is used. |
<> | 154:37f96f9d4de2 | 84 | * |
<> | 154:37f96f9d4de2 | 85 | * @param base I2C peripheral base address. |
<> | 154:37f96f9d4de2 | 86 | * @param sourceClock_Hz I2C functional clock frequency in Hertz. |
<> | 154:37f96f9d4de2 | 87 | * @param sclStopHoldTime_ns SCL stop hold time in ns. |
<> | 154:37f96f9d4de2 | 88 | */ |
<> | 154:37f96f9d4de2 | 89 | static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz); |
<> | 154:37f96f9d4de2 | 90 | |
<> | 154:37f96f9d4de2 | 91 | /*! |
<> | 154:37f96f9d4de2 | 92 | * @brief Set up master transfer, send slave address and decide the initial |
<> | 154:37f96f9d4de2 | 93 | * transfer state. |
<> | 154:37f96f9d4de2 | 94 | * |
<> | 154:37f96f9d4de2 | 95 | * @param base I2C peripheral base address. |
<> | 154:37f96f9d4de2 | 96 | * @param handle pointer to i2c_master_handle_t structure which stores the transfer state. |
<> | 154:37f96f9d4de2 | 97 | * @param xfer pointer to i2c_master_transfer_t structure. |
<> | 154:37f96f9d4de2 | 98 | */ |
<> | 154:37f96f9d4de2 | 99 | static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer); |
<> | 154:37f96f9d4de2 | 100 | |
<> | 154:37f96f9d4de2 | 101 | /*! |
<> | 154:37f96f9d4de2 | 102 | * @brief Check and clear status operation. |
<> | 154:37f96f9d4de2 | 103 | * |
<> | 154:37f96f9d4de2 | 104 | * @param base I2C peripheral base address. |
<> | 154:37f96f9d4de2 | 105 | * @param status current i2c hardware status. |
<> | 154:37f96f9d4de2 | 106 | * @retval kStatus_Success No error found. |
<> | 154:37f96f9d4de2 | 107 | * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. |
<> | 154:37f96f9d4de2 | 108 | * @retval kStatus_I2C_Nak Received Nak error. |
<> | 154:37f96f9d4de2 | 109 | */ |
<> | 154:37f96f9d4de2 | 110 | static status_t I2C_CheckAndClearError(I2C_Type *base, uint32_t status); |
<> | 154:37f96f9d4de2 | 111 | |
<> | 154:37f96f9d4de2 | 112 | /*! |
<> | 154:37f96f9d4de2 | 113 | * @brief Master run transfer state machine to perform a byte of transfer. |
<> | 154:37f96f9d4de2 | 114 | * |
<> | 154:37f96f9d4de2 | 115 | * @param base I2C peripheral base address. |
<> | 154:37f96f9d4de2 | 116 | * @param handle pointer to i2c_master_handle_t structure which stores the transfer state |
<> | 154:37f96f9d4de2 | 117 | * @param isDone input param to get whether the thing is done, true is done |
<> | 154:37f96f9d4de2 | 118 | * @retval kStatus_Success No error found. |
<> | 154:37f96f9d4de2 | 119 | * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. |
<> | 154:37f96f9d4de2 | 120 | * @retval kStatus_I2C_Nak Received Nak error. |
<> | 154:37f96f9d4de2 | 121 | * @retval kStatus_I2C_Timeout Transfer error, wait signal timeout. |
<> | 154:37f96f9d4de2 | 122 | */ |
<> | 154:37f96f9d4de2 | 123 | static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_handle_t *handle, bool *isDone); |
<> | 154:37f96f9d4de2 | 124 | |
<> | 154:37f96f9d4de2 | 125 | /*! |
<> | 154:37f96f9d4de2 | 126 | * @brief I2C common interrupt handler. |
<> | 154:37f96f9d4de2 | 127 | * |
<> | 154:37f96f9d4de2 | 128 | * @param base I2C peripheral base address. |
<> | 154:37f96f9d4de2 | 129 | * @param handle pointer to i2c_master_handle_t structure which stores the transfer state |
<> | 154:37f96f9d4de2 | 130 | */ |
<> | 154:37f96f9d4de2 | 131 | static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle); |
<> | 154:37f96f9d4de2 | 132 | |
<> | 154:37f96f9d4de2 | 133 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 134 | * Variables |
<> | 154:37f96f9d4de2 | 135 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 136 | |
<> | 154:37f96f9d4de2 | 137 | /*! @brief Pointers to i2c handles for each instance. */ |
<> | 154:37f96f9d4de2 | 138 | static void *s_i2cHandle[FSL_FEATURE_SOC_I2C_COUNT] = {NULL}; |
<> | 154:37f96f9d4de2 | 139 | |
<> | 154:37f96f9d4de2 | 140 | /*! @brief SCL clock divider used to calculate baudrate. */ |
<> | 154:37f96f9d4de2 | 141 | static const uint16_t s_i2cDividerTable[] = { |
<> | 154:37f96f9d4de2 | 142 | 20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, 48, 56, 68, |
<> | 154:37f96f9d4de2 | 143 | 48, 56, 64, 72, 80, 88, 104, 128, 80, 96, 112, 128, 144, 160, 192, 240, |
<> | 154:37f96f9d4de2 | 144 | 160, 192, 224, 256, 288, 320, 384, 480, 320, 384, 448, 512, 576, 640, 768, 960, |
<> | 154:37f96f9d4de2 | 145 | 640, 768, 896, 1024, 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840}; |
<> | 154:37f96f9d4de2 | 146 | |
<> | 154:37f96f9d4de2 | 147 | /*! @brief Pointers to i2c bases for each instance. */ |
<> | 154:37f96f9d4de2 | 148 | static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS; |
<> | 154:37f96f9d4de2 | 149 | |
<> | 154:37f96f9d4de2 | 150 | /*! @brief Pointers to i2c IRQ number for each instance. */ |
<> | 154:37f96f9d4de2 | 151 | static const IRQn_Type s_i2cIrqs[] = I2C_IRQS; |
<> | 154:37f96f9d4de2 | 152 | |
<> | 154:37f96f9d4de2 | 153 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 154 | /*! @brief Pointers to i2c clocks for each instance. */ |
<> | 154:37f96f9d4de2 | 155 | static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS; |
<> | 154:37f96f9d4de2 | 156 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 157 | |
<> | 154:37f96f9d4de2 | 158 | /*! @brief Pointer to master IRQ handler for each instance. */ |
<> | 154:37f96f9d4de2 | 159 | static i2c_isr_t s_i2cMasterIsr; |
<> | 154:37f96f9d4de2 | 160 | |
<> | 154:37f96f9d4de2 | 161 | /*! @brief Pointer to slave IRQ handler for each instance. */ |
<> | 154:37f96f9d4de2 | 162 | static i2c_isr_t s_i2cSlaveIsr; |
<> | 154:37f96f9d4de2 | 163 | |
<> | 154:37f96f9d4de2 | 164 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 165 | * Codes |
<> | 154:37f96f9d4de2 | 166 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 167 | |
<> | 154:37f96f9d4de2 | 168 | uint32_t I2C_GetInstance(I2C_Type *base) |
<> | 154:37f96f9d4de2 | 169 | { |
<> | 154:37f96f9d4de2 | 170 | uint32_t instance; |
<> | 154:37f96f9d4de2 | 171 | |
<> | 154:37f96f9d4de2 | 172 | /* Find the instance index from base address mappings. */ |
<> | 154:37f96f9d4de2 | 173 | for (instance = 0; instance < FSL_FEATURE_SOC_I2C_COUNT; instance++) |
<> | 154:37f96f9d4de2 | 174 | { |
<> | 154:37f96f9d4de2 | 175 | if (s_i2cBases[instance] == base) |
<> | 154:37f96f9d4de2 | 176 | { |
<> | 154:37f96f9d4de2 | 177 | break; |
<> | 154:37f96f9d4de2 | 178 | } |
<> | 154:37f96f9d4de2 | 179 | } |
<> | 154:37f96f9d4de2 | 180 | |
<> | 154:37f96f9d4de2 | 181 | assert(instance < FSL_FEATURE_SOC_I2C_COUNT); |
<> | 154:37f96f9d4de2 | 182 | |
<> | 154:37f96f9d4de2 | 183 | return instance; |
<> | 154:37f96f9d4de2 | 184 | } |
<> | 154:37f96f9d4de2 | 185 | |
<> | 154:37f96f9d4de2 | 186 | static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz) |
<> | 154:37f96f9d4de2 | 187 | { |
<> | 154:37f96f9d4de2 | 188 | uint32_t multiplier; |
<> | 154:37f96f9d4de2 | 189 | uint32_t computedSclHoldTime; |
<> | 154:37f96f9d4de2 | 190 | uint32_t absError; |
<> | 154:37f96f9d4de2 | 191 | uint32_t bestError = UINT32_MAX; |
<> | 154:37f96f9d4de2 | 192 | uint32_t bestMult = 0u; |
<> | 154:37f96f9d4de2 | 193 | uint32_t bestIcr = 0u; |
<> | 154:37f96f9d4de2 | 194 | uint8_t mult; |
<> | 154:37f96f9d4de2 | 195 | uint8_t i; |
<> | 154:37f96f9d4de2 | 196 | |
<> | 154:37f96f9d4de2 | 197 | /* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register, |
<> | 154:37f96f9d4de2 | 198 | * and ranges from 0-2. It selects the multiplier factor for the divider. */ |
<> | 154:37f96f9d4de2 | 199 | /* SDA hold time = bus period (s) * mul * SDA hold value. */ |
<> | 154:37f96f9d4de2 | 200 | /* SCL start hold time = bus period (s) * mul * SCL start hold value. */ |
<> | 154:37f96f9d4de2 | 201 | /* SCL stop hold time = bus period (s) * mul * SCL stop hold value. */ |
<> | 154:37f96f9d4de2 | 202 | |
<> | 154:37f96f9d4de2 | 203 | for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult) |
<> | 154:37f96f9d4de2 | 204 | { |
<> | 154:37f96f9d4de2 | 205 | multiplier = 1u << mult; |
<> | 154:37f96f9d4de2 | 206 | |
<> | 154:37f96f9d4de2 | 207 | /* Scan table to find best match. */ |
<> | 154:37f96f9d4de2 | 208 | for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(s_i2cDividerTable[0]); ++i) |
<> | 154:37f96f9d4de2 | 209 | { |
<> | 154:37f96f9d4de2 | 210 | /* Assume SCL hold(stop) value = s_i2cDividerTable[i]/2. */ |
<> | 154:37f96f9d4de2 | 211 | computedSclHoldTime = ((multiplier * s_i2cDividerTable[i]) * 500000000U) / sourceClock_Hz; |
<> | 154:37f96f9d4de2 | 212 | absError = sclStopHoldTime_ns > computedSclHoldTime ? (sclStopHoldTime_ns - computedSclHoldTime) : |
<> | 154:37f96f9d4de2 | 213 | (computedSclHoldTime - sclStopHoldTime_ns); |
<> | 154:37f96f9d4de2 | 214 | |
<> | 154:37f96f9d4de2 | 215 | if (absError < bestError) |
<> | 154:37f96f9d4de2 | 216 | { |
<> | 154:37f96f9d4de2 | 217 | bestMult = mult; |
<> | 154:37f96f9d4de2 | 218 | bestIcr = i; |
<> | 154:37f96f9d4de2 | 219 | bestError = absError; |
<> | 154:37f96f9d4de2 | 220 | |
<> | 154:37f96f9d4de2 | 221 | /* If the error is 0, then we can stop searching because we won't find a better match. */ |
<> | 154:37f96f9d4de2 | 222 | if (absError == 0) |
<> | 154:37f96f9d4de2 | 223 | { |
<> | 154:37f96f9d4de2 | 224 | break; |
<> | 154:37f96f9d4de2 | 225 | } |
<> | 154:37f96f9d4de2 | 226 | } |
<> | 154:37f96f9d4de2 | 227 | } |
<> | 154:37f96f9d4de2 | 228 | } |
<> | 154:37f96f9d4de2 | 229 | |
<> | 154:37f96f9d4de2 | 230 | /* Set frequency register based on best settings. */ |
<> | 154:37f96f9d4de2 | 231 | base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr); |
<> | 154:37f96f9d4de2 | 232 | } |
<> | 154:37f96f9d4de2 | 233 | |
<> | 154:37f96f9d4de2 | 234 | static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer) |
<> | 154:37f96f9d4de2 | 235 | { |
<> | 154:37f96f9d4de2 | 236 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 237 | i2c_direction_t direction = xfer->direction; |
<> | 154:37f96f9d4de2 | 238 | |
<> | 154:37f96f9d4de2 | 239 | /* Initialize the handle transfer information. */ |
<> | 154:37f96f9d4de2 | 240 | handle->transfer = *xfer; |
<> | 154:37f96f9d4de2 | 241 | |
<> | 154:37f96f9d4de2 | 242 | /* Save total transfer size. */ |
<> | 154:37f96f9d4de2 | 243 | handle->transferSize = xfer->dataSize; |
<> | 154:37f96f9d4de2 | 244 | |
<> | 154:37f96f9d4de2 | 245 | /* Initial transfer state. */ |
<> | 154:37f96f9d4de2 | 246 | if (handle->transfer.subaddressSize > 0) |
<> | 154:37f96f9d4de2 | 247 | { |
<> | 154:37f96f9d4de2 | 248 | if (xfer->direction == kI2C_Read) |
<> | 154:37f96f9d4de2 | 249 | { |
<> | 154:37f96f9d4de2 | 250 | direction = kI2C_Write; |
<> | 154:37f96f9d4de2 | 251 | } |
<> | 154:37f96f9d4de2 | 252 | } |
<> | 154:37f96f9d4de2 | 253 | |
<> | 154:37f96f9d4de2 | 254 | handle->state = kCheckAddressState; |
<> | 154:37f96f9d4de2 | 255 | |
<> | 154:37f96f9d4de2 | 256 | /* Clear all status before transfer. */ |
<> | 154:37f96f9d4de2 | 257 | I2C_MasterClearStatusFlags(base, kClearFlags); |
<> | 154:37f96f9d4de2 | 258 | |
<> | 154:37f96f9d4de2 | 259 | /* If repeated start is requested, send repeated start. */ |
<> | 154:37f96f9d4de2 | 260 | if (handle->transfer.flags & kI2C_TransferRepeatedStartFlag) |
<> | 154:37f96f9d4de2 | 261 | { |
<> | 154:37f96f9d4de2 | 262 | result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, direction); |
<> | 154:37f96f9d4de2 | 263 | } |
<> | 154:37f96f9d4de2 | 264 | else /* For normal transfer, send start. */ |
<> | 154:37f96f9d4de2 | 265 | { |
<> | 154:37f96f9d4de2 | 266 | result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction); |
<> | 154:37f96f9d4de2 | 267 | } |
<> | 154:37f96f9d4de2 | 268 | |
<> | 154:37f96f9d4de2 | 269 | return result; |
<> | 154:37f96f9d4de2 | 270 | } |
<> | 154:37f96f9d4de2 | 271 | |
<> | 154:37f96f9d4de2 | 272 | static status_t I2C_CheckAndClearError(I2C_Type *base, uint32_t status) |
<> | 154:37f96f9d4de2 | 273 | { |
<> | 154:37f96f9d4de2 | 274 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 275 | |
<> | 154:37f96f9d4de2 | 276 | /* Check arbitration lost. */ |
<> | 154:37f96f9d4de2 | 277 | if (status & kI2C_ArbitrationLostFlag) |
<> | 154:37f96f9d4de2 | 278 | { |
<> | 154:37f96f9d4de2 | 279 | /* Clear arbitration lost flag. */ |
<> | 154:37f96f9d4de2 | 280 | base->S = kI2C_ArbitrationLostFlag; |
<> | 154:37f96f9d4de2 | 281 | result = kStatus_I2C_ArbitrationLost; |
<> | 154:37f96f9d4de2 | 282 | } |
<> | 154:37f96f9d4de2 | 283 | /* Check NAK */ |
<> | 154:37f96f9d4de2 | 284 | else if (status & kI2C_ReceiveNakFlag) |
<> | 154:37f96f9d4de2 | 285 | { |
<> | 154:37f96f9d4de2 | 286 | result = kStatus_I2C_Nak; |
<> | 154:37f96f9d4de2 | 287 | } |
<> | 154:37f96f9d4de2 | 288 | else |
<> | 154:37f96f9d4de2 | 289 | { |
<> | 154:37f96f9d4de2 | 290 | } |
<> | 154:37f96f9d4de2 | 291 | |
<> | 154:37f96f9d4de2 | 292 | return result; |
<> | 154:37f96f9d4de2 | 293 | } |
<> | 154:37f96f9d4de2 | 294 | |
<> | 154:37f96f9d4de2 | 295 | static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_handle_t *handle, bool *isDone) |
<> | 154:37f96f9d4de2 | 296 | { |
<> | 154:37f96f9d4de2 | 297 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 298 | uint32_t statusFlags = base->S; |
<> | 154:37f96f9d4de2 | 299 | *isDone = false; |
<> | 154:37f96f9d4de2 | 300 | volatile uint8_t dummy = 0; |
<> | 154:37f96f9d4de2 | 301 | bool ignoreNak = ((handle->state == kSendDataState) && (handle->transfer.dataSize == 0U)) || |
<> | 154:37f96f9d4de2 | 302 | ((handle->state == kReceiveDataState) && (handle->transfer.dataSize == 1U)); |
<> | 154:37f96f9d4de2 | 303 | |
<> | 154:37f96f9d4de2 | 304 | /* Add this to avoid build warning. */ |
<> | 154:37f96f9d4de2 | 305 | dummy++; |
<> | 154:37f96f9d4de2 | 306 | |
<> | 154:37f96f9d4de2 | 307 | /* Check & clear error flags. */ |
<> | 154:37f96f9d4de2 | 308 | result = I2C_CheckAndClearError(base, statusFlags); |
<> | 154:37f96f9d4de2 | 309 | |
<> | 154:37f96f9d4de2 | 310 | /* Ignore Nak when it's appeared for last byte. */ |
<> | 154:37f96f9d4de2 | 311 | if ((result == kStatus_I2C_Nak) && ignoreNak) |
<> | 154:37f96f9d4de2 | 312 | { |
<> | 154:37f96f9d4de2 | 313 | result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 314 | } |
<> | 154:37f96f9d4de2 | 315 | |
<> | 154:37f96f9d4de2 | 316 | /* Handle Check address state to check the slave address is Acked in slave |
<> | 154:37f96f9d4de2 | 317 | probe application. */ |
<> | 154:37f96f9d4de2 | 318 | if (handle->state == kCheckAddressState) |
<> | 154:37f96f9d4de2 | 319 | { |
<> | 154:37f96f9d4de2 | 320 | if (statusFlags & kI2C_ReceiveNakFlag) |
<> | 154:37f96f9d4de2 | 321 | { |
<> | 154:37f96f9d4de2 | 322 | result = kStatus_I2C_Addr_Nak; |
<> | 154:37f96f9d4de2 | 323 | } |
<> | 154:37f96f9d4de2 | 324 | else |
<> | 154:37f96f9d4de2 | 325 | { |
<> | 154:37f96f9d4de2 | 326 | if (handle->transfer.subaddressSize > 0) |
<> | 154:37f96f9d4de2 | 327 | { |
<> | 154:37f96f9d4de2 | 328 | handle->state = kSendCommandState; |
<> | 154:37f96f9d4de2 | 329 | } |
<> | 154:37f96f9d4de2 | 330 | else |
<> | 154:37f96f9d4de2 | 331 | { |
<> | 154:37f96f9d4de2 | 332 | if (handle->transfer.direction == kI2C_Write) |
<> | 154:37f96f9d4de2 | 333 | { |
<> | 154:37f96f9d4de2 | 334 | /* Next state, send data. */ |
<> | 154:37f96f9d4de2 | 335 | handle->state = kSendDataState; |
<> | 154:37f96f9d4de2 | 336 | } |
<> | 154:37f96f9d4de2 | 337 | else |
<> | 154:37f96f9d4de2 | 338 | { |
<> | 154:37f96f9d4de2 | 339 | /* Next state, receive data begin. */ |
<> | 154:37f96f9d4de2 | 340 | handle->state = kReceiveDataBeginState; |
<> | 154:37f96f9d4de2 | 341 | } |
<> | 154:37f96f9d4de2 | 342 | } |
<> | 154:37f96f9d4de2 | 343 | } |
<> | 154:37f96f9d4de2 | 344 | } |
<> | 154:37f96f9d4de2 | 345 | |
<> | 154:37f96f9d4de2 | 346 | if (result) |
<> | 154:37f96f9d4de2 | 347 | { |
<> | 154:37f96f9d4de2 | 348 | return result; |
<> | 154:37f96f9d4de2 | 349 | } |
<> | 154:37f96f9d4de2 | 350 | |
<> | 154:37f96f9d4de2 | 351 | /* Run state machine. */ |
<> | 154:37f96f9d4de2 | 352 | switch (handle->state) |
<> | 154:37f96f9d4de2 | 353 | { |
<> | 154:37f96f9d4de2 | 354 | /* Send I2C command. */ |
<> | 154:37f96f9d4de2 | 355 | case kSendCommandState: |
<> | 154:37f96f9d4de2 | 356 | if (handle->transfer.subaddressSize) |
<> | 154:37f96f9d4de2 | 357 | { |
<> | 154:37f96f9d4de2 | 358 | handle->transfer.subaddressSize--; |
<> | 154:37f96f9d4de2 | 359 | base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize)); |
<> | 154:37f96f9d4de2 | 360 | } |
<> | 154:37f96f9d4de2 | 361 | else |
<> | 154:37f96f9d4de2 | 362 | { |
<> | 154:37f96f9d4de2 | 363 | if (handle->transfer.direction == kI2C_Write) |
<> | 154:37f96f9d4de2 | 364 | { |
<> | 154:37f96f9d4de2 | 365 | /* Next state, send data. */ |
<> | 154:37f96f9d4de2 | 366 | handle->state = kSendDataState; |
<> | 154:37f96f9d4de2 | 367 | |
<> | 154:37f96f9d4de2 | 368 | /* Send first byte of data. */ |
<> | 154:37f96f9d4de2 | 369 | if (handle->transfer.dataSize > 0) |
<> | 154:37f96f9d4de2 | 370 | { |
<> | 154:37f96f9d4de2 | 371 | base->D = *handle->transfer.data; |
<> | 154:37f96f9d4de2 | 372 | handle->transfer.data++; |
<> | 154:37f96f9d4de2 | 373 | handle->transfer.dataSize--; |
<> | 154:37f96f9d4de2 | 374 | } |
<> | 154:37f96f9d4de2 | 375 | } |
<> | 154:37f96f9d4de2 | 376 | else |
<> | 154:37f96f9d4de2 | 377 | { |
<> | 154:37f96f9d4de2 | 378 | /* Send repeated start and slave address. */ |
<> | 154:37f96f9d4de2 | 379 | result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read); |
<> | 154:37f96f9d4de2 | 380 | |
<> | 154:37f96f9d4de2 | 381 | /* Next state, receive data begin. */ |
<> | 154:37f96f9d4de2 | 382 | handle->state = kReceiveDataBeginState; |
<> | 154:37f96f9d4de2 | 383 | } |
<> | 154:37f96f9d4de2 | 384 | } |
<> | 154:37f96f9d4de2 | 385 | break; |
<> | 154:37f96f9d4de2 | 386 | |
<> | 154:37f96f9d4de2 | 387 | /* Send I2C data. */ |
<> | 154:37f96f9d4de2 | 388 | case kSendDataState: |
<> | 154:37f96f9d4de2 | 389 | /* Send one byte of data. */ |
<> | 154:37f96f9d4de2 | 390 | if (handle->transfer.dataSize > 0) |
<> | 154:37f96f9d4de2 | 391 | { |
<> | 154:37f96f9d4de2 | 392 | base->D = *handle->transfer.data; |
<> | 154:37f96f9d4de2 | 393 | handle->transfer.data++; |
<> | 154:37f96f9d4de2 | 394 | handle->transfer.dataSize--; |
<> | 154:37f96f9d4de2 | 395 | } |
<> | 154:37f96f9d4de2 | 396 | else |
<> | 154:37f96f9d4de2 | 397 | { |
<> | 154:37f96f9d4de2 | 398 | *isDone = true; |
<> | 154:37f96f9d4de2 | 399 | } |
<> | 154:37f96f9d4de2 | 400 | break; |
<> | 154:37f96f9d4de2 | 401 | |
<> | 154:37f96f9d4de2 | 402 | /* Start I2C data receive. */ |
<> | 154:37f96f9d4de2 | 403 | case kReceiveDataBeginState: |
<> | 154:37f96f9d4de2 | 404 | base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 405 | |
<> | 154:37f96f9d4de2 | 406 | /* Send nak at the last receive byte. */ |
<> | 154:37f96f9d4de2 | 407 | if (handle->transfer.dataSize == 1) |
<> | 154:37f96f9d4de2 | 408 | { |
<> | 154:37f96f9d4de2 | 409 | base->C1 |= I2C_C1_TXAK_MASK; |
<> | 154:37f96f9d4de2 | 410 | } |
<> | 154:37f96f9d4de2 | 411 | |
<> | 154:37f96f9d4de2 | 412 | /* Read dummy to release the bus. */ |
<> | 154:37f96f9d4de2 | 413 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 414 | |
<> | 154:37f96f9d4de2 | 415 | /* Next state, receive data. */ |
<> | 154:37f96f9d4de2 | 416 | handle->state = kReceiveDataState; |
<> | 154:37f96f9d4de2 | 417 | break; |
<> | 154:37f96f9d4de2 | 418 | |
<> | 154:37f96f9d4de2 | 419 | /* Receive I2C data. */ |
<> | 154:37f96f9d4de2 | 420 | case kReceiveDataState: |
<> | 154:37f96f9d4de2 | 421 | /* Receive one byte of data. */ |
<> | 154:37f96f9d4de2 | 422 | if (handle->transfer.dataSize--) |
<> | 154:37f96f9d4de2 | 423 | { |
<> | 154:37f96f9d4de2 | 424 | if (handle->transfer.dataSize == 0) |
<> | 154:37f96f9d4de2 | 425 | { |
<> | 154:37f96f9d4de2 | 426 | *isDone = true; |
<> | 154:37f96f9d4de2 | 427 | |
<> | 154:37f96f9d4de2 | 428 | /* Send stop if kI2C_TransferNoStop is not asserted. */ |
<> | 154:37f96f9d4de2 | 429 | if (!(handle->transfer.flags & kI2C_TransferNoStopFlag)) |
<> | 154:37f96f9d4de2 | 430 | { |
<> | 154:37f96f9d4de2 | 431 | result = I2C_MasterStop(base); |
<> | 154:37f96f9d4de2 | 432 | } |
<> | 154:37f96f9d4de2 | 433 | else |
<> | 154:37f96f9d4de2 | 434 | { |
<> | 154:37f96f9d4de2 | 435 | base->C1 |= I2C_C1_TX_MASK; |
<> | 154:37f96f9d4de2 | 436 | } |
<> | 154:37f96f9d4de2 | 437 | } |
<> | 154:37f96f9d4de2 | 438 | |
<> | 154:37f96f9d4de2 | 439 | /* Send NAK at the last receive byte. */ |
<> | 154:37f96f9d4de2 | 440 | if (handle->transfer.dataSize == 1) |
<> | 154:37f96f9d4de2 | 441 | { |
<> | 154:37f96f9d4de2 | 442 | base->C1 |= I2C_C1_TXAK_MASK; |
<> | 154:37f96f9d4de2 | 443 | } |
<> | 154:37f96f9d4de2 | 444 | |
<> | 154:37f96f9d4de2 | 445 | /* Read the data byte into the transfer buffer. */ |
<> | 154:37f96f9d4de2 | 446 | *handle->transfer.data = base->D; |
<> | 154:37f96f9d4de2 | 447 | handle->transfer.data++; |
<> | 154:37f96f9d4de2 | 448 | } |
<> | 154:37f96f9d4de2 | 449 | break; |
<> | 154:37f96f9d4de2 | 450 | |
<> | 154:37f96f9d4de2 | 451 | default: |
<> | 154:37f96f9d4de2 | 452 | break; |
<> | 154:37f96f9d4de2 | 453 | } |
<> | 154:37f96f9d4de2 | 454 | |
<> | 154:37f96f9d4de2 | 455 | return result; |
<> | 154:37f96f9d4de2 | 456 | } |
<> | 154:37f96f9d4de2 | 457 | |
<> | 154:37f96f9d4de2 | 458 | static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle) |
<> | 154:37f96f9d4de2 | 459 | { |
<> | 154:37f96f9d4de2 | 460 | /* Check if master interrupt. */ |
<> | 154:37f96f9d4de2 | 461 | if ((base->S & kI2C_ArbitrationLostFlag) || (base->C1 & I2C_C1_MST_MASK)) |
<> | 154:37f96f9d4de2 | 462 | { |
<> | 154:37f96f9d4de2 | 463 | s_i2cMasterIsr(base, handle); |
<> | 154:37f96f9d4de2 | 464 | } |
<> | 154:37f96f9d4de2 | 465 | else |
<> | 154:37f96f9d4de2 | 466 | { |
<> | 154:37f96f9d4de2 | 467 | s_i2cSlaveIsr(base, handle); |
<> | 154:37f96f9d4de2 | 468 | } |
<> | 154:37f96f9d4de2 | 469 | __DSB(); |
<> | 154:37f96f9d4de2 | 470 | } |
<> | 154:37f96f9d4de2 | 471 | |
<> | 154:37f96f9d4de2 | 472 | void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz) |
<> | 154:37f96f9d4de2 | 473 | { |
<> | 154:37f96f9d4de2 | 474 | assert(masterConfig && srcClock_Hz); |
<> | 154:37f96f9d4de2 | 475 | |
<> | 154:37f96f9d4de2 | 476 | /* Temporary register for filter read. */ |
<> | 154:37f96f9d4de2 | 477 | uint8_t fltReg; |
<> | 154:37f96f9d4de2 | 478 | #if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION |
<> | 154:37f96f9d4de2 | 479 | uint8_t c2Reg; |
<> | 154:37f96f9d4de2 | 480 | #endif |
<> | 154:37f96f9d4de2 | 481 | #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE |
<> | 154:37f96f9d4de2 | 482 | uint8_t s2Reg; |
<> | 154:37f96f9d4de2 | 483 | #endif |
<> | 154:37f96f9d4de2 | 484 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 485 | /* Enable I2C clock. */ |
<> | 154:37f96f9d4de2 | 486 | CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 487 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 488 | |
<> | 154:37f96f9d4de2 | 489 | /* Disable I2C prior to configuring it. */ |
<> | 154:37f96f9d4de2 | 490 | base->C1 &= ~(I2C_C1_IICEN_MASK); |
<> | 154:37f96f9d4de2 | 491 | |
<> | 154:37f96f9d4de2 | 492 | /* Clear all flags. */ |
<> | 154:37f96f9d4de2 | 493 | I2C_MasterClearStatusFlags(base, kClearFlags); |
<> | 154:37f96f9d4de2 | 494 | |
<> | 154:37f96f9d4de2 | 495 | /* Configure baud rate. */ |
<> | 154:37f96f9d4de2 | 496 | I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz); |
<> | 154:37f96f9d4de2 | 497 | |
<> | 154:37f96f9d4de2 | 498 | #if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION |
<> | 154:37f96f9d4de2 | 499 | /* Configure high drive feature. */ |
<> | 154:37f96f9d4de2 | 500 | c2Reg = base->C2; |
<> | 154:37f96f9d4de2 | 501 | c2Reg &= ~(I2C_C2_HDRS_MASK); |
<> | 154:37f96f9d4de2 | 502 | c2Reg |= I2C_C2_HDRS(masterConfig->enableHighDrive); |
<> | 154:37f96f9d4de2 | 503 | base->C2 = c2Reg; |
<> | 154:37f96f9d4de2 | 504 | #endif |
<> | 154:37f96f9d4de2 | 505 | |
<> | 154:37f96f9d4de2 | 506 | /* Read out the FLT register. */ |
<> | 154:37f96f9d4de2 | 507 | fltReg = base->FLT; |
<> | 154:37f96f9d4de2 | 508 | |
<> | 154:37f96f9d4de2 | 509 | #if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF |
<> | 154:37f96f9d4de2 | 510 | /* Configure the stop / hold enable. */ |
<> | 154:37f96f9d4de2 | 511 | fltReg &= ~(I2C_FLT_SHEN_MASK); |
<> | 154:37f96f9d4de2 | 512 | fltReg |= I2C_FLT_SHEN(masterConfig->enableStopHold); |
<> | 154:37f96f9d4de2 | 513 | #endif |
<> | 154:37f96f9d4de2 | 514 | |
<> | 154:37f96f9d4de2 | 515 | /* Configure the glitch filter value. */ |
<> | 154:37f96f9d4de2 | 516 | fltReg &= ~(I2C_FLT_FLT_MASK); |
<> | 154:37f96f9d4de2 | 517 | fltReg |= I2C_FLT_FLT(masterConfig->glitchFilterWidth); |
<> | 154:37f96f9d4de2 | 518 | |
<> | 154:37f96f9d4de2 | 519 | /* Write the register value back to the filter register. */ |
<> | 154:37f96f9d4de2 | 520 | base->FLT = fltReg; |
<> | 154:37f96f9d4de2 | 521 | |
<> | 154:37f96f9d4de2 | 522 | /* Enable/Disable double buffering. */ |
<> | 154:37f96f9d4de2 | 523 | #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE |
<> | 154:37f96f9d4de2 | 524 | s2Reg = base->S2 & (~I2C_S2_DFEN_MASK); |
<> | 154:37f96f9d4de2 | 525 | base->S2 = s2Reg | I2C_S2_DFEN(masterConfig->enableDoubleBuffering); |
<> | 154:37f96f9d4de2 | 526 | #endif |
<> | 154:37f96f9d4de2 | 527 | |
<> | 154:37f96f9d4de2 | 528 | /* Enable the I2C peripheral based on the configuration. */ |
<> | 154:37f96f9d4de2 | 529 | base->C1 = I2C_C1_IICEN(masterConfig->enableMaster); |
<> | 154:37f96f9d4de2 | 530 | } |
<> | 154:37f96f9d4de2 | 531 | |
<> | 154:37f96f9d4de2 | 532 | void I2C_MasterDeinit(I2C_Type *base) |
<> | 154:37f96f9d4de2 | 533 | { |
<> | 154:37f96f9d4de2 | 534 | /* Disable I2C module. */ |
<> | 154:37f96f9d4de2 | 535 | I2C_Enable(base, false); |
<> | 154:37f96f9d4de2 | 536 | |
<> | 154:37f96f9d4de2 | 537 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 538 | /* Disable I2C clock. */ |
<> | 154:37f96f9d4de2 | 539 | CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 540 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 541 | } |
<> | 154:37f96f9d4de2 | 542 | |
<> | 154:37f96f9d4de2 | 543 | void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) |
<> | 154:37f96f9d4de2 | 544 | { |
<> | 154:37f96f9d4de2 | 545 | assert(masterConfig); |
<> | 154:37f96f9d4de2 | 546 | |
<> | 154:37f96f9d4de2 | 547 | /* Default baud rate at 100kbps. */ |
<> | 154:37f96f9d4de2 | 548 | masterConfig->baudRate_Bps = 100000U; |
<> | 154:37f96f9d4de2 | 549 | |
<> | 154:37f96f9d4de2 | 550 | /* Default pin high drive is disabled. */ |
<> | 154:37f96f9d4de2 | 551 | #if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION |
<> | 154:37f96f9d4de2 | 552 | masterConfig->enableHighDrive = false; |
<> | 154:37f96f9d4de2 | 553 | #endif |
<> | 154:37f96f9d4de2 | 554 | |
<> | 154:37f96f9d4de2 | 555 | /* Default stop hold enable is disabled. */ |
<> | 154:37f96f9d4de2 | 556 | #if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF |
<> | 154:37f96f9d4de2 | 557 | masterConfig->enableStopHold = false; |
<> | 154:37f96f9d4de2 | 558 | #endif |
<> | 154:37f96f9d4de2 | 559 | |
<> | 154:37f96f9d4de2 | 560 | /* Default glitch filter value is no filter. */ |
<> | 154:37f96f9d4de2 | 561 | masterConfig->glitchFilterWidth = 0U; |
<> | 154:37f96f9d4de2 | 562 | |
<> | 154:37f96f9d4de2 | 563 | /* Default enable double buffering. */ |
<> | 154:37f96f9d4de2 | 564 | #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE |
<> | 154:37f96f9d4de2 | 565 | masterConfig->enableDoubleBuffering = true; |
<> | 154:37f96f9d4de2 | 566 | #endif |
<> | 154:37f96f9d4de2 | 567 | |
<> | 154:37f96f9d4de2 | 568 | /* Enable the I2C peripheral. */ |
<> | 154:37f96f9d4de2 | 569 | masterConfig->enableMaster = true; |
<> | 154:37f96f9d4de2 | 570 | } |
<> | 154:37f96f9d4de2 | 571 | |
<> | 154:37f96f9d4de2 | 572 | void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask) |
<> | 154:37f96f9d4de2 | 573 | { |
<> | 154:37f96f9d4de2 | 574 | #ifdef I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 575 | uint8_t fltReg; |
<> | 154:37f96f9d4de2 | 576 | #endif |
<> | 154:37f96f9d4de2 | 577 | |
<> | 154:37f96f9d4de2 | 578 | if (mask & kI2C_GlobalInterruptEnable) |
<> | 154:37f96f9d4de2 | 579 | { |
<> | 154:37f96f9d4de2 | 580 | base->C1 |= I2C_C1_IICIE_MASK; |
<> | 154:37f96f9d4de2 | 581 | } |
<> | 154:37f96f9d4de2 | 582 | |
<> | 154:37f96f9d4de2 | 583 | #if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 584 | if (mask & kI2C_StopDetectInterruptEnable) |
<> | 154:37f96f9d4de2 | 585 | { |
<> | 154:37f96f9d4de2 | 586 | fltReg = base->FLT; |
<> | 154:37f96f9d4de2 | 587 | |
<> | 154:37f96f9d4de2 | 588 | /* Keep STOPF flag. */ |
<> | 154:37f96f9d4de2 | 589 | fltReg &= ~I2C_FLT_STOPF_MASK; |
<> | 154:37f96f9d4de2 | 590 | |
<> | 154:37f96f9d4de2 | 591 | /* Stop detect enable. */ |
<> | 154:37f96f9d4de2 | 592 | fltReg |= I2C_FLT_STOPIE_MASK; |
<> | 154:37f96f9d4de2 | 593 | base->FLT = fltReg; |
<> | 154:37f96f9d4de2 | 594 | } |
<> | 154:37f96f9d4de2 | 595 | #endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 596 | |
<> | 154:37f96f9d4de2 | 597 | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT |
<> | 154:37f96f9d4de2 | 598 | if (mask & kI2C_StartStopDetectInterruptEnable) |
<> | 154:37f96f9d4de2 | 599 | { |
<> | 154:37f96f9d4de2 | 600 | fltReg = base->FLT; |
<> | 154:37f96f9d4de2 | 601 | |
<> | 154:37f96f9d4de2 | 602 | /* Keep STARTF and STOPF flags. */ |
<> | 154:37f96f9d4de2 | 603 | fltReg &= ~(I2C_FLT_STOPF_MASK | I2C_FLT_STARTF_MASK); |
<> | 154:37f96f9d4de2 | 604 | |
<> | 154:37f96f9d4de2 | 605 | /* Start and stop detect enable. */ |
<> | 154:37f96f9d4de2 | 606 | fltReg |= I2C_FLT_SSIE_MASK; |
<> | 154:37f96f9d4de2 | 607 | base->FLT = fltReg; |
<> | 154:37f96f9d4de2 | 608 | } |
<> | 154:37f96f9d4de2 | 609 | #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 610 | } |
<> | 154:37f96f9d4de2 | 611 | |
<> | 154:37f96f9d4de2 | 612 | void I2C_DisableInterrupts(I2C_Type *base, uint32_t mask) |
<> | 154:37f96f9d4de2 | 613 | { |
<> | 154:37f96f9d4de2 | 614 | if (mask & kI2C_GlobalInterruptEnable) |
<> | 154:37f96f9d4de2 | 615 | { |
<> | 154:37f96f9d4de2 | 616 | base->C1 &= ~I2C_C1_IICIE_MASK; |
<> | 154:37f96f9d4de2 | 617 | } |
<> | 154:37f96f9d4de2 | 618 | |
<> | 154:37f96f9d4de2 | 619 | #if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 620 | if (mask & kI2C_StopDetectInterruptEnable) |
<> | 154:37f96f9d4de2 | 621 | { |
<> | 154:37f96f9d4de2 | 622 | base->FLT &= ~(I2C_FLT_STOPIE_MASK | I2C_FLT_STOPF_MASK); |
<> | 154:37f96f9d4de2 | 623 | } |
<> | 154:37f96f9d4de2 | 624 | #endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 625 | |
<> | 154:37f96f9d4de2 | 626 | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT |
<> | 154:37f96f9d4de2 | 627 | if (mask & kI2C_StartStopDetectInterruptEnable) |
<> | 154:37f96f9d4de2 | 628 | { |
<> | 154:37f96f9d4de2 | 629 | base->FLT &= ~(I2C_FLT_SSIE_MASK | I2C_FLT_STOPF_MASK | I2C_FLT_STARTF_MASK); |
<> | 154:37f96f9d4de2 | 630 | } |
<> | 154:37f96f9d4de2 | 631 | #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 632 | } |
<> | 154:37f96f9d4de2 | 633 | |
<> | 154:37f96f9d4de2 | 634 | void I2C_MasterSetBaudRate(I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz) |
<> | 154:37f96f9d4de2 | 635 | { |
<> | 154:37f96f9d4de2 | 636 | uint32_t multiplier; |
<> | 154:37f96f9d4de2 | 637 | uint32_t computedRate; |
<> | 154:37f96f9d4de2 | 638 | uint32_t absError; |
<> | 154:37f96f9d4de2 | 639 | uint32_t bestError = UINT32_MAX; |
<> | 154:37f96f9d4de2 | 640 | uint32_t bestMult = 0u; |
<> | 154:37f96f9d4de2 | 641 | uint32_t bestIcr = 0u; |
<> | 154:37f96f9d4de2 | 642 | uint8_t mult; |
<> | 154:37f96f9d4de2 | 643 | uint8_t i; |
<> | 154:37f96f9d4de2 | 644 | |
<> | 154:37f96f9d4de2 | 645 | /* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register, |
<> | 154:37f96f9d4de2 | 646 | * and ranges from 0-2. It selects the multiplier factor for the divider. */ |
<> | 154:37f96f9d4de2 | 647 | for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult) |
<> | 154:37f96f9d4de2 | 648 | { |
<> | 154:37f96f9d4de2 | 649 | multiplier = 1u << mult; |
<> | 154:37f96f9d4de2 | 650 | |
<> | 154:37f96f9d4de2 | 651 | /* Scan table to find best match. */ |
<> | 154:37f96f9d4de2 | 652 | for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(uint16_t); ++i) |
<> | 154:37f96f9d4de2 | 653 | { |
<> | 154:37f96f9d4de2 | 654 | computedRate = srcClock_Hz / (multiplier * s_i2cDividerTable[i]); |
<> | 154:37f96f9d4de2 | 655 | absError = baudRate_Bps > computedRate ? (baudRate_Bps - computedRate) : (computedRate - baudRate_Bps); |
<> | 154:37f96f9d4de2 | 656 | |
<> | 154:37f96f9d4de2 | 657 | if (absError < bestError) |
<> | 154:37f96f9d4de2 | 658 | { |
<> | 154:37f96f9d4de2 | 659 | bestMult = mult; |
<> | 154:37f96f9d4de2 | 660 | bestIcr = i; |
<> | 154:37f96f9d4de2 | 661 | bestError = absError; |
<> | 154:37f96f9d4de2 | 662 | |
<> | 154:37f96f9d4de2 | 663 | /* If the error is 0, then we can stop searching because we won't find a better match. */ |
<> | 154:37f96f9d4de2 | 664 | if (absError == 0) |
<> | 154:37f96f9d4de2 | 665 | { |
<> | 154:37f96f9d4de2 | 666 | break; |
<> | 154:37f96f9d4de2 | 667 | } |
<> | 154:37f96f9d4de2 | 668 | } |
<> | 154:37f96f9d4de2 | 669 | } |
<> | 154:37f96f9d4de2 | 670 | } |
<> | 154:37f96f9d4de2 | 671 | |
<> | 154:37f96f9d4de2 | 672 | /* Set frequency register based on best settings. */ |
<> | 154:37f96f9d4de2 | 673 | base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr); |
<> | 154:37f96f9d4de2 | 674 | } |
<> | 154:37f96f9d4de2 | 675 | |
<> | 154:37f96f9d4de2 | 676 | status_t I2C_MasterStart(I2C_Type *base, uint8_t address, i2c_direction_t direction) |
<> | 154:37f96f9d4de2 | 677 | { |
<> | 154:37f96f9d4de2 | 678 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 679 | uint32_t statusFlags = I2C_MasterGetStatusFlags(base); |
<> | 154:37f96f9d4de2 | 680 | |
<> | 154:37f96f9d4de2 | 681 | /* Return an error if the bus is already in use. */ |
<> | 154:37f96f9d4de2 | 682 | if (statusFlags & kI2C_BusBusyFlag) |
<> | 154:37f96f9d4de2 | 683 | { |
<> | 154:37f96f9d4de2 | 684 | result = kStatus_I2C_Busy; |
<> | 154:37f96f9d4de2 | 685 | } |
<> | 154:37f96f9d4de2 | 686 | else |
<> | 154:37f96f9d4de2 | 687 | { |
<> | 154:37f96f9d4de2 | 688 | /* Send the START signal. */ |
<> | 154:37f96f9d4de2 | 689 | base->C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK; |
<> | 154:37f96f9d4de2 | 690 | |
<> | 154:37f96f9d4de2 | 691 | #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING |
<> | 154:37f96f9d4de2 | 692 | while (!(base->S2 & I2C_S2_EMPTY_MASK)) |
<> | 154:37f96f9d4de2 | 693 | { |
<> | 154:37f96f9d4de2 | 694 | } |
<> | 154:37f96f9d4de2 | 695 | #endif /* FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING */ |
<> | 154:37f96f9d4de2 | 696 | |
<> | 154:37f96f9d4de2 | 697 | base->D = (((uint32_t)address) << 1U | ((direction == kI2C_Read) ? 1U : 0U)); |
<> | 154:37f96f9d4de2 | 698 | } |
<> | 154:37f96f9d4de2 | 699 | |
<> | 154:37f96f9d4de2 | 700 | return result; |
<> | 154:37f96f9d4de2 | 701 | } |
<> | 154:37f96f9d4de2 | 702 | |
<> | 154:37f96f9d4de2 | 703 | status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction) |
<> | 154:37f96f9d4de2 | 704 | { |
<> | 154:37f96f9d4de2 | 705 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 706 | uint8_t savedMult; |
<> | 154:37f96f9d4de2 | 707 | uint32_t statusFlags = I2C_MasterGetStatusFlags(base); |
<> | 154:37f96f9d4de2 | 708 | uint8_t timeDelay = 6; |
<> | 154:37f96f9d4de2 | 709 | |
<> | 154:37f96f9d4de2 | 710 | /* Return an error if the bus is already in use, but not by us. */ |
<> | 154:37f96f9d4de2 | 711 | if ((statusFlags & kI2C_BusBusyFlag) && ((base->C1 & I2C_C1_MST_MASK) == 0)) |
<> | 154:37f96f9d4de2 | 712 | { |
<> | 154:37f96f9d4de2 | 713 | result = kStatus_I2C_Busy; |
<> | 154:37f96f9d4de2 | 714 | } |
<> | 154:37f96f9d4de2 | 715 | else |
<> | 154:37f96f9d4de2 | 716 | { |
<> | 154:37f96f9d4de2 | 717 | savedMult = base->F; |
<> | 154:37f96f9d4de2 | 718 | base->F = savedMult & (~I2C_F_MULT_MASK); |
<> | 154:37f96f9d4de2 | 719 | |
<> | 154:37f96f9d4de2 | 720 | /* We are already in a transfer, so send a repeated start. */ |
<> | 154:37f96f9d4de2 | 721 | base->C1 |= I2C_C1_RSTA_MASK | I2C_C1_TX_MASK; |
<> | 154:37f96f9d4de2 | 722 | |
<> | 154:37f96f9d4de2 | 723 | /* Restore the multiplier factor. */ |
<> | 154:37f96f9d4de2 | 724 | base->F = savedMult; |
<> | 154:37f96f9d4de2 | 725 | |
<> | 154:37f96f9d4de2 | 726 | /* Add some delay to wait the Re-Start signal. */ |
<> | 154:37f96f9d4de2 | 727 | while (timeDelay--) |
<> | 154:37f96f9d4de2 | 728 | { |
<> | 154:37f96f9d4de2 | 729 | __NOP(); |
<> | 154:37f96f9d4de2 | 730 | } |
<> | 154:37f96f9d4de2 | 731 | |
<> | 154:37f96f9d4de2 | 732 | #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING |
<> | 154:37f96f9d4de2 | 733 | while (!(base->S2 & I2C_S2_EMPTY_MASK)) |
<> | 154:37f96f9d4de2 | 734 | { |
<> | 154:37f96f9d4de2 | 735 | } |
<> | 154:37f96f9d4de2 | 736 | #endif /* FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING */ |
<> | 154:37f96f9d4de2 | 737 | |
<> | 154:37f96f9d4de2 | 738 | base->D = (((uint32_t)address) << 1U | ((direction == kI2C_Read) ? 1U : 0U)); |
<> | 154:37f96f9d4de2 | 739 | } |
<> | 154:37f96f9d4de2 | 740 | |
<> | 154:37f96f9d4de2 | 741 | return result; |
<> | 154:37f96f9d4de2 | 742 | } |
<> | 154:37f96f9d4de2 | 743 | |
<> | 154:37f96f9d4de2 | 744 | status_t I2C_MasterStop(I2C_Type *base) |
<> | 154:37f96f9d4de2 | 745 | { |
<> | 154:37f96f9d4de2 | 746 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 747 | uint16_t timeout = UINT16_MAX; |
<> | 154:37f96f9d4de2 | 748 | |
<> | 154:37f96f9d4de2 | 749 | /* Issue the STOP command on the bus. */ |
<> | 154:37f96f9d4de2 | 750 | base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 751 | |
<> | 154:37f96f9d4de2 | 752 | /* Wait until data transfer complete. */ |
<> | 154:37f96f9d4de2 | 753 | while ((base->S & kI2C_BusBusyFlag) && (--timeout)) |
<> | 154:37f96f9d4de2 | 754 | { |
<> | 154:37f96f9d4de2 | 755 | } |
<> | 154:37f96f9d4de2 | 756 | |
<> | 154:37f96f9d4de2 | 757 | if (timeout == 0) |
<> | 154:37f96f9d4de2 | 758 | { |
<> | 154:37f96f9d4de2 | 759 | result = kStatus_I2C_Timeout; |
<> | 154:37f96f9d4de2 | 760 | } |
<> | 154:37f96f9d4de2 | 761 | |
<> | 154:37f96f9d4de2 | 762 | return result; |
<> | 154:37f96f9d4de2 | 763 | } |
<> | 154:37f96f9d4de2 | 764 | |
<> | 154:37f96f9d4de2 | 765 | uint32_t I2C_MasterGetStatusFlags(I2C_Type *base) |
<> | 154:37f96f9d4de2 | 766 | { |
<> | 154:37f96f9d4de2 | 767 | uint32_t statusFlags = base->S; |
<> | 154:37f96f9d4de2 | 768 | |
<> | 154:37f96f9d4de2 | 769 | #ifdef I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 770 | /* Look up the STOPF bit from the filter register. */ |
<> | 154:37f96f9d4de2 | 771 | if (base->FLT & I2C_FLT_STOPF_MASK) |
<> | 154:37f96f9d4de2 | 772 | { |
<> | 154:37f96f9d4de2 | 773 | statusFlags |= kI2C_StopDetectFlag; |
<> | 154:37f96f9d4de2 | 774 | } |
<> | 154:37f96f9d4de2 | 775 | #endif |
<> | 154:37f96f9d4de2 | 776 | |
<> | 154:37f96f9d4de2 | 777 | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT |
<> | 154:37f96f9d4de2 | 778 | /* Look up the STARTF bit from the filter register. */ |
<> | 154:37f96f9d4de2 | 779 | if (base->FLT & I2C_FLT_STARTF_MASK) |
<> | 154:37f96f9d4de2 | 780 | { |
<> | 154:37f96f9d4de2 | 781 | statusFlags |= kI2C_StartDetectFlag; |
<> | 154:37f96f9d4de2 | 782 | } |
<> | 154:37f96f9d4de2 | 783 | #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 784 | |
<> | 154:37f96f9d4de2 | 785 | return statusFlags; |
<> | 154:37f96f9d4de2 | 786 | } |
<> | 154:37f96f9d4de2 | 787 | |
<> | 154:37f96f9d4de2 | 788 | status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags) |
<> | 154:37f96f9d4de2 | 789 | { |
<> | 154:37f96f9d4de2 | 790 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 791 | uint8_t statusFlags = 0; |
<> | 154:37f96f9d4de2 | 792 | |
<> | 154:37f96f9d4de2 | 793 | /* Wait until the data register is ready for transmit. */ |
<> | 154:37f96f9d4de2 | 794 | while (!(base->S & kI2C_TransferCompleteFlag)) |
<> | 154:37f96f9d4de2 | 795 | { |
<> | 154:37f96f9d4de2 | 796 | } |
<> | 154:37f96f9d4de2 | 797 | |
<> | 154:37f96f9d4de2 | 798 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 799 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 800 | |
<> | 154:37f96f9d4de2 | 801 | /* Setup the I2C peripheral to transmit data. */ |
<> | 154:37f96f9d4de2 | 802 | base->C1 |= I2C_C1_TX_MASK; |
<> | 154:37f96f9d4de2 | 803 | |
<> | 154:37f96f9d4de2 | 804 | while (txSize--) |
<> | 154:37f96f9d4de2 | 805 | { |
<> | 154:37f96f9d4de2 | 806 | /* Send a byte of data. */ |
<> | 154:37f96f9d4de2 | 807 | base->D = *txBuff++; |
<> | 154:37f96f9d4de2 | 808 | |
<> | 154:37f96f9d4de2 | 809 | /* Wait until data transfer complete. */ |
<> | 154:37f96f9d4de2 | 810 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 811 | { |
<> | 154:37f96f9d4de2 | 812 | } |
<> | 154:37f96f9d4de2 | 813 | |
<> | 154:37f96f9d4de2 | 814 | statusFlags = base->S; |
<> | 154:37f96f9d4de2 | 815 | |
<> | 154:37f96f9d4de2 | 816 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 817 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 818 | |
<> | 154:37f96f9d4de2 | 819 | /* Check if arbitration lost or no acknowledgement (NAK), return failure status. */ |
<> | 154:37f96f9d4de2 | 820 | if (statusFlags & kI2C_ArbitrationLostFlag) |
<> | 154:37f96f9d4de2 | 821 | { |
<> | 154:37f96f9d4de2 | 822 | base->S = kI2C_ArbitrationLostFlag; |
<> | 154:37f96f9d4de2 | 823 | result = kStatus_I2C_ArbitrationLost; |
<> | 154:37f96f9d4de2 | 824 | } |
<> | 154:37f96f9d4de2 | 825 | |
<> | 154:37f96f9d4de2 | 826 | if ((statusFlags & kI2C_ReceiveNakFlag) && txSize) |
<> | 154:37f96f9d4de2 | 827 | { |
<> | 154:37f96f9d4de2 | 828 | base->S = kI2C_ReceiveNakFlag; |
<> | 154:37f96f9d4de2 | 829 | result = kStatus_I2C_Nak; |
<> | 154:37f96f9d4de2 | 830 | } |
<> | 154:37f96f9d4de2 | 831 | |
<> | 154:37f96f9d4de2 | 832 | if (result != kStatus_Success) |
<> | 154:37f96f9d4de2 | 833 | { |
<> | 154:37f96f9d4de2 | 834 | /* Breaking out of the send loop. */ |
<> | 154:37f96f9d4de2 | 835 | break; |
<> | 154:37f96f9d4de2 | 836 | } |
<> | 154:37f96f9d4de2 | 837 | } |
<> | 154:37f96f9d4de2 | 838 | |
<> | 154:37f96f9d4de2 | 839 | if (((result == kStatus_Success) && (!(flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak)) |
<> | 154:37f96f9d4de2 | 840 | { |
<> | 154:37f96f9d4de2 | 841 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 842 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 843 | |
<> | 154:37f96f9d4de2 | 844 | /* Send stop. */ |
<> | 154:37f96f9d4de2 | 845 | result = I2C_MasterStop(base); |
<> | 154:37f96f9d4de2 | 846 | } |
<> | 154:37f96f9d4de2 | 847 | |
<> | 154:37f96f9d4de2 | 848 | return result; |
<> | 154:37f96f9d4de2 | 849 | } |
<> | 154:37f96f9d4de2 | 850 | |
<> | 154:37f96f9d4de2 | 851 | status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags) |
<> | 154:37f96f9d4de2 | 852 | { |
<> | 154:37f96f9d4de2 | 853 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 854 | volatile uint8_t dummy = 0; |
<> | 154:37f96f9d4de2 | 855 | |
<> | 154:37f96f9d4de2 | 856 | /* Add this to avoid build warning. */ |
<> | 154:37f96f9d4de2 | 857 | dummy++; |
<> | 154:37f96f9d4de2 | 858 | |
<> | 154:37f96f9d4de2 | 859 | /* Wait until the data register is ready for transmit. */ |
<> | 154:37f96f9d4de2 | 860 | while (!(base->S & kI2C_TransferCompleteFlag)) |
<> | 154:37f96f9d4de2 | 861 | { |
<> | 154:37f96f9d4de2 | 862 | } |
<> | 154:37f96f9d4de2 | 863 | |
<> | 154:37f96f9d4de2 | 864 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 865 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 866 | |
<> | 154:37f96f9d4de2 | 867 | /* Setup the I2C peripheral to receive data. */ |
<> | 154:37f96f9d4de2 | 868 | base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 869 | |
<> | 154:37f96f9d4de2 | 870 | /* If rxSize equals 1, configure to send NAK. */ |
<> | 154:37f96f9d4de2 | 871 | if (rxSize == 1) |
<> | 154:37f96f9d4de2 | 872 | { |
<> | 154:37f96f9d4de2 | 873 | /* Issue NACK on read. */ |
<> | 154:37f96f9d4de2 | 874 | base->C1 |= I2C_C1_TXAK_MASK; |
<> | 154:37f96f9d4de2 | 875 | } |
<> | 154:37f96f9d4de2 | 876 | |
<> | 154:37f96f9d4de2 | 877 | /* Do dummy read. */ |
<> | 154:37f96f9d4de2 | 878 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 879 | |
<> | 154:37f96f9d4de2 | 880 | while ((rxSize--)) |
<> | 154:37f96f9d4de2 | 881 | { |
<> | 154:37f96f9d4de2 | 882 | /* Wait until data transfer complete. */ |
<> | 154:37f96f9d4de2 | 883 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 884 | { |
<> | 154:37f96f9d4de2 | 885 | } |
<> | 154:37f96f9d4de2 | 886 | |
<> | 154:37f96f9d4de2 | 887 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 888 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 889 | |
<> | 154:37f96f9d4de2 | 890 | /* Single byte use case. */ |
<> | 154:37f96f9d4de2 | 891 | if (rxSize == 0) |
<> | 154:37f96f9d4de2 | 892 | { |
<> | 154:37f96f9d4de2 | 893 | if (!(flags & kI2C_TransferNoStopFlag)) |
<> | 154:37f96f9d4de2 | 894 | { |
<> | 154:37f96f9d4de2 | 895 | /* Issue STOP command before reading last byte. */ |
<> | 154:37f96f9d4de2 | 896 | result = I2C_MasterStop(base); |
<> | 154:37f96f9d4de2 | 897 | } |
<> | 154:37f96f9d4de2 | 898 | else |
<> | 154:37f96f9d4de2 | 899 | { |
<> | 154:37f96f9d4de2 | 900 | /* Change direction to Tx to avoid extra clocks. */ |
<> | 154:37f96f9d4de2 | 901 | base->C1 |= I2C_C1_TX_MASK; |
<> | 154:37f96f9d4de2 | 902 | } |
<> | 154:37f96f9d4de2 | 903 | } |
<> | 154:37f96f9d4de2 | 904 | |
<> | 154:37f96f9d4de2 | 905 | if (rxSize == 1) |
<> | 154:37f96f9d4de2 | 906 | { |
<> | 154:37f96f9d4de2 | 907 | /* Issue NACK on read. */ |
<> | 154:37f96f9d4de2 | 908 | base->C1 |= I2C_C1_TXAK_MASK; |
<> | 154:37f96f9d4de2 | 909 | } |
<> | 154:37f96f9d4de2 | 910 | |
<> | 154:37f96f9d4de2 | 911 | /* Read from the data register. */ |
<> | 154:37f96f9d4de2 | 912 | *rxBuff++ = base->D; |
<> | 154:37f96f9d4de2 | 913 | } |
<> | 154:37f96f9d4de2 | 914 | |
<> | 154:37f96f9d4de2 | 915 | return result; |
<> | 154:37f96f9d4de2 | 916 | } |
<> | 154:37f96f9d4de2 | 917 | |
<> | 154:37f96f9d4de2 | 918 | status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) |
<> | 154:37f96f9d4de2 | 919 | { |
<> | 154:37f96f9d4de2 | 920 | assert(xfer); |
<> | 154:37f96f9d4de2 | 921 | |
<> | 154:37f96f9d4de2 | 922 | i2c_direction_t direction = xfer->direction; |
<> | 154:37f96f9d4de2 | 923 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 924 | |
<> | 154:37f96f9d4de2 | 925 | /* Clear all status before transfer. */ |
<> | 154:37f96f9d4de2 | 926 | I2C_MasterClearStatusFlags(base, kClearFlags); |
<> | 154:37f96f9d4de2 | 927 | |
<> | 154:37f96f9d4de2 | 928 | /* Wait until ready to complete. */ |
<> | 154:37f96f9d4de2 | 929 | while (!(base->S & kI2C_TransferCompleteFlag)) |
<> | 154:37f96f9d4de2 | 930 | { |
<> | 154:37f96f9d4de2 | 931 | } |
<> | 154:37f96f9d4de2 | 932 | |
<> | 154:37f96f9d4de2 | 933 | /* Change to send write address when it's a read operation with command. */ |
<> | 154:37f96f9d4de2 | 934 | if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read)) |
<> | 154:37f96f9d4de2 | 935 | { |
<> | 154:37f96f9d4de2 | 936 | direction = kI2C_Write; |
<> | 154:37f96f9d4de2 | 937 | } |
<> | 154:37f96f9d4de2 | 938 | |
<> | 154:37f96f9d4de2 | 939 | /* If repeated start is requested, send repeated start. */ |
<> | 154:37f96f9d4de2 | 940 | if (xfer->flags & kI2C_TransferRepeatedStartFlag) |
<> | 154:37f96f9d4de2 | 941 | { |
<> | 154:37f96f9d4de2 | 942 | result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, direction); |
<> | 154:37f96f9d4de2 | 943 | } |
<> | 154:37f96f9d4de2 | 944 | else /* For normal transfer, send start. */ |
<> | 154:37f96f9d4de2 | 945 | { |
<> | 154:37f96f9d4de2 | 946 | result = I2C_MasterStart(base, xfer->slaveAddress, direction); |
<> | 154:37f96f9d4de2 | 947 | } |
<> | 154:37f96f9d4de2 | 948 | |
<> | 154:37f96f9d4de2 | 949 | /* Return if error. */ |
<> | 154:37f96f9d4de2 | 950 | if (result) |
<> | 154:37f96f9d4de2 | 951 | { |
<> | 154:37f96f9d4de2 | 952 | return result; |
<> | 154:37f96f9d4de2 | 953 | } |
<> | 154:37f96f9d4de2 | 954 | |
<> | 154:37f96f9d4de2 | 955 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 956 | { |
<> | 154:37f96f9d4de2 | 957 | } |
<> | 154:37f96f9d4de2 | 958 | |
<> | 154:37f96f9d4de2 | 959 | /* Check if there's transfer error. */ |
<> | 154:37f96f9d4de2 | 960 | result = I2C_CheckAndClearError(base, base->S); |
<> | 154:37f96f9d4de2 | 961 | |
<> | 154:37f96f9d4de2 | 962 | /* Return if error. */ |
<> | 154:37f96f9d4de2 | 963 | if (result) |
<> | 154:37f96f9d4de2 | 964 | { |
<> | 154:37f96f9d4de2 | 965 | if (result == kStatus_I2C_Nak) |
<> | 154:37f96f9d4de2 | 966 | { |
<> | 154:37f96f9d4de2 | 967 | result = kStatus_I2C_Addr_Nak; |
<> | 154:37f96f9d4de2 | 968 | |
<> | 154:37f96f9d4de2 | 969 | I2C_MasterStop(base); |
<> | 154:37f96f9d4de2 | 970 | } |
<> | 154:37f96f9d4de2 | 971 | |
<> | 154:37f96f9d4de2 | 972 | return result; |
<> | 154:37f96f9d4de2 | 973 | } |
<> | 154:37f96f9d4de2 | 974 | |
<> | 154:37f96f9d4de2 | 975 | /* Send subaddress. */ |
<> | 154:37f96f9d4de2 | 976 | if (xfer->subaddressSize) |
<> | 154:37f96f9d4de2 | 977 | { |
<> | 154:37f96f9d4de2 | 978 | do |
<> | 154:37f96f9d4de2 | 979 | { |
<> | 154:37f96f9d4de2 | 980 | /* Clear interrupt pending flag. */ |
<> | 154:37f96f9d4de2 | 981 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 982 | |
<> | 154:37f96f9d4de2 | 983 | xfer->subaddressSize--; |
<> | 154:37f96f9d4de2 | 984 | base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); |
<> | 154:37f96f9d4de2 | 985 | |
<> | 154:37f96f9d4de2 | 986 | /* Wait until data transfer complete. */ |
<> | 154:37f96f9d4de2 | 987 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 988 | { |
<> | 154:37f96f9d4de2 | 989 | } |
<> | 154:37f96f9d4de2 | 990 | |
<> | 154:37f96f9d4de2 | 991 | /* Check if there's transfer error. */ |
<> | 154:37f96f9d4de2 | 992 | result = I2C_CheckAndClearError(base, base->S); |
<> | 154:37f96f9d4de2 | 993 | |
<> | 154:37f96f9d4de2 | 994 | if (result) |
<> | 154:37f96f9d4de2 | 995 | { |
<> | 154:37f96f9d4de2 | 996 | if (result == kStatus_I2C_Nak) |
<> | 154:37f96f9d4de2 | 997 | { |
<> | 154:37f96f9d4de2 | 998 | I2C_MasterStop(base); |
<> | 154:37f96f9d4de2 | 999 | } |
<> | 154:37f96f9d4de2 | 1000 | |
<> | 154:37f96f9d4de2 | 1001 | return result; |
<> | 154:37f96f9d4de2 | 1002 | } |
<> | 154:37f96f9d4de2 | 1003 | |
<> | 154:37f96f9d4de2 | 1004 | } while ((xfer->subaddressSize > 0) && (result == kStatus_Success)); |
<> | 154:37f96f9d4de2 | 1005 | |
<> | 154:37f96f9d4de2 | 1006 | if (xfer->direction == kI2C_Read) |
<> | 154:37f96f9d4de2 | 1007 | { |
<> | 154:37f96f9d4de2 | 1008 | /* Clear pending flag. */ |
<> | 154:37f96f9d4de2 | 1009 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1010 | |
<> | 154:37f96f9d4de2 | 1011 | /* Send repeated start and slave address. */ |
<> | 154:37f96f9d4de2 | 1012 | result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read); |
<> | 154:37f96f9d4de2 | 1013 | |
<> | 154:37f96f9d4de2 | 1014 | /* Return if error. */ |
<> | 154:37f96f9d4de2 | 1015 | if (result) |
<> | 154:37f96f9d4de2 | 1016 | { |
<> | 154:37f96f9d4de2 | 1017 | return result; |
<> | 154:37f96f9d4de2 | 1018 | } |
<> | 154:37f96f9d4de2 | 1019 | |
<> | 154:37f96f9d4de2 | 1020 | /* Wait until data transfer complete. */ |
<> | 154:37f96f9d4de2 | 1021 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 1022 | { |
<> | 154:37f96f9d4de2 | 1023 | } |
<> | 154:37f96f9d4de2 | 1024 | |
<> | 154:37f96f9d4de2 | 1025 | /* Check if there's transfer error. */ |
<> | 154:37f96f9d4de2 | 1026 | result = I2C_CheckAndClearError(base, base->S); |
<> | 154:37f96f9d4de2 | 1027 | |
<> | 154:37f96f9d4de2 | 1028 | if (result) |
<> | 154:37f96f9d4de2 | 1029 | { |
<> | 154:37f96f9d4de2 | 1030 | if (result == kStatus_I2C_Nak) |
<> | 154:37f96f9d4de2 | 1031 | { |
<> | 154:37f96f9d4de2 | 1032 | result = kStatus_I2C_Addr_Nak; |
<> | 154:37f96f9d4de2 | 1033 | |
<> | 154:37f96f9d4de2 | 1034 | I2C_MasterStop(base); |
<> | 154:37f96f9d4de2 | 1035 | } |
<> | 154:37f96f9d4de2 | 1036 | |
<> | 154:37f96f9d4de2 | 1037 | return result; |
<> | 154:37f96f9d4de2 | 1038 | } |
<> | 154:37f96f9d4de2 | 1039 | } |
<> | 154:37f96f9d4de2 | 1040 | } |
<> | 154:37f96f9d4de2 | 1041 | |
<> | 154:37f96f9d4de2 | 1042 | /* Transmit data. */ |
<> | 154:37f96f9d4de2 | 1043 | if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0)) |
<> | 154:37f96f9d4de2 | 1044 | { |
<> | 154:37f96f9d4de2 | 1045 | /* Send Data. */ |
<> | 154:37f96f9d4de2 | 1046 | result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags); |
<> | 154:37f96f9d4de2 | 1047 | } |
<> | 154:37f96f9d4de2 | 1048 | |
<> | 154:37f96f9d4de2 | 1049 | /* Receive Data. */ |
<> | 154:37f96f9d4de2 | 1050 | if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0)) |
<> | 154:37f96f9d4de2 | 1051 | { |
<> | 154:37f96f9d4de2 | 1052 | result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags); |
<> | 154:37f96f9d4de2 | 1053 | } |
<> | 154:37f96f9d4de2 | 1054 | |
<> | 154:37f96f9d4de2 | 1055 | return result; |
<> | 154:37f96f9d4de2 | 1056 | } |
<> | 154:37f96f9d4de2 | 1057 | |
<> | 154:37f96f9d4de2 | 1058 | void I2C_MasterTransferCreateHandle(I2C_Type *base, |
<> | 154:37f96f9d4de2 | 1059 | i2c_master_handle_t *handle, |
<> | 154:37f96f9d4de2 | 1060 | i2c_master_transfer_callback_t callback, |
<> | 154:37f96f9d4de2 | 1061 | void *userData) |
<> | 154:37f96f9d4de2 | 1062 | { |
<> | 154:37f96f9d4de2 | 1063 | assert(handle); |
<> | 154:37f96f9d4de2 | 1064 | |
<> | 154:37f96f9d4de2 | 1065 | uint32_t instance = I2C_GetInstance(base); |
<> | 154:37f96f9d4de2 | 1066 | |
<> | 154:37f96f9d4de2 | 1067 | /* Zero handle. */ |
<> | 154:37f96f9d4de2 | 1068 | memset(handle, 0, sizeof(*handle)); |
<> | 154:37f96f9d4de2 | 1069 | |
<> | 154:37f96f9d4de2 | 1070 | /* Set callback and userData. */ |
<> | 154:37f96f9d4de2 | 1071 | handle->completionCallback = callback; |
<> | 154:37f96f9d4de2 | 1072 | handle->userData = userData; |
<> | 154:37f96f9d4de2 | 1073 | |
<> | 154:37f96f9d4de2 | 1074 | /* Save the context in global variables to support the double weak mechanism. */ |
<> | 154:37f96f9d4de2 | 1075 | s_i2cHandle[instance] = handle; |
<> | 154:37f96f9d4de2 | 1076 | |
<> | 154:37f96f9d4de2 | 1077 | /* Save master interrupt handler. */ |
<> | 154:37f96f9d4de2 | 1078 | s_i2cMasterIsr = I2C_MasterTransferHandleIRQ; |
<> | 154:37f96f9d4de2 | 1079 | |
<> | 154:37f96f9d4de2 | 1080 | /* Enable NVIC interrupt. */ |
<> | 154:37f96f9d4de2 | 1081 | EnableIRQ(s_i2cIrqs[instance]); |
<> | 154:37f96f9d4de2 | 1082 | } |
<> | 154:37f96f9d4de2 | 1083 | |
<> | 154:37f96f9d4de2 | 1084 | status_t I2C_MasterTransferNonBlocking(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer) |
<> | 154:37f96f9d4de2 | 1085 | { |
<> | 154:37f96f9d4de2 | 1086 | assert(handle); |
<> | 154:37f96f9d4de2 | 1087 | assert(xfer); |
<> | 154:37f96f9d4de2 | 1088 | |
<> | 154:37f96f9d4de2 | 1089 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 1090 | |
<> | 154:37f96f9d4de2 | 1091 | /* Check if the I2C bus is idle - if not return busy status. */ |
<> | 154:37f96f9d4de2 | 1092 | if (handle->state != kIdleState) |
<> | 154:37f96f9d4de2 | 1093 | { |
<> | 154:37f96f9d4de2 | 1094 | result = kStatus_I2C_Busy; |
<> | 154:37f96f9d4de2 | 1095 | } |
<> | 154:37f96f9d4de2 | 1096 | else |
<> | 154:37f96f9d4de2 | 1097 | { |
<> | 154:37f96f9d4de2 | 1098 | /* Start up the master transfer state machine. */ |
<> | 154:37f96f9d4de2 | 1099 | result = I2C_InitTransferStateMachine(base, handle, xfer); |
<> | 154:37f96f9d4de2 | 1100 | |
<> | 154:37f96f9d4de2 | 1101 | if (result == kStatus_Success) |
<> | 154:37f96f9d4de2 | 1102 | { |
<> | 154:37f96f9d4de2 | 1103 | /* Enable the I2C interrupts. */ |
<> | 154:37f96f9d4de2 | 1104 | I2C_EnableInterrupts(base, kI2C_GlobalInterruptEnable); |
<> | 154:37f96f9d4de2 | 1105 | } |
<> | 154:37f96f9d4de2 | 1106 | } |
<> | 154:37f96f9d4de2 | 1107 | |
<> | 154:37f96f9d4de2 | 1108 | return result; |
<> | 154:37f96f9d4de2 | 1109 | } |
<> | 154:37f96f9d4de2 | 1110 | |
<> | 154:37f96f9d4de2 | 1111 | void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1112 | { |
<> | 154:37f96f9d4de2 | 1113 | assert(handle); |
<> | 154:37f96f9d4de2 | 1114 | |
<> | 154:37f96f9d4de2 | 1115 | volatile uint8_t dummy = 0; |
<> | 154:37f96f9d4de2 | 1116 | |
<> | 154:37f96f9d4de2 | 1117 | /* Add this to avoid build warning. */ |
<> | 154:37f96f9d4de2 | 1118 | dummy++; |
<> | 154:37f96f9d4de2 | 1119 | |
<> | 154:37f96f9d4de2 | 1120 | /* Disable interrupt. */ |
<> | 154:37f96f9d4de2 | 1121 | I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable); |
<> | 154:37f96f9d4de2 | 1122 | |
<> | 154:37f96f9d4de2 | 1123 | /* Reset the state to idle. */ |
<> | 154:37f96f9d4de2 | 1124 | handle->state = kIdleState; |
<> | 154:37f96f9d4de2 | 1125 | |
<> | 154:37f96f9d4de2 | 1126 | /* Send STOP signal. */ |
<> | 154:37f96f9d4de2 | 1127 | if (handle->transfer.direction == kI2C_Read) |
<> | 154:37f96f9d4de2 | 1128 | { |
<> | 154:37f96f9d4de2 | 1129 | base->C1 |= I2C_C1_TXAK_MASK; |
<> | 154:37f96f9d4de2 | 1130 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 1131 | { |
<> | 154:37f96f9d4de2 | 1132 | } |
<> | 154:37f96f9d4de2 | 1133 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1134 | |
<> | 154:37f96f9d4de2 | 1135 | base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 1136 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 1137 | } |
<> | 154:37f96f9d4de2 | 1138 | else |
<> | 154:37f96f9d4de2 | 1139 | { |
<> | 154:37f96f9d4de2 | 1140 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 1141 | { |
<> | 154:37f96f9d4de2 | 1142 | } |
<> | 154:37f96f9d4de2 | 1143 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1144 | base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 1145 | } |
<> | 154:37f96f9d4de2 | 1146 | } |
<> | 154:37f96f9d4de2 | 1147 | |
<> | 154:37f96f9d4de2 | 1148 | status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count) |
<> | 154:37f96f9d4de2 | 1149 | { |
<> | 154:37f96f9d4de2 | 1150 | assert(handle); |
<> | 154:37f96f9d4de2 | 1151 | |
<> | 154:37f96f9d4de2 | 1152 | if (!count) |
<> | 154:37f96f9d4de2 | 1153 | { |
<> | 154:37f96f9d4de2 | 1154 | return kStatus_InvalidArgument; |
<> | 154:37f96f9d4de2 | 1155 | } |
<> | 154:37f96f9d4de2 | 1156 | |
<> | 154:37f96f9d4de2 | 1157 | *count = handle->transferSize - handle->transfer.dataSize; |
<> | 154:37f96f9d4de2 | 1158 | |
<> | 154:37f96f9d4de2 | 1159 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1160 | } |
<> | 154:37f96f9d4de2 | 1161 | |
<> | 154:37f96f9d4de2 | 1162 | void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle) |
<> | 154:37f96f9d4de2 | 1163 | { |
<> | 154:37f96f9d4de2 | 1164 | assert(i2cHandle); |
<> | 154:37f96f9d4de2 | 1165 | |
<> | 154:37f96f9d4de2 | 1166 | i2c_master_handle_t *handle = (i2c_master_handle_t *)i2cHandle; |
<> | 154:37f96f9d4de2 | 1167 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 1168 | bool isDone; |
<> | 154:37f96f9d4de2 | 1169 | |
<> | 154:37f96f9d4de2 | 1170 | /* Clear the interrupt flag. */ |
<> | 154:37f96f9d4de2 | 1171 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1172 | |
<> | 154:37f96f9d4de2 | 1173 | /* Check transfer complete flag. */ |
<> | 154:37f96f9d4de2 | 1174 | result = I2C_MasterTransferRunStateMachine(base, handle, &isDone); |
<> | 154:37f96f9d4de2 | 1175 | |
<> | 154:37f96f9d4de2 | 1176 | if (isDone || result) |
<> | 154:37f96f9d4de2 | 1177 | { |
<> | 154:37f96f9d4de2 | 1178 | /* Send stop command if transfer done or received Nak. */ |
<> | 154:37f96f9d4de2 | 1179 | if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak) || |
<> | 154:37f96f9d4de2 | 1180 | (result == kStatus_I2C_Addr_Nak)) |
<> | 154:37f96f9d4de2 | 1181 | { |
<> | 154:37f96f9d4de2 | 1182 | /* Ensure stop command is a need. */ |
<> | 154:37f96f9d4de2 | 1183 | if ((base->C1 & I2C_C1_MST_MASK)) |
<> | 154:37f96f9d4de2 | 1184 | { |
<> | 154:37f96f9d4de2 | 1185 | if (I2C_MasterStop(base) != kStatus_Success) |
<> | 154:37f96f9d4de2 | 1186 | { |
<> | 154:37f96f9d4de2 | 1187 | result = kStatus_I2C_Timeout; |
<> | 154:37f96f9d4de2 | 1188 | } |
<> | 154:37f96f9d4de2 | 1189 | } |
<> | 154:37f96f9d4de2 | 1190 | } |
<> | 154:37f96f9d4de2 | 1191 | |
<> | 154:37f96f9d4de2 | 1192 | /* Restore handle to idle state. */ |
<> | 154:37f96f9d4de2 | 1193 | handle->state = kIdleState; |
<> | 154:37f96f9d4de2 | 1194 | |
<> | 154:37f96f9d4de2 | 1195 | /* Disable interrupt. */ |
<> | 154:37f96f9d4de2 | 1196 | I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable); |
<> | 154:37f96f9d4de2 | 1197 | |
<> | 154:37f96f9d4de2 | 1198 | /* Call the callback function after the function has completed. */ |
<> | 154:37f96f9d4de2 | 1199 | if (handle->completionCallback) |
<> | 154:37f96f9d4de2 | 1200 | { |
<> | 154:37f96f9d4de2 | 1201 | handle->completionCallback(base, handle, result, handle->userData); |
<> | 154:37f96f9d4de2 | 1202 | } |
<> | 154:37f96f9d4de2 | 1203 | } |
<> | 154:37f96f9d4de2 | 1204 | } |
<> | 154:37f96f9d4de2 | 1205 | |
<> | 154:37f96f9d4de2 | 1206 | void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz) |
<> | 154:37f96f9d4de2 | 1207 | { |
<> | 154:37f96f9d4de2 | 1208 | assert(slaveConfig); |
<> | 154:37f96f9d4de2 | 1209 | |
<> | 154:37f96f9d4de2 | 1210 | uint8_t tmpReg; |
<> | 154:37f96f9d4de2 | 1211 | |
<> | 154:37f96f9d4de2 | 1212 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 1213 | CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 1214 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 1215 | |
<> | 154:37f96f9d4de2 | 1216 | /* Configure addressing mode. */ |
<> | 154:37f96f9d4de2 | 1217 | switch (slaveConfig->addressingMode) |
<> | 154:37f96f9d4de2 | 1218 | { |
<> | 154:37f96f9d4de2 | 1219 | case kI2C_Address7bit: |
<> | 154:37f96f9d4de2 | 1220 | base->A1 = ((uint32_t)(slaveConfig->slaveAddress)) << 1U; |
<> | 154:37f96f9d4de2 | 1221 | break; |
<> | 154:37f96f9d4de2 | 1222 | |
<> | 154:37f96f9d4de2 | 1223 | case kI2C_RangeMatch: |
<> | 154:37f96f9d4de2 | 1224 | assert(slaveConfig->slaveAddress < slaveConfig->upperAddress); |
<> | 154:37f96f9d4de2 | 1225 | base->A1 = ((uint32_t)(slaveConfig->slaveAddress)) << 1U; |
<> | 154:37f96f9d4de2 | 1226 | base->RA = ((uint32_t)(slaveConfig->upperAddress)) << 1U; |
<> | 154:37f96f9d4de2 | 1227 | base->C2 |= I2C_C2_RMEN_MASK; |
<> | 154:37f96f9d4de2 | 1228 | break; |
<> | 154:37f96f9d4de2 | 1229 | |
<> | 154:37f96f9d4de2 | 1230 | default: |
<> | 154:37f96f9d4de2 | 1231 | break; |
<> | 154:37f96f9d4de2 | 1232 | } |
<> | 154:37f96f9d4de2 | 1233 | |
<> | 154:37f96f9d4de2 | 1234 | /* Configure low power wake up feature. */ |
<> | 154:37f96f9d4de2 | 1235 | tmpReg = base->C1; |
<> | 154:37f96f9d4de2 | 1236 | tmpReg &= ~I2C_C1_WUEN_MASK; |
<> | 154:37f96f9d4de2 | 1237 | base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave); |
<> | 154:37f96f9d4de2 | 1238 | |
<> | 154:37f96f9d4de2 | 1239 | /* Configure general call & baud rate control & high drive feature. */ |
<> | 154:37f96f9d4de2 | 1240 | tmpReg = base->C2; |
<> | 154:37f96f9d4de2 | 1241 | tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK); |
<> | 154:37f96f9d4de2 | 1242 | tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall); |
<> | 154:37f96f9d4de2 | 1243 | #if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION |
<> | 154:37f96f9d4de2 | 1244 | tmpReg &= ~I2C_C2_HDRS_MASK; |
<> | 154:37f96f9d4de2 | 1245 | tmpReg |= I2C_C2_HDRS(slaveConfig->enableHighDrive); |
<> | 154:37f96f9d4de2 | 1246 | #endif |
<> | 154:37f96f9d4de2 | 1247 | base->C2 = tmpReg; |
<> | 154:37f96f9d4de2 | 1248 | |
<> | 154:37f96f9d4de2 | 1249 | /* Enable/Disable double buffering. */ |
<> | 154:37f96f9d4de2 | 1250 | #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE |
<> | 154:37f96f9d4de2 | 1251 | tmpReg = base->S2 & (~I2C_S2_DFEN_MASK); |
<> | 154:37f96f9d4de2 | 1252 | base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering); |
<> | 154:37f96f9d4de2 | 1253 | #endif |
<> | 154:37f96f9d4de2 | 1254 | |
<> | 154:37f96f9d4de2 | 1255 | /* Set hold time. */ |
<> | 154:37f96f9d4de2 | 1256 | I2C_SetHoldTime(base, slaveConfig->sclStopHoldTime_ns, srcClock_Hz); |
<> | 154:37f96f9d4de2 | 1257 | } |
<> | 154:37f96f9d4de2 | 1258 | |
<> | 154:37f96f9d4de2 | 1259 | void I2C_SlaveDeinit(I2C_Type *base) |
<> | 154:37f96f9d4de2 | 1260 | { |
<> | 154:37f96f9d4de2 | 1261 | /* Disable I2C module. */ |
<> | 154:37f96f9d4de2 | 1262 | I2C_Enable(base, false); |
<> | 154:37f96f9d4de2 | 1263 | |
<> | 154:37f96f9d4de2 | 1264 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 1265 | /* Disable I2C clock. */ |
<> | 154:37f96f9d4de2 | 1266 | CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 1267 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 1268 | } |
<> | 154:37f96f9d4de2 | 1269 | |
<> | 154:37f96f9d4de2 | 1270 | void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig) |
<> | 154:37f96f9d4de2 | 1271 | { |
<> | 154:37f96f9d4de2 | 1272 | assert(slaveConfig); |
<> | 154:37f96f9d4de2 | 1273 | |
<> | 154:37f96f9d4de2 | 1274 | /* By default slave is addressed with 7-bit address. */ |
<> | 154:37f96f9d4de2 | 1275 | slaveConfig->addressingMode = kI2C_Address7bit; |
<> | 154:37f96f9d4de2 | 1276 | |
<> | 154:37f96f9d4de2 | 1277 | /* General call mode is disabled by default. */ |
<> | 154:37f96f9d4de2 | 1278 | slaveConfig->enableGeneralCall = false; |
<> | 154:37f96f9d4de2 | 1279 | |
<> | 154:37f96f9d4de2 | 1280 | /* Slave address match waking up MCU from low power mode is disabled. */ |
<> | 154:37f96f9d4de2 | 1281 | slaveConfig->enableWakeUp = false; |
<> | 154:37f96f9d4de2 | 1282 | |
<> | 154:37f96f9d4de2 | 1283 | #if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION |
<> | 154:37f96f9d4de2 | 1284 | /* Default pin high drive is disabled. */ |
<> | 154:37f96f9d4de2 | 1285 | slaveConfig->enableHighDrive = false; |
<> | 154:37f96f9d4de2 | 1286 | #endif |
<> | 154:37f96f9d4de2 | 1287 | |
<> | 154:37f96f9d4de2 | 1288 | /* Independent slave mode baud rate at maximum frequency is disabled. */ |
<> | 154:37f96f9d4de2 | 1289 | slaveConfig->enableBaudRateCtl = false; |
<> | 154:37f96f9d4de2 | 1290 | |
<> | 154:37f96f9d4de2 | 1291 | /* Default enable double buffering. */ |
<> | 154:37f96f9d4de2 | 1292 | #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE |
<> | 154:37f96f9d4de2 | 1293 | slaveConfig->enableDoubleBuffering = true; |
<> | 154:37f96f9d4de2 | 1294 | #endif |
<> | 154:37f96f9d4de2 | 1295 | |
<> | 154:37f96f9d4de2 | 1296 | /* Set default SCL stop hold time to 4us which is minimum requirement in I2C spec. */ |
<> | 154:37f96f9d4de2 | 1297 | slaveConfig->sclStopHoldTime_ns = 4000; |
<> | 154:37f96f9d4de2 | 1298 | |
<> | 154:37f96f9d4de2 | 1299 | /* Enable the I2C peripheral. */ |
<> | 154:37f96f9d4de2 | 1300 | slaveConfig->enableSlave = true; |
<> | 154:37f96f9d4de2 | 1301 | } |
<> | 154:37f96f9d4de2 | 1302 | |
<> | 154:37f96f9d4de2 | 1303 | status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize) |
<> | 154:37f96f9d4de2 | 1304 | { |
<> | 154:37f96f9d4de2 | 1305 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 1306 | volatile uint8_t dummy = 0; |
<> | 154:37f96f9d4de2 | 1307 | |
<> | 154:37f96f9d4de2 | 1308 | /* Add this to avoid build warning. */ |
<> | 154:37f96f9d4de2 | 1309 | dummy++; |
<> | 154:37f96f9d4de2 | 1310 | |
<> | 154:37f96f9d4de2 | 1311 | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT |
<> | 154:37f96f9d4de2 | 1312 | /* Check start flag. */ |
<> | 154:37f96f9d4de2 | 1313 | while (!(base->FLT & I2C_FLT_STARTF_MASK)) |
<> | 154:37f96f9d4de2 | 1314 | { |
<> | 154:37f96f9d4de2 | 1315 | } |
<> | 154:37f96f9d4de2 | 1316 | /* Clear STARTF flag. */ |
<> | 154:37f96f9d4de2 | 1317 | base->FLT |= I2C_FLT_STARTF_MASK; |
<> | 154:37f96f9d4de2 | 1318 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 1319 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1320 | #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 1321 | |
<> | 154:37f96f9d4de2 | 1322 | /* Wait for address match flag. */ |
<> | 154:37f96f9d4de2 | 1323 | while (!(base->S & kI2C_AddressMatchFlag)) |
<> | 154:37f96f9d4de2 | 1324 | { |
<> | 154:37f96f9d4de2 | 1325 | } |
<> | 154:37f96f9d4de2 | 1326 | |
<> | 154:37f96f9d4de2 | 1327 | /* Read dummy to release bus. */ |
<> | 154:37f96f9d4de2 | 1328 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 1329 | |
<> | 154:37f96f9d4de2 | 1330 | result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag); |
<> | 154:37f96f9d4de2 | 1331 | |
<> | 154:37f96f9d4de2 | 1332 | /* Switch to receive mode. */ |
<> | 154:37f96f9d4de2 | 1333 | base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 1334 | |
<> | 154:37f96f9d4de2 | 1335 | /* Read dummy to release bus. */ |
<> | 154:37f96f9d4de2 | 1336 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 1337 | |
<> | 154:37f96f9d4de2 | 1338 | return result; |
<> | 154:37f96f9d4de2 | 1339 | } |
<> | 154:37f96f9d4de2 | 1340 | |
<> | 154:37f96f9d4de2 | 1341 | void I2C_SlaveReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) |
<> | 154:37f96f9d4de2 | 1342 | { |
<> | 154:37f96f9d4de2 | 1343 | volatile uint8_t dummy = 0; |
<> | 154:37f96f9d4de2 | 1344 | |
<> | 154:37f96f9d4de2 | 1345 | /* Add this to avoid build warning. */ |
<> | 154:37f96f9d4de2 | 1346 | dummy++; |
<> | 154:37f96f9d4de2 | 1347 | |
<> | 154:37f96f9d4de2 | 1348 | /* Wait until address match. */ |
<> | 154:37f96f9d4de2 | 1349 | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT |
<> | 154:37f96f9d4de2 | 1350 | /* Check start flag. */ |
<> | 154:37f96f9d4de2 | 1351 | while (!(base->FLT & I2C_FLT_STARTF_MASK)) |
<> | 154:37f96f9d4de2 | 1352 | { |
<> | 154:37f96f9d4de2 | 1353 | } |
<> | 154:37f96f9d4de2 | 1354 | /* Clear STARTF flag. */ |
<> | 154:37f96f9d4de2 | 1355 | base->FLT |= I2C_FLT_STARTF_MASK; |
<> | 154:37f96f9d4de2 | 1356 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 1357 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1358 | #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 1359 | |
<> | 154:37f96f9d4de2 | 1360 | /* Wait for address match and int pending flag. */ |
<> | 154:37f96f9d4de2 | 1361 | while (!(base->S & kI2C_AddressMatchFlag)) |
<> | 154:37f96f9d4de2 | 1362 | { |
<> | 154:37f96f9d4de2 | 1363 | } |
<> | 154:37f96f9d4de2 | 1364 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 1365 | { |
<> | 154:37f96f9d4de2 | 1366 | } |
<> | 154:37f96f9d4de2 | 1367 | |
<> | 154:37f96f9d4de2 | 1368 | /* Read dummy to release bus. */ |
<> | 154:37f96f9d4de2 | 1369 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 1370 | |
<> | 154:37f96f9d4de2 | 1371 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 1372 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1373 | |
<> | 154:37f96f9d4de2 | 1374 | /* Setup the I2C peripheral to receive data. */ |
<> | 154:37f96f9d4de2 | 1375 | base->C1 &= ~(I2C_C1_TX_MASK); |
<> | 154:37f96f9d4de2 | 1376 | |
<> | 154:37f96f9d4de2 | 1377 | while (rxSize--) |
<> | 154:37f96f9d4de2 | 1378 | { |
<> | 154:37f96f9d4de2 | 1379 | /* Wait until data transfer complete. */ |
<> | 154:37f96f9d4de2 | 1380 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 154:37f96f9d4de2 | 1381 | { |
<> | 154:37f96f9d4de2 | 1382 | } |
<> | 154:37f96f9d4de2 | 1383 | /* Clear the IICIF flag. */ |
<> | 154:37f96f9d4de2 | 1384 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1385 | |
<> | 154:37f96f9d4de2 | 1386 | /* Read from the data register. */ |
<> | 154:37f96f9d4de2 | 1387 | *rxBuff++ = base->D; |
<> | 154:37f96f9d4de2 | 1388 | } |
<> | 154:37f96f9d4de2 | 1389 | } |
<> | 154:37f96f9d4de2 | 1390 | |
<> | 154:37f96f9d4de2 | 1391 | void I2C_SlaveTransferCreateHandle(I2C_Type *base, |
<> | 154:37f96f9d4de2 | 1392 | i2c_slave_handle_t *handle, |
<> | 154:37f96f9d4de2 | 1393 | i2c_slave_transfer_callback_t callback, |
<> | 154:37f96f9d4de2 | 1394 | void *userData) |
<> | 154:37f96f9d4de2 | 1395 | { |
<> | 154:37f96f9d4de2 | 1396 | assert(handle); |
<> | 154:37f96f9d4de2 | 1397 | |
<> | 154:37f96f9d4de2 | 1398 | uint32_t instance = I2C_GetInstance(base); |
<> | 154:37f96f9d4de2 | 1399 | |
<> | 154:37f96f9d4de2 | 1400 | /* Zero handle. */ |
<> | 154:37f96f9d4de2 | 1401 | memset(handle, 0, sizeof(*handle)); |
<> | 154:37f96f9d4de2 | 1402 | |
<> | 154:37f96f9d4de2 | 1403 | /* Set callback and userData. */ |
<> | 154:37f96f9d4de2 | 1404 | handle->callback = callback; |
<> | 154:37f96f9d4de2 | 1405 | handle->userData = userData; |
<> | 154:37f96f9d4de2 | 1406 | |
<> | 154:37f96f9d4de2 | 1407 | /* Save the context in global variables to support the double weak mechanism. */ |
<> | 154:37f96f9d4de2 | 1408 | s_i2cHandle[instance] = handle; |
<> | 154:37f96f9d4de2 | 1409 | |
<> | 154:37f96f9d4de2 | 1410 | /* Save slave interrupt handler. */ |
<> | 154:37f96f9d4de2 | 1411 | s_i2cSlaveIsr = I2C_SlaveTransferHandleIRQ; |
<> | 154:37f96f9d4de2 | 1412 | |
<> | 154:37f96f9d4de2 | 1413 | /* Enable NVIC interrupt. */ |
<> | 154:37f96f9d4de2 | 1414 | EnableIRQ(s_i2cIrqs[instance]); |
<> | 154:37f96f9d4de2 | 1415 | } |
<> | 154:37f96f9d4de2 | 1416 | |
<> | 154:37f96f9d4de2 | 1417 | status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle, uint32_t eventMask) |
<> | 154:37f96f9d4de2 | 1418 | { |
<> | 154:37f96f9d4de2 | 1419 | assert(handle); |
<> | 154:37f96f9d4de2 | 1420 | |
<> | 154:37f96f9d4de2 | 1421 | /* Check if the I2C bus is idle - if not return busy status. */ |
<> | 154:37f96f9d4de2 | 1422 | if (handle->isBusy) |
<> | 154:37f96f9d4de2 | 1423 | { |
<> | 154:37f96f9d4de2 | 1424 | return kStatus_I2C_Busy; |
<> | 154:37f96f9d4de2 | 1425 | } |
<> | 154:37f96f9d4de2 | 1426 | else |
<> | 154:37f96f9d4de2 | 1427 | { |
<> | 154:37f96f9d4de2 | 1428 | /* Disable LPI2C IRQ sources while we configure stuff. */ |
<> | 154:37f96f9d4de2 | 1429 | I2C_DisableInterrupts(base, kIrqFlags); |
<> | 154:37f96f9d4de2 | 1430 | |
<> | 154:37f96f9d4de2 | 1431 | /* Clear transfer in handle. */ |
<> | 154:37f96f9d4de2 | 1432 | memset(&handle->transfer, 0, sizeof(handle->transfer)); |
<> | 154:37f96f9d4de2 | 1433 | |
<> | 154:37f96f9d4de2 | 1434 | /* Record that we're busy. */ |
<> | 154:37f96f9d4de2 | 1435 | handle->isBusy = true; |
<> | 154:37f96f9d4de2 | 1436 | |
<> | 154:37f96f9d4de2 | 1437 | /* Set up event mask. tx and rx are always enabled. */ |
<> | 154:37f96f9d4de2 | 1438 | handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | kI2C_SlaveGenaralcallEvent; |
<> | 154:37f96f9d4de2 | 1439 | |
<> | 154:37f96f9d4de2 | 1440 | /* Clear all flags. */ |
<> | 154:37f96f9d4de2 | 1441 | I2C_SlaveClearStatusFlags(base, kClearFlags); |
<> | 154:37f96f9d4de2 | 1442 | |
<> | 154:37f96f9d4de2 | 1443 | /* Enable I2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */ |
<> | 154:37f96f9d4de2 | 1444 | I2C_EnableInterrupts(base, kIrqFlags); |
<> | 154:37f96f9d4de2 | 1445 | } |
<> | 154:37f96f9d4de2 | 1446 | |
<> | 154:37f96f9d4de2 | 1447 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1448 | } |
<> | 154:37f96f9d4de2 | 1449 | |
<> | 154:37f96f9d4de2 | 1450 | void I2C_SlaveTransferAbort(I2C_Type *base, i2c_slave_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1451 | { |
<> | 154:37f96f9d4de2 | 1452 | assert(handle); |
<> | 154:37f96f9d4de2 | 1453 | |
<> | 154:37f96f9d4de2 | 1454 | if (handle->isBusy) |
<> | 154:37f96f9d4de2 | 1455 | { |
<> | 154:37f96f9d4de2 | 1456 | /* Disable interrupts. */ |
<> | 154:37f96f9d4de2 | 1457 | I2C_DisableInterrupts(base, kIrqFlags); |
<> | 154:37f96f9d4de2 | 1458 | |
<> | 154:37f96f9d4de2 | 1459 | /* Reset transfer info. */ |
<> | 154:37f96f9d4de2 | 1460 | memset(&handle->transfer, 0, sizeof(handle->transfer)); |
<> | 154:37f96f9d4de2 | 1461 | |
<> | 154:37f96f9d4de2 | 1462 | /* Reset the state to idle. */ |
<> | 154:37f96f9d4de2 | 1463 | handle->isBusy = false; |
<> | 154:37f96f9d4de2 | 1464 | } |
<> | 154:37f96f9d4de2 | 1465 | } |
<> | 154:37f96f9d4de2 | 1466 | |
<> | 154:37f96f9d4de2 | 1467 | status_t I2C_SlaveTransferGetCount(I2C_Type *base, i2c_slave_handle_t *handle, size_t *count) |
<> | 154:37f96f9d4de2 | 1468 | { |
<> | 154:37f96f9d4de2 | 1469 | assert(handle); |
<> | 154:37f96f9d4de2 | 1470 | |
<> | 154:37f96f9d4de2 | 1471 | if (!count) |
<> | 154:37f96f9d4de2 | 1472 | { |
<> | 154:37f96f9d4de2 | 1473 | return kStatus_InvalidArgument; |
<> | 154:37f96f9d4de2 | 1474 | } |
<> | 154:37f96f9d4de2 | 1475 | |
<> | 154:37f96f9d4de2 | 1476 | /* Catch when there is not an active transfer. */ |
<> | 154:37f96f9d4de2 | 1477 | if (!handle->isBusy) |
<> | 154:37f96f9d4de2 | 1478 | { |
<> | 154:37f96f9d4de2 | 1479 | *count = 0; |
<> | 154:37f96f9d4de2 | 1480 | return kStatus_NoTransferInProgress; |
<> | 154:37f96f9d4de2 | 1481 | } |
<> | 154:37f96f9d4de2 | 1482 | |
<> | 154:37f96f9d4de2 | 1483 | /* For an active transfer, just return the count from the handle. */ |
<> | 154:37f96f9d4de2 | 1484 | *count = handle->transfer.transferredCount; |
<> | 154:37f96f9d4de2 | 1485 | |
<> | 154:37f96f9d4de2 | 1486 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1487 | } |
<> | 154:37f96f9d4de2 | 1488 | |
<> | 154:37f96f9d4de2 | 1489 | void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) |
<> | 154:37f96f9d4de2 | 1490 | { |
<> | 154:37f96f9d4de2 | 1491 | assert(i2cHandle); |
<> | 154:37f96f9d4de2 | 1492 | |
<> | 154:37f96f9d4de2 | 1493 | uint16_t status; |
<> | 154:37f96f9d4de2 | 1494 | bool doTransmit = false; |
<> | 154:37f96f9d4de2 | 1495 | i2c_slave_handle_t *handle = (i2c_slave_handle_t *)i2cHandle; |
<> | 154:37f96f9d4de2 | 1496 | i2c_slave_transfer_t *xfer; |
<> | 154:37f96f9d4de2 | 1497 | volatile uint8_t dummy = 0; |
<> | 154:37f96f9d4de2 | 1498 | |
<> | 154:37f96f9d4de2 | 1499 | /* Add this to avoid build warning. */ |
<> | 154:37f96f9d4de2 | 1500 | dummy++; |
<> | 154:37f96f9d4de2 | 1501 | |
<> | 154:37f96f9d4de2 | 1502 | status = I2C_SlaveGetStatusFlags(base); |
<> | 154:37f96f9d4de2 | 1503 | xfer = &(handle->transfer); |
<> | 154:37f96f9d4de2 | 1504 | |
<> | 154:37f96f9d4de2 | 1505 | #ifdef I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 1506 | /* Check stop flag. */ |
<> | 154:37f96f9d4de2 | 1507 | if (status & kI2C_StopDetectFlag) |
<> | 154:37f96f9d4de2 | 1508 | { |
<> | 154:37f96f9d4de2 | 1509 | I2C_MasterClearStatusFlags(base, kI2C_StopDetectFlag); |
<> | 154:37f96f9d4de2 | 1510 | |
<> | 154:37f96f9d4de2 | 1511 | /* Clear the interrupt flag. */ |
<> | 154:37f96f9d4de2 | 1512 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1513 | |
<> | 154:37f96f9d4de2 | 1514 | /* Call slave callback if this is the STOP of the transfer. */ |
<> | 154:37f96f9d4de2 | 1515 | if (handle->isBusy) |
<> | 154:37f96f9d4de2 | 1516 | { |
<> | 154:37f96f9d4de2 | 1517 | xfer->event = kI2C_SlaveCompletionEvent; |
<> | 154:37f96f9d4de2 | 1518 | xfer->completionStatus = kStatus_Success; |
<> | 154:37f96f9d4de2 | 1519 | handle->isBusy = false; |
<> | 154:37f96f9d4de2 | 1520 | |
<> | 154:37f96f9d4de2 | 1521 | if ((handle->eventMask & xfer->event) && (handle->callback)) |
<> | 154:37f96f9d4de2 | 1522 | { |
<> | 154:37f96f9d4de2 | 1523 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1524 | } |
<> | 154:37f96f9d4de2 | 1525 | } |
<> | 154:37f96f9d4de2 | 1526 | |
<> | 154:37f96f9d4de2 | 1527 | return; |
<> | 154:37f96f9d4de2 | 1528 | } |
<> | 154:37f96f9d4de2 | 1529 | #endif /* I2C_HAS_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 1530 | |
<> | 154:37f96f9d4de2 | 1531 | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT |
<> | 154:37f96f9d4de2 | 1532 | /* Check start flag. */ |
<> | 154:37f96f9d4de2 | 1533 | if (status & kI2C_StartDetectFlag) |
<> | 154:37f96f9d4de2 | 1534 | { |
<> | 154:37f96f9d4de2 | 1535 | I2C_MasterClearStatusFlags(base, kI2C_StartDetectFlag); |
<> | 154:37f96f9d4de2 | 1536 | |
<> | 154:37f96f9d4de2 | 1537 | /* Clear the interrupt flag. */ |
<> | 154:37f96f9d4de2 | 1538 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1539 | |
<> | 154:37f96f9d4de2 | 1540 | xfer->event = kI2C_SlaveStartEvent; |
<> | 154:37f96f9d4de2 | 1541 | |
<> | 154:37f96f9d4de2 | 1542 | if ((handle->eventMask & xfer->event) && (handle->callback)) |
<> | 154:37f96f9d4de2 | 1543 | { |
<> | 154:37f96f9d4de2 | 1544 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1545 | } |
<> | 154:37f96f9d4de2 | 1546 | |
<> | 154:37f96f9d4de2 | 1547 | if (!(status & kI2C_AddressMatchFlag)) |
<> | 154:37f96f9d4de2 | 1548 | { |
<> | 154:37f96f9d4de2 | 1549 | return; |
<> | 154:37f96f9d4de2 | 1550 | } |
<> | 154:37f96f9d4de2 | 1551 | } |
<> | 154:37f96f9d4de2 | 1552 | #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 1553 | |
<> | 154:37f96f9d4de2 | 1554 | /* Clear the interrupt flag. */ |
<> | 154:37f96f9d4de2 | 1555 | base->S = kI2C_IntPendingFlag; |
<> | 154:37f96f9d4de2 | 1556 | |
<> | 154:37f96f9d4de2 | 1557 | /* Check NAK */ |
<> | 154:37f96f9d4de2 | 1558 | if (status & kI2C_ReceiveNakFlag) |
<> | 154:37f96f9d4de2 | 1559 | { |
<> | 154:37f96f9d4de2 | 1560 | /* Set receive mode. */ |
<> | 154:37f96f9d4de2 | 1561 | base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 1562 | |
<> | 154:37f96f9d4de2 | 1563 | /* Read dummy. */ |
<> | 154:37f96f9d4de2 | 1564 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 1565 | |
<> | 154:37f96f9d4de2 | 1566 | if (handle->transfer.dataSize != 0) |
<> | 154:37f96f9d4de2 | 1567 | { |
<> | 154:37f96f9d4de2 | 1568 | xfer->event = kI2C_SlaveCompletionEvent; |
<> | 154:37f96f9d4de2 | 1569 | xfer->completionStatus = kStatus_I2C_Nak; |
<> | 154:37f96f9d4de2 | 1570 | handle->isBusy = false; |
<> | 154:37f96f9d4de2 | 1571 | |
<> | 154:37f96f9d4de2 | 1572 | if ((handle->eventMask & xfer->event) && (handle->callback)) |
<> | 154:37f96f9d4de2 | 1573 | { |
<> | 154:37f96f9d4de2 | 1574 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1575 | } |
<> | 154:37f96f9d4de2 | 1576 | } |
<> | 154:37f96f9d4de2 | 1577 | else |
<> | 154:37f96f9d4de2 | 1578 | { |
<> | 154:37f96f9d4de2 | 1579 | #ifndef I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 1580 | xfer->event = kI2C_SlaveCompletionEvent; |
<> | 154:37f96f9d4de2 | 1581 | xfer->completionStatus = kStatus_Success; |
<> | 154:37f96f9d4de2 | 1582 | handle->isBusy = false; |
<> | 154:37f96f9d4de2 | 1583 | |
<> | 154:37f96f9d4de2 | 1584 | if ((handle->eventMask & xfer->event) && (handle->callback)) |
<> | 154:37f96f9d4de2 | 1585 | { |
<> | 154:37f96f9d4de2 | 1586 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1587 | } |
<> | 154:37f96f9d4de2 | 1588 | #endif /* !FSL_FEATURE_I2C_HAS_START_STOP_DETECT or !FSL_FEATURE_I2C_HAS_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 1589 | } |
<> | 154:37f96f9d4de2 | 1590 | } |
<> | 154:37f96f9d4de2 | 1591 | /* Check address match. */ |
<> | 154:37f96f9d4de2 | 1592 | else if (status & kI2C_AddressMatchFlag) |
<> | 154:37f96f9d4de2 | 1593 | { |
<> | 154:37f96f9d4de2 | 1594 | handle->isBusy = true; |
<> | 154:37f96f9d4de2 | 1595 | xfer->event = kI2C_SlaveAddressMatchEvent; |
<> | 154:37f96f9d4de2 | 1596 | |
<> | 154:37f96f9d4de2 | 1597 | /* Slave transmit, master reading from slave. */ |
<> | 154:37f96f9d4de2 | 1598 | if (status & kI2C_TransferDirectionFlag) |
<> | 154:37f96f9d4de2 | 1599 | { |
<> | 154:37f96f9d4de2 | 1600 | /* Change direction to send data. */ |
<> | 154:37f96f9d4de2 | 1601 | base->C1 |= I2C_C1_TX_MASK; |
<> | 154:37f96f9d4de2 | 1602 | |
<> | 154:37f96f9d4de2 | 1603 | doTransmit = true; |
<> | 154:37f96f9d4de2 | 1604 | } |
<> | 154:37f96f9d4de2 | 1605 | else |
<> | 154:37f96f9d4de2 | 1606 | { |
<> | 154:37f96f9d4de2 | 1607 | /* Slave receive, master writing to slave. */ |
<> | 154:37f96f9d4de2 | 1608 | base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 1609 | |
<> | 154:37f96f9d4de2 | 1610 | /* Read dummy to release the bus. */ |
<> | 154:37f96f9d4de2 | 1611 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 1612 | |
<> | 154:37f96f9d4de2 | 1613 | if (dummy == 0) |
<> | 154:37f96f9d4de2 | 1614 | { |
<> | 154:37f96f9d4de2 | 1615 | xfer->event = kI2C_SlaveGenaralcallEvent; |
<> | 154:37f96f9d4de2 | 1616 | } |
<> | 154:37f96f9d4de2 | 1617 | } |
<> | 154:37f96f9d4de2 | 1618 | |
<> | 154:37f96f9d4de2 | 1619 | if ((handle->eventMask & xfer->event) && (handle->callback)) |
<> | 154:37f96f9d4de2 | 1620 | { |
<> | 154:37f96f9d4de2 | 1621 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1622 | } |
<> | 154:37f96f9d4de2 | 1623 | } |
<> | 154:37f96f9d4de2 | 1624 | /* Check transfer complete flag. */ |
<> | 154:37f96f9d4de2 | 1625 | else if (status & kI2C_TransferCompleteFlag) |
<> | 154:37f96f9d4de2 | 1626 | { |
<> | 154:37f96f9d4de2 | 1627 | /* Slave transmit, master reading from slave. */ |
<> | 154:37f96f9d4de2 | 1628 | if (status & kI2C_TransferDirectionFlag) |
<> | 154:37f96f9d4de2 | 1629 | { |
<> | 154:37f96f9d4de2 | 1630 | doTransmit = true; |
<> | 154:37f96f9d4de2 | 1631 | } |
<> | 154:37f96f9d4de2 | 1632 | else |
<> | 154:37f96f9d4de2 | 1633 | { |
<> | 154:37f96f9d4de2 | 1634 | /* If we're out of data, invoke callback to get more. */ |
<> | 154:37f96f9d4de2 | 1635 | if ((!xfer->data) || (!xfer->dataSize)) |
<> | 154:37f96f9d4de2 | 1636 | { |
<> | 154:37f96f9d4de2 | 1637 | xfer->event = kI2C_SlaveReceiveEvent; |
<> | 154:37f96f9d4de2 | 1638 | |
<> | 154:37f96f9d4de2 | 1639 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1640 | { |
<> | 154:37f96f9d4de2 | 1641 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1642 | } |
<> | 154:37f96f9d4de2 | 1643 | |
<> | 154:37f96f9d4de2 | 1644 | /* Clear the transferred count now that we have a new buffer. */ |
<> | 154:37f96f9d4de2 | 1645 | xfer->transferredCount = 0; |
<> | 154:37f96f9d4de2 | 1646 | } |
<> | 154:37f96f9d4de2 | 1647 | |
<> | 154:37f96f9d4de2 | 1648 | /* Slave receive, master writing to slave. */ |
<> | 154:37f96f9d4de2 | 1649 | uint8_t data = base->D; |
<> | 154:37f96f9d4de2 | 1650 | |
<> | 154:37f96f9d4de2 | 1651 | if (handle->transfer.dataSize) |
<> | 154:37f96f9d4de2 | 1652 | { |
<> | 154:37f96f9d4de2 | 1653 | /* Receive data. */ |
<> | 154:37f96f9d4de2 | 1654 | *handle->transfer.data++ = data; |
<> | 154:37f96f9d4de2 | 1655 | handle->transfer.dataSize--; |
<> | 154:37f96f9d4de2 | 1656 | xfer->transferredCount++; |
<> | 154:37f96f9d4de2 | 1657 | if (!handle->transfer.dataSize) |
<> | 154:37f96f9d4de2 | 1658 | { |
<> | 154:37f96f9d4de2 | 1659 | #ifndef I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 1660 | xfer->event = kI2C_SlaveCompletionEvent; |
<> | 154:37f96f9d4de2 | 1661 | xfer->completionStatus = kStatus_Success; |
<> | 154:37f96f9d4de2 | 1662 | handle->isBusy = false; |
<> | 154:37f96f9d4de2 | 1663 | |
<> | 154:37f96f9d4de2 | 1664 | /* Proceed receive complete event. */ |
<> | 154:37f96f9d4de2 | 1665 | if ((handle->eventMask & xfer->event) && (handle->callback)) |
<> | 154:37f96f9d4de2 | 1666 | { |
<> | 154:37f96f9d4de2 | 1667 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1668 | } |
<> | 154:37f96f9d4de2 | 1669 | #endif /* !FSL_FEATURE_I2C_HAS_START_STOP_DETECT or !FSL_FEATURE_I2C_HAS_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 1670 | } |
<> | 154:37f96f9d4de2 | 1671 | } |
<> | 154:37f96f9d4de2 | 1672 | } |
<> | 154:37f96f9d4de2 | 1673 | } |
<> | 154:37f96f9d4de2 | 1674 | else |
<> | 154:37f96f9d4de2 | 1675 | { |
<> | 154:37f96f9d4de2 | 1676 | /* Read dummy to release bus. */ |
<> | 154:37f96f9d4de2 | 1677 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 1678 | } |
<> | 154:37f96f9d4de2 | 1679 | |
<> | 154:37f96f9d4de2 | 1680 | /* Send data if there is the need. */ |
<> | 154:37f96f9d4de2 | 1681 | if (doTransmit) |
<> | 154:37f96f9d4de2 | 1682 | { |
<> | 154:37f96f9d4de2 | 1683 | /* If we're out of data, invoke callback to get more. */ |
<> | 154:37f96f9d4de2 | 1684 | if ((!xfer->data) || (!xfer->dataSize)) |
<> | 154:37f96f9d4de2 | 1685 | { |
<> | 154:37f96f9d4de2 | 1686 | xfer->event = kI2C_SlaveTransmitEvent; |
<> | 154:37f96f9d4de2 | 1687 | |
<> | 154:37f96f9d4de2 | 1688 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1689 | { |
<> | 154:37f96f9d4de2 | 1690 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1691 | } |
<> | 154:37f96f9d4de2 | 1692 | |
<> | 154:37f96f9d4de2 | 1693 | /* Clear the transferred count now that we have a new buffer. */ |
<> | 154:37f96f9d4de2 | 1694 | xfer->transferredCount = 0; |
<> | 154:37f96f9d4de2 | 1695 | } |
<> | 154:37f96f9d4de2 | 1696 | |
<> | 154:37f96f9d4de2 | 1697 | if (handle->transfer.dataSize) |
<> | 154:37f96f9d4de2 | 1698 | { |
<> | 154:37f96f9d4de2 | 1699 | /* Send data. */ |
<> | 154:37f96f9d4de2 | 1700 | base->D = *handle->transfer.data++; |
<> | 154:37f96f9d4de2 | 1701 | handle->transfer.dataSize--; |
<> | 154:37f96f9d4de2 | 1702 | xfer->transferredCount++; |
<> | 154:37f96f9d4de2 | 1703 | } |
<> | 154:37f96f9d4de2 | 1704 | else |
<> | 154:37f96f9d4de2 | 1705 | { |
<> | 154:37f96f9d4de2 | 1706 | /* Switch to receive mode. */ |
<> | 154:37f96f9d4de2 | 1707 | base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); |
<> | 154:37f96f9d4de2 | 1708 | |
<> | 154:37f96f9d4de2 | 1709 | /* Read dummy to release bus. */ |
<> | 154:37f96f9d4de2 | 1710 | dummy = base->D; |
<> | 154:37f96f9d4de2 | 1711 | |
<> | 154:37f96f9d4de2 | 1712 | #ifndef I2C_HAS_STOP_DETECT |
<> | 154:37f96f9d4de2 | 1713 | xfer->event = kI2C_SlaveCompletionEvent; |
<> | 154:37f96f9d4de2 | 1714 | xfer->completionStatus = kStatus_Success; |
<> | 154:37f96f9d4de2 | 1715 | handle->isBusy = false; |
<> | 154:37f96f9d4de2 | 1716 | |
<> | 154:37f96f9d4de2 | 1717 | /* Proceed txdone event. */ |
<> | 154:37f96f9d4de2 | 1718 | if ((handle->eventMask & xfer->event) && (handle->callback)) |
<> | 154:37f96f9d4de2 | 1719 | { |
<> | 154:37f96f9d4de2 | 1720 | handle->callback(base, xfer, handle->userData); |
<> | 154:37f96f9d4de2 | 1721 | } |
<> | 154:37f96f9d4de2 | 1722 | #endif /* !FSL_FEATURE_I2C_HAS_START_STOP_DETECT or !FSL_FEATURE_I2C_HAS_STOP_DETECT */ |
<> | 154:37f96f9d4de2 | 1723 | } |
<> | 154:37f96f9d4de2 | 1724 | } |
<> | 154:37f96f9d4de2 | 1725 | } |
<> | 154:37f96f9d4de2 | 1726 | |
<> | 154:37f96f9d4de2 | 1727 | void I2C0_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1728 | { |
<> | 154:37f96f9d4de2 | 1729 | I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]); |
<> | 154:37f96f9d4de2 | 1730 | } |
<> | 154:37f96f9d4de2 | 1731 | |
<> | 154:37f96f9d4de2 | 1732 | #if (FSL_FEATURE_SOC_I2C_COUNT > 1) |
<> | 154:37f96f9d4de2 | 1733 | void I2C1_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1734 | { |
<> | 154:37f96f9d4de2 | 1735 | I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]); |
<> | 154:37f96f9d4de2 | 1736 | } |
<> | 154:37f96f9d4de2 | 1737 | #endif /* I2C COUNT > 1 */ |
<> | 154:37f96f9d4de2 | 1738 | |
<> | 154:37f96f9d4de2 | 1739 | #if (FSL_FEATURE_SOC_I2C_COUNT > 2) |
<> | 154:37f96f9d4de2 | 1740 | void I2C2_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1741 | { |
<> | 154:37f96f9d4de2 | 1742 | I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]); |
<> | 154:37f96f9d4de2 | 1743 | } |
<> | 154:37f96f9d4de2 | 1744 | #endif /* I2C COUNT > 2 */ |
<> | 154:37f96f9d4de2 | 1745 | #if (FSL_FEATURE_SOC_I2C_COUNT > 3) |
<> | 154:37f96f9d4de2 | 1746 | void I2C3_DriverIRQHandler(void) |
<> | 154:37f96f9d4de2 | 1747 | { |
<> | 154:37f96f9d4de2 | 1748 | I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]); |
<> | 154:37f96f9d4de2 | 1749 | } |
<> | 154:37f96f9d4de2 | 1750 | #endif /* I2C COUNT > 3 */ |