added prescaler for 16 bit pwm in LPC1347 target
Fork of mbed-dev by
targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL43Z/drivers/fsl_i2c_dma.c@147:ba84b7dc41a7, 2016-09-10 (annotated)
- Committer:
- JojoS
- Date:
- Sat Sep 10 15:32:04 2016 +0000
- Revision:
- 147:ba84b7dc41a7
- Parent:
- 144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 144:ef7eb2e8f9f7 | 1 | /* |
<> | 144:ef7eb2e8f9f7 | 2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. |
<> | 144:ef7eb2e8f9f7 | 3 | * All rights reserved. |
<> | 144:ef7eb2e8f9f7 | 4 | * |
<> | 144:ef7eb2e8f9f7 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
<> | 144:ef7eb2e8f9f7 | 6 | * are permitted provided that the following conditions are met: |
<> | 144:ef7eb2e8f9f7 | 7 | * |
<> | 144:ef7eb2e8f9f7 | 8 | * o Redistributions of source code must retain the above copyright notice, this list |
<> | 144:ef7eb2e8f9f7 | 9 | * of conditions and the following disclaimer. |
<> | 144:ef7eb2e8f9f7 | 10 | * |
<> | 144:ef7eb2e8f9f7 | 11 | * o Redistributions in binary form must reproduce the above copyright notice, this |
<> | 144:ef7eb2e8f9f7 | 12 | * list of conditions and the following disclaimer in the documentation and/or |
<> | 144:ef7eb2e8f9f7 | 13 | * other materials provided with the distribution. |
<> | 144:ef7eb2e8f9f7 | 14 | * |
<> | 144:ef7eb2e8f9f7 | 15 | * o Neither the name of Freescale Semiconductor, Inc. nor the names of its |
<> | 144:ef7eb2e8f9f7 | 16 | * contributors may be used to endorse or promote products derived from this |
<> | 144:ef7eb2e8f9f7 | 17 | * software without specific prior written permission. |
<> | 144:ef7eb2e8f9f7 | 18 | * |
<> | 144:ef7eb2e8f9f7 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
<> | 144:ef7eb2e8f9f7 | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
<> | 144:ef7eb2e8f9f7 | 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
<> | 144:ef7eb2e8f9f7 | 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
<> | 144:ef7eb2e8f9f7 | 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
<> | 144:ef7eb2e8f9f7 | 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
<> | 144:ef7eb2e8f9f7 | 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
<> | 144:ef7eb2e8f9f7 | 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
<> | 144:ef7eb2e8f9f7 | 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
<> | 144:ef7eb2e8f9f7 | 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
<> | 144:ef7eb2e8f9f7 | 29 | */ |
<> | 144:ef7eb2e8f9f7 | 30 | |
<> | 144:ef7eb2e8f9f7 | 31 | #include "fsl_i2c_dma.h" |
<> | 144:ef7eb2e8f9f7 | 32 | |
<> | 144:ef7eb2e8f9f7 | 33 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 34 | * Definitions |
<> | 144:ef7eb2e8f9f7 | 35 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 36 | |
<> | 144:ef7eb2e8f9f7 | 37 | /*<! @brief Structure definition for i2c_master_dma_handle_t. The structure is private. */ |
<> | 144:ef7eb2e8f9f7 | 38 | typedef struct _i2c_master_dma_private_handle |
<> | 144:ef7eb2e8f9f7 | 39 | { |
<> | 144:ef7eb2e8f9f7 | 40 | I2C_Type *base; |
<> | 144:ef7eb2e8f9f7 | 41 | i2c_master_dma_handle_t *handle; |
<> | 144:ef7eb2e8f9f7 | 42 | } i2c_master_dma_private_handle_t; |
<> | 144:ef7eb2e8f9f7 | 43 | |
<> | 144:ef7eb2e8f9f7 | 44 | /*! @brief i2c master DMA transfer state. */ |
<> | 144:ef7eb2e8f9f7 | 45 | enum _i2c_master_dma_transfer_states |
<> | 144:ef7eb2e8f9f7 | 46 | { |
<> | 144:ef7eb2e8f9f7 | 47 | kIdleState = 0x0U, /*!< I2C bus idle. */ |
<> | 144:ef7eb2e8f9f7 | 48 | kTransferDataState = 0x1U, /*!< 7-bit address check state. */ |
<> | 144:ef7eb2e8f9f7 | 49 | }; |
<> | 144:ef7eb2e8f9f7 | 50 | |
<> | 144:ef7eb2e8f9f7 | 51 | /*! @brief Common sets of flags used by the driver. */ |
<> | 144:ef7eb2e8f9f7 | 52 | enum _i2c_flag_constants |
<> | 144:ef7eb2e8f9f7 | 53 | { |
<> | 144:ef7eb2e8f9f7 | 54 | /*! All flags which are cleared by the driver upon starting a transfer. */ |
<> | 144:ef7eb2e8f9f7 | 55 | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT |
<> | 144:ef7eb2e8f9f7 | 56 | kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag | kI2C_StartDetectFlag | kI2C_StopDetectFlag, |
<> | 144:ef7eb2e8f9f7 | 57 | #elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT |
<> | 144:ef7eb2e8f9f7 | 58 | kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag | kI2C_StopDetectFlag, |
<> | 144:ef7eb2e8f9f7 | 59 | #else |
<> | 144:ef7eb2e8f9f7 | 60 | kClearFlags = kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag, |
<> | 144:ef7eb2e8f9f7 | 61 | #endif |
<> | 144:ef7eb2e8f9f7 | 62 | }; |
<> | 144:ef7eb2e8f9f7 | 63 | |
<> | 144:ef7eb2e8f9f7 | 64 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 65 | * Prototypes |
<> | 144:ef7eb2e8f9f7 | 66 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 67 | |
<> | 144:ef7eb2e8f9f7 | 68 | /*! |
<> | 144:ef7eb2e8f9f7 | 69 | * @brief DMA callback for I2C master DMA driver. |
<> | 144:ef7eb2e8f9f7 | 70 | * |
<> | 144:ef7eb2e8f9f7 | 71 | * @param handle DMA handler for I2C master DMA driver |
<> | 144:ef7eb2e8f9f7 | 72 | * @param userData user param passed to the callback function |
<> | 144:ef7eb2e8f9f7 | 73 | */ |
<> | 144:ef7eb2e8f9f7 | 74 | static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData); |
<> | 144:ef7eb2e8f9f7 | 75 | |
<> | 144:ef7eb2e8f9f7 | 76 | /*! |
<> | 144:ef7eb2e8f9f7 | 77 | * @brief Check and clear status operation. |
<> | 144:ef7eb2e8f9f7 | 78 | * |
<> | 144:ef7eb2e8f9f7 | 79 | * @param base I2C peripheral base address. |
<> | 144:ef7eb2e8f9f7 | 80 | * @param status current i2c hardware status |
<> | 144:ef7eb2e8f9f7 | 81 | * @retval kStatus_Success No error found. |
<> | 144:ef7eb2e8f9f7 | 82 | * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. |
<> | 144:ef7eb2e8f9f7 | 83 | * @retval kStatus_I2C_Nak Received Nak error. |
<> | 144:ef7eb2e8f9f7 | 84 | */ |
<> | 144:ef7eb2e8f9f7 | 85 | static status_t I2C_CheckAndClearError(I2C_Type *base, uint32_t status); |
<> | 144:ef7eb2e8f9f7 | 86 | |
<> | 144:ef7eb2e8f9f7 | 87 | /*! |
<> | 144:ef7eb2e8f9f7 | 88 | * @brief DMA config for I2C master driver. |
<> | 144:ef7eb2e8f9f7 | 89 | * |
<> | 144:ef7eb2e8f9f7 | 90 | * @param base I2C peripheral base address. |
<> | 144:ef7eb2e8f9f7 | 91 | * @param handle pointer to i2c_master_dma_handle_t structure which stores the transfer state. |
<> | 144:ef7eb2e8f9f7 | 92 | */ |
<> | 144:ef7eb2e8f9f7 | 93 | static void I2C_MasterTransferDMAConfig(I2C_Type *base, i2c_master_dma_handle_t *handle); |
<> | 144:ef7eb2e8f9f7 | 94 | |
<> | 144:ef7eb2e8f9f7 | 95 | /*! |
<> | 144:ef7eb2e8f9f7 | 96 | * @brief Set up master transfer, send slave address and sub address(if any), wait until the |
<> | 144:ef7eb2e8f9f7 | 97 | * wait until address sent status return. |
<> | 144:ef7eb2e8f9f7 | 98 | * |
<> | 144:ef7eb2e8f9f7 | 99 | * @param base I2C peripheral base address. |
<> | 144:ef7eb2e8f9f7 | 100 | * @param handle pointer to i2c_master_dma_handle_t structure which stores the transfer state. |
<> | 144:ef7eb2e8f9f7 | 101 | * @param xfer pointer to i2c_master_transfer_t structure. |
<> | 144:ef7eb2e8f9f7 | 102 | */ |
<> | 144:ef7eb2e8f9f7 | 103 | static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base, |
<> | 144:ef7eb2e8f9f7 | 104 | i2c_master_dma_handle_t *handle, |
<> | 144:ef7eb2e8f9f7 | 105 | i2c_master_transfer_t *xfer); |
<> | 144:ef7eb2e8f9f7 | 106 | |
<> | 144:ef7eb2e8f9f7 | 107 | /*! |
<> | 144:ef7eb2e8f9f7 | 108 | * @brief Get the I2C instance from peripheral base address. |
<> | 144:ef7eb2e8f9f7 | 109 | * |
<> | 144:ef7eb2e8f9f7 | 110 | * @param base I2C peripheral base address. |
<> | 144:ef7eb2e8f9f7 | 111 | * @return I2C instance. |
<> | 144:ef7eb2e8f9f7 | 112 | */ |
<> | 144:ef7eb2e8f9f7 | 113 | extern uint32_t I2C_GetInstance(I2C_Type *base); |
<> | 144:ef7eb2e8f9f7 | 114 | |
<> | 144:ef7eb2e8f9f7 | 115 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 116 | * Variables |
<> | 144:ef7eb2e8f9f7 | 117 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 118 | |
<> | 144:ef7eb2e8f9f7 | 119 | /*<! Private handle only used for internally. */ |
<> | 144:ef7eb2e8f9f7 | 120 | static i2c_master_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_I2C_COUNT]; |
<> | 144:ef7eb2e8f9f7 | 121 | |
<> | 144:ef7eb2e8f9f7 | 122 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 123 | * Codes |
<> | 144:ef7eb2e8f9f7 | 124 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 125 | |
<> | 144:ef7eb2e8f9f7 | 126 | static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData) |
<> | 144:ef7eb2e8f9f7 | 127 | { |
<> | 144:ef7eb2e8f9f7 | 128 | i2c_master_dma_private_handle_t *i2cPrivateHandle = (i2c_master_dma_private_handle_t *)userData; |
<> | 144:ef7eb2e8f9f7 | 129 | status_t result = kStatus_Success; |
<> | 144:ef7eb2e8f9f7 | 130 | |
<> | 144:ef7eb2e8f9f7 | 131 | /* Disable DMA. */ |
<> | 144:ef7eb2e8f9f7 | 132 | I2C_EnableDMA(i2cPrivateHandle->base, false); |
<> | 144:ef7eb2e8f9f7 | 133 | |
<> | 144:ef7eb2e8f9f7 | 134 | /* Send stop if kI2C_TransferNoStop flag is not asserted. */ |
<> | 144:ef7eb2e8f9f7 | 135 | if (!(i2cPrivateHandle->handle->transfer.flags & kI2C_TransferNoStopFlag)) |
<> | 144:ef7eb2e8f9f7 | 136 | { |
<> | 144:ef7eb2e8f9f7 | 137 | if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read) |
<> | 144:ef7eb2e8f9f7 | 138 | { |
<> | 144:ef7eb2e8f9f7 | 139 | /* Change to send NAK at the last byte. */ |
<> | 144:ef7eb2e8f9f7 | 140 | i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK; |
<> | 144:ef7eb2e8f9f7 | 141 | |
<> | 144:ef7eb2e8f9f7 | 142 | /* Wait the last data to be received. */ |
<> | 144:ef7eb2e8f9f7 | 143 | while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag)) |
<> | 144:ef7eb2e8f9f7 | 144 | { |
<> | 144:ef7eb2e8f9f7 | 145 | } |
<> | 144:ef7eb2e8f9f7 | 146 | |
<> | 144:ef7eb2e8f9f7 | 147 | /* Send stop signal. */ |
<> | 144:ef7eb2e8f9f7 | 148 | result = I2C_MasterStop(i2cPrivateHandle->base); |
<> | 144:ef7eb2e8f9f7 | 149 | |
<> | 144:ef7eb2e8f9f7 | 150 | /* Read the last data byte. */ |
<> | 144:ef7eb2e8f9f7 | 151 | *(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) = |
<> | 144:ef7eb2e8f9f7 | 152 | i2cPrivateHandle->base->D; |
<> | 144:ef7eb2e8f9f7 | 153 | } |
<> | 144:ef7eb2e8f9f7 | 154 | else |
<> | 144:ef7eb2e8f9f7 | 155 | { |
<> | 144:ef7eb2e8f9f7 | 156 | /* Wait the last data to be sent. */ |
<> | 144:ef7eb2e8f9f7 | 157 | while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag)) |
<> | 144:ef7eb2e8f9f7 | 158 | { |
<> | 144:ef7eb2e8f9f7 | 159 | } |
<> | 144:ef7eb2e8f9f7 | 160 | |
<> | 144:ef7eb2e8f9f7 | 161 | /* Send stop signal. */ |
<> | 144:ef7eb2e8f9f7 | 162 | result = I2C_MasterStop(i2cPrivateHandle->base); |
<> | 144:ef7eb2e8f9f7 | 163 | } |
<> | 144:ef7eb2e8f9f7 | 164 | } |
<> | 144:ef7eb2e8f9f7 | 165 | |
<> | 144:ef7eb2e8f9f7 | 166 | i2cPrivateHandle->handle->state = kIdleState; |
<> | 144:ef7eb2e8f9f7 | 167 | |
<> | 144:ef7eb2e8f9f7 | 168 | if (i2cPrivateHandle->handle->completionCallback) |
<> | 144:ef7eb2e8f9f7 | 169 | { |
<> | 144:ef7eb2e8f9f7 | 170 | i2cPrivateHandle->handle->completionCallback(i2cPrivateHandle->base, i2cPrivateHandle->handle, result, |
<> | 144:ef7eb2e8f9f7 | 171 | i2cPrivateHandle->handle->userData); |
<> | 144:ef7eb2e8f9f7 | 172 | } |
<> | 144:ef7eb2e8f9f7 | 173 | } |
<> | 144:ef7eb2e8f9f7 | 174 | |
<> | 144:ef7eb2e8f9f7 | 175 | static status_t I2C_CheckAndClearError(I2C_Type *base, uint32_t status) |
<> | 144:ef7eb2e8f9f7 | 176 | { |
<> | 144:ef7eb2e8f9f7 | 177 | status_t result = kStatus_Success; |
<> | 144:ef7eb2e8f9f7 | 178 | |
<> | 144:ef7eb2e8f9f7 | 179 | /* Check arbitration lost. */ |
<> | 144:ef7eb2e8f9f7 | 180 | if (status & kI2C_ArbitrationLostFlag) |
<> | 144:ef7eb2e8f9f7 | 181 | { |
<> | 144:ef7eb2e8f9f7 | 182 | /* Clear arbitration lost flag. */ |
<> | 144:ef7eb2e8f9f7 | 183 | base->S = kI2C_ArbitrationLostFlag; |
<> | 144:ef7eb2e8f9f7 | 184 | result = kStatus_I2C_ArbitrationLost; |
<> | 144:ef7eb2e8f9f7 | 185 | } |
<> | 144:ef7eb2e8f9f7 | 186 | /* Check NAK */ |
<> | 144:ef7eb2e8f9f7 | 187 | else if (status & kI2C_ReceiveNakFlag) |
<> | 144:ef7eb2e8f9f7 | 188 | { |
<> | 144:ef7eb2e8f9f7 | 189 | result = kStatus_I2C_Nak; |
<> | 144:ef7eb2e8f9f7 | 190 | } |
<> | 144:ef7eb2e8f9f7 | 191 | else |
<> | 144:ef7eb2e8f9f7 | 192 | { |
<> | 144:ef7eb2e8f9f7 | 193 | } |
<> | 144:ef7eb2e8f9f7 | 194 | |
<> | 144:ef7eb2e8f9f7 | 195 | return result; |
<> | 144:ef7eb2e8f9f7 | 196 | } |
<> | 144:ef7eb2e8f9f7 | 197 | |
<> | 144:ef7eb2e8f9f7 | 198 | static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base, |
<> | 144:ef7eb2e8f9f7 | 199 | i2c_master_dma_handle_t *handle, |
<> | 144:ef7eb2e8f9f7 | 200 | i2c_master_transfer_t *xfer) |
<> | 144:ef7eb2e8f9f7 | 201 | { |
<> | 144:ef7eb2e8f9f7 | 202 | assert(handle); |
<> | 144:ef7eb2e8f9f7 | 203 | assert(xfer); |
<> | 144:ef7eb2e8f9f7 | 204 | |
<> | 144:ef7eb2e8f9f7 | 205 | /* Set up transfer first. */ |
<> | 144:ef7eb2e8f9f7 | 206 | i2c_direction_t direction = xfer->direction; |
<> | 144:ef7eb2e8f9f7 | 207 | status_t result = kStatus_Success; |
<> | 144:ef7eb2e8f9f7 | 208 | uint16_t timeout = UINT16_MAX; |
<> | 144:ef7eb2e8f9f7 | 209 | |
<> | 144:ef7eb2e8f9f7 | 210 | if (handle->state != kIdleState) |
<> | 144:ef7eb2e8f9f7 | 211 | { |
<> | 144:ef7eb2e8f9f7 | 212 | return kStatus_I2C_Busy; |
<> | 144:ef7eb2e8f9f7 | 213 | } |
<> | 144:ef7eb2e8f9f7 | 214 | else |
<> | 144:ef7eb2e8f9f7 | 215 | { |
<> | 144:ef7eb2e8f9f7 | 216 | /* Init the handle member. */ |
<> | 144:ef7eb2e8f9f7 | 217 | handle->transfer = *xfer; |
<> | 144:ef7eb2e8f9f7 | 218 | |
<> | 144:ef7eb2e8f9f7 | 219 | /* Save total transfer size. */ |
<> | 144:ef7eb2e8f9f7 | 220 | handle->transferSize = xfer->dataSize; |
<> | 144:ef7eb2e8f9f7 | 221 | |
<> | 144:ef7eb2e8f9f7 | 222 | handle->state = kTransferDataState; |
<> | 144:ef7eb2e8f9f7 | 223 | |
<> | 144:ef7eb2e8f9f7 | 224 | /* Wait until ready to complete. */ |
<> | 144:ef7eb2e8f9f7 | 225 | while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout)) |
<> | 144:ef7eb2e8f9f7 | 226 | { |
<> | 144:ef7eb2e8f9f7 | 227 | } |
<> | 144:ef7eb2e8f9f7 | 228 | |
<> | 144:ef7eb2e8f9f7 | 229 | /* Failed to start the transfer. */ |
<> | 144:ef7eb2e8f9f7 | 230 | if (timeout == 0) |
<> | 144:ef7eb2e8f9f7 | 231 | { |
<> | 144:ef7eb2e8f9f7 | 232 | return kStatus_I2C_Timeout; |
<> | 144:ef7eb2e8f9f7 | 233 | } |
<> | 144:ef7eb2e8f9f7 | 234 | |
<> | 144:ef7eb2e8f9f7 | 235 | /* Clear all status before transfer. */ |
<> | 144:ef7eb2e8f9f7 | 236 | I2C_MasterClearStatusFlags(base, kClearFlags); |
<> | 144:ef7eb2e8f9f7 | 237 | |
<> | 144:ef7eb2e8f9f7 | 238 | /* Change to send write address when it's a read operation with command. */ |
<> | 144:ef7eb2e8f9f7 | 239 | if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read)) |
<> | 144:ef7eb2e8f9f7 | 240 | { |
<> | 144:ef7eb2e8f9f7 | 241 | direction = kI2C_Write; |
<> | 144:ef7eb2e8f9f7 | 242 | } |
<> | 144:ef7eb2e8f9f7 | 243 | |
<> | 144:ef7eb2e8f9f7 | 244 | /* If repeated start is requested, send repeated start. */ |
<> | 144:ef7eb2e8f9f7 | 245 | if (handle->transfer.flags & kI2C_TransferRepeatedStartFlag) |
<> | 144:ef7eb2e8f9f7 | 246 | { |
<> | 144:ef7eb2e8f9f7 | 247 | result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, direction); |
<> | 144:ef7eb2e8f9f7 | 248 | } |
<> | 144:ef7eb2e8f9f7 | 249 | else /* For normal transfer, send start. */ |
<> | 144:ef7eb2e8f9f7 | 250 | { |
<> | 144:ef7eb2e8f9f7 | 251 | result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction); |
<> | 144:ef7eb2e8f9f7 | 252 | } |
<> | 144:ef7eb2e8f9f7 | 253 | |
<> | 144:ef7eb2e8f9f7 | 254 | /* Send subaddress. */ |
<> | 144:ef7eb2e8f9f7 | 255 | if (handle->transfer.subaddressSize) |
<> | 144:ef7eb2e8f9f7 | 256 | { |
<> | 144:ef7eb2e8f9f7 | 257 | do |
<> | 144:ef7eb2e8f9f7 | 258 | { |
<> | 144:ef7eb2e8f9f7 | 259 | /* Wait until data transfer complete. */ |
<> | 144:ef7eb2e8f9f7 | 260 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 144:ef7eb2e8f9f7 | 261 | { |
<> | 144:ef7eb2e8f9f7 | 262 | } |
<> | 144:ef7eb2e8f9f7 | 263 | |
<> | 144:ef7eb2e8f9f7 | 264 | /* Clear interrupt pending flag. */ |
<> | 144:ef7eb2e8f9f7 | 265 | base->S = kI2C_IntPendingFlag; |
<> | 144:ef7eb2e8f9f7 | 266 | |
<> | 144:ef7eb2e8f9f7 | 267 | handle->transfer.subaddressSize--; |
<> | 144:ef7eb2e8f9f7 | 268 | base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize)); |
<> | 144:ef7eb2e8f9f7 | 269 | |
<> | 144:ef7eb2e8f9f7 | 270 | /* Check if there's transfer error. */ |
<> | 144:ef7eb2e8f9f7 | 271 | result = I2C_CheckAndClearError(base, base->S); |
<> | 144:ef7eb2e8f9f7 | 272 | |
<> | 144:ef7eb2e8f9f7 | 273 | if (result) |
<> | 144:ef7eb2e8f9f7 | 274 | { |
<> | 144:ef7eb2e8f9f7 | 275 | return result; |
<> | 144:ef7eb2e8f9f7 | 276 | } |
<> | 144:ef7eb2e8f9f7 | 277 | |
<> | 144:ef7eb2e8f9f7 | 278 | } while ((handle->transfer.subaddressSize > 0) && (result == kStatus_Success)); |
<> | 144:ef7eb2e8f9f7 | 279 | |
<> | 144:ef7eb2e8f9f7 | 280 | if (handle->transfer.direction == kI2C_Read) |
<> | 144:ef7eb2e8f9f7 | 281 | { |
<> | 144:ef7eb2e8f9f7 | 282 | /* Wait until data transfer complete. */ |
<> | 144:ef7eb2e8f9f7 | 283 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 144:ef7eb2e8f9f7 | 284 | { |
<> | 144:ef7eb2e8f9f7 | 285 | } |
<> | 144:ef7eb2e8f9f7 | 286 | |
<> | 144:ef7eb2e8f9f7 | 287 | /* Clear pending flag. */ |
<> | 144:ef7eb2e8f9f7 | 288 | base->S = kI2C_IntPendingFlag; |
<> | 144:ef7eb2e8f9f7 | 289 | |
<> | 144:ef7eb2e8f9f7 | 290 | /* Send repeated start and slave address. */ |
<> | 144:ef7eb2e8f9f7 | 291 | result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read); |
<> | 144:ef7eb2e8f9f7 | 292 | } |
<> | 144:ef7eb2e8f9f7 | 293 | } |
<> | 144:ef7eb2e8f9f7 | 294 | |
<> | 144:ef7eb2e8f9f7 | 295 | if (result) |
<> | 144:ef7eb2e8f9f7 | 296 | { |
<> | 144:ef7eb2e8f9f7 | 297 | return result; |
<> | 144:ef7eb2e8f9f7 | 298 | } |
<> | 144:ef7eb2e8f9f7 | 299 | |
<> | 144:ef7eb2e8f9f7 | 300 | /* Wait until data transfer complete. */ |
<> | 144:ef7eb2e8f9f7 | 301 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 144:ef7eb2e8f9f7 | 302 | { |
<> | 144:ef7eb2e8f9f7 | 303 | } |
<> | 144:ef7eb2e8f9f7 | 304 | |
<> | 144:ef7eb2e8f9f7 | 305 | /* Clear pending flag. */ |
<> | 144:ef7eb2e8f9f7 | 306 | base->S = kI2C_IntPendingFlag; |
<> | 144:ef7eb2e8f9f7 | 307 | |
<> | 144:ef7eb2e8f9f7 | 308 | /* Check if there's transfer error. */ |
<> | 144:ef7eb2e8f9f7 | 309 | result = I2C_CheckAndClearError(base, base->S); |
<> | 144:ef7eb2e8f9f7 | 310 | } |
<> | 144:ef7eb2e8f9f7 | 311 | |
<> | 144:ef7eb2e8f9f7 | 312 | return result; |
<> | 144:ef7eb2e8f9f7 | 313 | } |
<> | 144:ef7eb2e8f9f7 | 314 | |
<> | 144:ef7eb2e8f9f7 | 315 | static void I2C_MasterTransferDMAConfig(I2C_Type *base, i2c_master_dma_handle_t *handle) |
<> | 144:ef7eb2e8f9f7 | 316 | { |
<> | 144:ef7eb2e8f9f7 | 317 | dma_transfer_config_t transfer_config; |
<> | 144:ef7eb2e8f9f7 | 318 | dma_transfer_options_t transfer_options = kDMA_EnableInterrupt; |
<> | 144:ef7eb2e8f9f7 | 319 | |
<> | 144:ef7eb2e8f9f7 | 320 | if (handle->transfer.direction == kI2C_Read) |
<> | 144:ef7eb2e8f9f7 | 321 | { |
<> | 144:ef7eb2e8f9f7 | 322 | transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base); |
<> | 144:ef7eb2e8f9f7 | 323 | transfer_config.destAddr = (uint32_t)(handle->transfer.data); |
<> | 144:ef7eb2e8f9f7 | 324 | |
<> | 144:ef7eb2e8f9f7 | 325 | /* Send stop if kI2C_TransferNoStop flag is not asserted. */ |
<> | 144:ef7eb2e8f9f7 | 326 | if (!(handle->transfer.flags & kI2C_TransferNoStopFlag)) |
<> | 144:ef7eb2e8f9f7 | 327 | { |
<> | 144:ef7eb2e8f9f7 | 328 | transfer_config.transferSize = (handle->transfer.dataSize - 1); |
<> | 144:ef7eb2e8f9f7 | 329 | } |
<> | 144:ef7eb2e8f9f7 | 330 | else |
<> | 144:ef7eb2e8f9f7 | 331 | { |
<> | 144:ef7eb2e8f9f7 | 332 | transfer_config.transferSize = handle->transfer.dataSize; |
<> | 144:ef7eb2e8f9f7 | 333 | } |
<> | 144:ef7eb2e8f9f7 | 334 | |
<> | 144:ef7eb2e8f9f7 | 335 | transfer_config.srcSize = kDMA_Transfersize8bits; |
<> | 144:ef7eb2e8f9f7 | 336 | transfer_config.enableSrcIncrement = false; |
<> | 144:ef7eb2e8f9f7 | 337 | transfer_config.destSize = kDMA_Transfersize8bits; |
<> | 144:ef7eb2e8f9f7 | 338 | transfer_config.enableDestIncrement = true; |
<> | 144:ef7eb2e8f9f7 | 339 | } |
<> | 144:ef7eb2e8f9f7 | 340 | else |
<> | 144:ef7eb2e8f9f7 | 341 | { |
<> | 144:ef7eb2e8f9f7 | 342 | transfer_config.srcAddr = (uint32_t)(handle->transfer.data + 1); |
<> | 144:ef7eb2e8f9f7 | 343 | transfer_config.destAddr = (uint32_t)I2C_GetDataRegAddr(base); |
<> | 144:ef7eb2e8f9f7 | 344 | transfer_config.transferSize = (handle->transfer.dataSize - 1); |
<> | 144:ef7eb2e8f9f7 | 345 | transfer_config.srcSize = kDMA_Transfersize8bits; |
<> | 144:ef7eb2e8f9f7 | 346 | transfer_config.enableSrcIncrement = true; |
<> | 144:ef7eb2e8f9f7 | 347 | transfer_config.destSize = kDMA_Transfersize8bits; |
<> | 144:ef7eb2e8f9f7 | 348 | transfer_config.enableDestIncrement = false; |
<> | 144:ef7eb2e8f9f7 | 349 | } |
<> | 144:ef7eb2e8f9f7 | 350 | |
<> | 144:ef7eb2e8f9f7 | 351 | DMA_SubmitTransfer(handle->dmaHandle, &transfer_config, transfer_options); |
<> | 144:ef7eb2e8f9f7 | 352 | DMA_StartTransfer(handle->dmaHandle); |
<> | 144:ef7eb2e8f9f7 | 353 | } |
<> | 144:ef7eb2e8f9f7 | 354 | |
<> | 144:ef7eb2e8f9f7 | 355 | void I2C_MasterTransferCreateHandleDMA(I2C_Type *base, |
<> | 144:ef7eb2e8f9f7 | 356 | i2c_master_dma_handle_t *handle, |
<> | 144:ef7eb2e8f9f7 | 357 | i2c_master_dma_transfer_callback_t callback, |
<> | 144:ef7eb2e8f9f7 | 358 | void *userData, |
<> | 144:ef7eb2e8f9f7 | 359 | dma_handle_t *dmaHandle) |
<> | 144:ef7eb2e8f9f7 | 360 | { |
<> | 144:ef7eb2e8f9f7 | 361 | assert(handle); |
<> | 144:ef7eb2e8f9f7 | 362 | assert(dmaHandle); |
<> | 144:ef7eb2e8f9f7 | 363 | |
<> | 144:ef7eb2e8f9f7 | 364 | uint32_t instance = I2C_GetInstance(base); |
<> | 144:ef7eb2e8f9f7 | 365 | |
<> | 144:ef7eb2e8f9f7 | 366 | /* Zero handle. */ |
<> | 144:ef7eb2e8f9f7 | 367 | memset(handle, 0, sizeof(*handle)); |
<> | 144:ef7eb2e8f9f7 | 368 | |
<> | 144:ef7eb2e8f9f7 | 369 | /* Set the user callback and userData. */ |
<> | 144:ef7eb2e8f9f7 | 370 | handle->completionCallback = callback; |
<> | 144:ef7eb2e8f9f7 | 371 | handle->userData = userData; |
<> | 144:ef7eb2e8f9f7 | 372 | |
<> | 144:ef7eb2e8f9f7 | 373 | /* Set the handle for DMA. */ |
<> | 144:ef7eb2e8f9f7 | 374 | handle->dmaHandle = dmaHandle; |
<> | 144:ef7eb2e8f9f7 | 375 | |
<> | 144:ef7eb2e8f9f7 | 376 | s_dmaPrivateHandle[instance].base = base; |
<> | 144:ef7eb2e8f9f7 | 377 | s_dmaPrivateHandle[instance].handle = handle; |
<> | 144:ef7eb2e8f9f7 | 378 | |
<> | 144:ef7eb2e8f9f7 | 379 | DMA_SetCallback(dmaHandle, (dma_callback)I2C_MasterTransferCallbackDMA, &s_dmaPrivateHandle[instance]); |
<> | 144:ef7eb2e8f9f7 | 380 | } |
<> | 144:ef7eb2e8f9f7 | 381 | |
<> | 144:ef7eb2e8f9f7 | 382 | status_t I2C_MasterTransferDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, i2c_master_transfer_t *xfer) |
<> | 144:ef7eb2e8f9f7 | 383 | { |
<> | 144:ef7eb2e8f9f7 | 384 | assert(handle); |
<> | 144:ef7eb2e8f9f7 | 385 | assert(xfer); |
<> | 144:ef7eb2e8f9f7 | 386 | |
<> | 144:ef7eb2e8f9f7 | 387 | status_t result; |
<> | 144:ef7eb2e8f9f7 | 388 | uint8_t tmpReg; |
<> | 144:ef7eb2e8f9f7 | 389 | volatile uint8_t dummy = 0; |
<> | 144:ef7eb2e8f9f7 | 390 | |
<> | 144:ef7eb2e8f9f7 | 391 | /* Add this to avoid build warning. */ |
<> | 144:ef7eb2e8f9f7 | 392 | dummy++; |
<> | 144:ef7eb2e8f9f7 | 393 | |
<> | 144:ef7eb2e8f9f7 | 394 | /* Disable dma transfer. */ |
<> | 144:ef7eb2e8f9f7 | 395 | I2C_EnableDMA(base, false); |
<> | 144:ef7eb2e8f9f7 | 396 | |
<> | 144:ef7eb2e8f9f7 | 397 | /* Send address and command buffer(if there is), until senddata phase or receive data phase. */ |
<> | 144:ef7eb2e8f9f7 | 398 | result = I2C_InitTransferStateMachineDMA(base, handle, xfer); |
<> | 144:ef7eb2e8f9f7 | 399 | |
<> | 144:ef7eb2e8f9f7 | 400 | if (result != kStatus_Success) |
<> | 144:ef7eb2e8f9f7 | 401 | { |
<> | 144:ef7eb2e8f9f7 | 402 | /* Send stop if received Nak. */ |
<> | 144:ef7eb2e8f9f7 | 403 | if (result == kStatus_I2C_Nak) |
<> | 144:ef7eb2e8f9f7 | 404 | { |
<> | 144:ef7eb2e8f9f7 | 405 | if (I2C_MasterStop(base) != kStatus_Success) |
<> | 144:ef7eb2e8f9f7 | 406 | { |
<> | 144:ef7eb2e8f9f7 | 407 | result = kStatus_I2C_Timeout; |
<> | 144:ef7eb2e8f9f7 | 408 | } |
<> | 144:ef7eb2e8f9f7 | 409 | } |
<> | 144:ef7eb2e8f9f7 | 410 | |
<> | 144:ef7eb2e8f9f7 | 411 | /* Reset the state to idle state. */ |
<> | 144:ef7eb2e8f9f7 | 412 | handle->state = kIdleState; |
<> | 144:ef7eb2e8f9f7 | 413 | |
<> | 144:ef7eb2e8f9f7 | 414 | return result; |
<> | 144:ef7eb2e8f9f7 | 415 | } |
<> | 144:ef7eb2e8f9f7 | 416 | |
<> | 144:ef7eb2e8f9f7 | 417 | /* Configure dma transfer. */ |
<> | 144:ef7eb2e8f9f7 | 418 | /* For i2c send, need to send 1 byte first to trigger the dma, for i2c read, |
<> | 144:ef7eb2e8f9f7 | 419 | need to send stop before reading the last byte, so the dma transfer size should |
<> | 144:ef7eb2e8f9f7 | 420 | be (xSize - 1). */ |
<> | 144:ef7eb2e8f9f7 | 421 | if (handle->transfer.dataSize > 1) |
<> | 144:ef7eb2e8f9f7 | 422 | { |
<> | 144:ef7eb2e8f9f7 | 423 | I2C_MasterTransferDMAConfig(base, handle); |
<> | 144:ef7eb2e8f9f7 | 424 | if (handle->transfer.direction == kI2C_Read) |
<> | 144:ef7eb2e8f9f7 | 425 | { |
<> | 144:ef7eb2e8f9f7 | 426 | /* Change direction for receive. */ |
<> | 144:ef7eb2e8f9f7 | 427 | base->C1 &= ~I2C_C1_TX_MASK; |
<> | 144:ef7eb2e8f9f7 | 428 | |
<> | 144:ef7eb2e8f9f7 | 429 | /* Read dummy to release the bus. */ |
<> | 144:ef7eb2e8f9f7 | 430 | dummy = base->D; |
<> | 144:ef7eb2e8f9f7 | 431 | |
<> | 144:ef7eb2e8f9f7 | 432 | /* Enabe dma transfer. */ |
<> | 144:ef7eb2e8f9f7 | 433 | I2C_EnableDMA(base, true); |
<> | 144:ef7eb2e8f9f7 | 434 | } |
<> | 144:ef7eb2e8f9f7 | 435 | else |
<> | 144:ef7eb2e8f9f7 | 436 | { |
<> | 144:ef7eb2e8f9f7 | 437 | /* Enabe dma transfer. */ |
<> | 144:ef7eb2e8f9f7 | 438 | I2C_EnableDMA(base, true); |
<> | 144:ef7eb2e8f9f7 | 439 | |
<> | 144:ef7eb2e8f9f7 | 440 | /* Send the first data. */ |
<> | 144:ef7eb2e8f9f7 | 441 | base->D = *handle->transfer.data; |
<> | 144:ef7eb2e8f9f7 | 442 | } |
<> | 144:ef7eb2e8f9f7 | 443 | } |
<> | 144:ef7eb2e8f9f7 | 444 | else /* If transfer size is 1, use polling method. */ |
<> | 144:ef7eb2e8f9f7 | 445 | { |
<> | 144:ef7eb2e8f9f7 | 446 | if (handle->transfer.direction == kI2C_Read) |
<> | 144:ef7eb2e8f9f7 | 447 | { |
<> | 144:ef7eb2e8f9f7 | 448 | tmpReg = base->C1; |
<> | 144:ef7eb2e8f9f7 | 449 | |
<> | 144:ef7eb2e8f9f7 | 450 | /* Change direction to Rx. */ |
<> | 144:ef7eb2e8f9f7 | 451 | tmpReg &= ~I2C_C1_TX_MASK; |
<> | 144:ef7eb2e8f9f7 | 452 | |
<> | 144:ef7eb2e8f9f7 | 453 | /* Configure send NAK */ |
<> | 144:ef7eb2e8f9f7 | 454 | tmpReg |= I2C_C1_TXAK_MASK; |
<> | 144:ef7eb2e8f9f7 | 455 | |
<> | 144:ef7eb2e8f9f7 | 456 | base->C1 = tmpReg; |
<> | 144:ef7eb2e8f9f7 | 457 | |
<> | 144:ef7eb2e8f9f7 | 458 | /* Read dummy to release the bus. */ |
<> | 144:ef7eb2e8f9f7 | 459 | dummy = base->D; |
<> | 144:ef7eb2e8f9f7 | 460 | } |
<> | 144:ef7eb2e8f9f7 | 461 | else |
<> | 144:ef7eb2e8f9f7 | 462 | { |
<> | 144:ef7eb2e8f9f7 | 463 | base->D = *handle->transfer.data; |
<> | 144:ef7eb2e8f9f7 | 464 | } |
<> | 144:ef7eb2e8f9f7 | 465 | |
<> | 144:ef7eb2e8f9f7 | 466 | /* Wait until data transfer complete. */ |
<> | 144:ef7eb2e8f9f7 | 467 | while (!(base->S & kI2C_IntPendingFlag)) |
<> | 144:ef7eb2e8f9f7 | 468 | { |
<> | 144:ef7eb2e8f9f7 | 469 | } |
<> | 144:ef7eb2e8f9f7 | 470 | |
<> | 144:ef7eb2e8f9f7 | 471 | /* Clear pending flag. */ |
<> | 144:ef7eb2e8f9f7 | 472 | base->S = kI2C_IntPendingFlag; |
<> | 144:ef7eb2e8f9f7 | 473 | |
<> | 144:ef7eb2e8f9f7 | 474 | /* Send stop if kI2C_TransferNoStop flag is not asserted. */ |
<> | 144:ef7eb2e8f9f7 | 475 | if (!(handle->transfer.flags & kI2C_TransferNoStopFlag)) |
<> | 144:ef7eb2e8f9f7 | 476 | { |
<> | 144:ef7eb2e8f9f7 | 477 | result = I2C_MasterStop(base); |
<> | 144:ef7eb2e8f9f7 | 478 | } |
<> | 144:ef7eb2e8f9f7 | 479 | |
<> | 144:ef7eb2e8f9f7 | 480 | /* Read the last byte of data. */ |
<> | 144:ef7eb2e8f9f7 | 481 | if (handle->transfer.direction == kI2C_Read) |
<> | 144:ef7eb2e8f9f7 | 482 | { |
<> | 144:ef7eb2e8f9f7 | 483 | *handle->transfer.data = base->D; |
<> | 144:ef7eb2e8f9f7 | 484 | } |
<> | 144:ef7eb2e8f9f7 | 485 | |
<> | 144:ef7eb2e8f9f7 | 486 | /* Reset the state to idle. */ |
<> | 144:ef7eb2e8f9f7 | 487 | handle->state = kIdleState; |
<> | 144:ef7eb2e8f9f7 | 488 | } |
<> | 144:ef7eb2e8f9f7 | 489 | |
<> | 144:ef7eb2e8f9f7 | 490 | return result; |
<> | 144:ef7eb2e8f9f7 | 491 | } |
<> | 144:ef7eb2e8f9f7 | 492 | |
<> | 144:ef7eb2e8f9f7 | 493 | status_t I2C_MasterTransferGetCountDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, size_t *count) |
<> | 144:ef7eb2e8f9f7 | 494 | { |
<> | 144:ef7eb2e8f9f7 | 495 | assert(handle); |
<> | 144:ef7eb2e8f9f7 | 496 | |
<> | 144:ef7eb2e8f9f7 | 497 | if (!count) |
<> | 144:ef7eb2e8f9f7 | 498 | { |
<> | 144:ef7eb2e8f9f7 | 499 | return kStatus_InvalidArgument; |
<> | 144:ef7eb2e8f9f7 | 500 | } |
<> | 144:ef7eb2e8f9f7 | 501 | |
<> | 144:ef7eb2e8f9f7 | 502 | if (kIdleState != handle->state) |
<> | 144:ef7eb2e8f9f7 | 503 | { |
<> | 144:ef7eb2e8f9f7 | 504 | *count = (handle->transferSize - DMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); |
<> | 144:ef7eb2e8f9f7 | 505 | } |
<> | 144:ef7eb2e8f9f7 | 506 | else |
<> | 144:ef7eb2e8f9f7 | 507 | { |
<> | 144:ef7eb2e8f9f7 | 508 | *count = handle->transferSize; |
<> | 144:ef7eb2e8f9f7 | 509 | } |
<> | 144:ef7eb2e8f9f7 | 510 | |
<> | 144:ef7eb2e8f9f7 | 511 | return kStatus_Success; |
<> | 144:ef7eb2e8f9f7 | 512 | } |
<> | 144:ef7eb2e8f9f7 | 513 | |
<> | 144:ef7eb2e8f9f7 | 514 | void I2C_MasterTransferAbortDMA(I2C_Type *base, i2c_master_dma_handle_t *handle) |
<> | 144:ef7eb2e8f9f7 | 515 | { |
<> | 144:ef7eb2e8f9f7 | 516 | DMA_AbortTransfer(handle->dmaHandle); |
<> | 144:ef7eb2e8f9f7 | 517 | |
<> | 144:ef7eb2e8f9f7 | 518 | /* Disable dma transfer. */ |
<> | 144:ef7eb2e8f9f7 | 519 | I2C_EnableDMA(base, false); |
<> | 144:ef7eb2e8f9f7 | 520 | |
<> | 144:ef7eb2e8f9f7 | 521 | /* Reset the state to idle. */ |
<> | 144:ef7eb2e8f9f7 | 522 | handle->state = kIdleState; |
<> | 144:ef7eb2e8f9f7 | 523 | } |