mbed official / mbed-dev

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Tue Mar 20 16:56:18 2018 +0000
Revision:
182:a56a73fd2a6f
Parent:
175:af195413fb11
mbed-dev library. Release version 160

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Kojto 170:19eb464bc2be 1 /*
AnnaBridge 182:a56a73fd2a6f 2 * The Clear BSD License
Kojto 170:19eb464bc2be 3 * Copyright (c) 2016, Freescale Semiconductor, Inc.
Kojto 170:19eb464bc2be 4 * Copyright 2016-2017 NXP
AnnaBridge 182:a56a73fd2a6f 5 * All rights reserved.
Kojto 170:19eb464bc2be 6 *
Kojto 170:19eb464bc2be 7 * Redistribution and use in source and binary forms, with or without modification,
AnnaBridge 182:a56a73fd2a6f 8 * are permitted (subject to the limitations in the disclaimer below) provided
AnnaBridge 182:a56a73fd2a6f 9 * that the following conditions are met:
Kojto 170:19eb464bc2be 10 *
Kojto 170:19eb464bc2be 11 * o Redistributions of source code must retain the above copyright notice, this list
Kojto 170:19eb464bc2be 12 * of conditions and the following disclaimer.
Kojto 170:19eb464bc2be 13 *
Kojto 170:19eb464bc2be 14 * o Redistributions in binary form must reproduce the above copyright notice, this
Kojto 170:19eb464bc2be 15 * list of conditions and the following disclaimer in the documentation and/or
Kojto 170:19eb464bc2be 16 * other materials provided with the distribution.
Kojto 170:19eb464bc2be 17 *
Kojto 170:19eb464bc2be 18 * o Neither the name of the copyright holder nor the names of its
Kojto 170:19eb464bc2be 19 * contributors may be used to endorse or promote products derived from this
Kojto 170:19eb464bc2be 20 * software without specific prior written permission.
Kojto 170:19eb464bc2be 21 *
AnnaBridge 182:a56a73fd2a6f 22 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
Kojto 170:19eb464bc2be 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Kojto 170:19eb464bc2be 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Kojto 170:19eb464bc2be 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Kojto 170:19eb464bc2be 26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
Kojto 170:19eb464bc2be 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Kojto 170:19eb464bc2be 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Kojto 170:19eb464bc2be 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
Kojto 170:19eb464bc2be 30 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Kojto 170:19eb464bc2be 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Kojto 170:19eb464bc2be 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Kojto 170:19eb464bc2be 33 */
Kojto 170:19eb464bc2be 34
Kojto 170:19eb464bc2be 35 #include "fsl_spi_dma.h"
Kojto 170:19eb464bc2be 36
Kojto 170:19eb464bc2be 37 /*******************************************************************************
Kojto 170:19eb464bc2be 38 * Definitons
Kojto 170:19eb464bc2be 39 ******************************************************************************/
Kojto 170:19eb464bc2be 40 /*<! Structure definition for spi_dma_private_handle_t. The structure is private. */
Kojto 170:19eb464bc2be 41 typedef struct _spi_dma_private_handle
Kojto 170:19eb464bc2be 42 {
Kojto 170:19eb464bc2be 43 SPI_Type *base;
Kojto 170:19eb464bc2be 44 spi_dma_handle_t *handle;
Kojto 170:19eb464bc2be 45 } spi_dma_private_handle_t;
Kojto 170:19eb464bc2be 46
Kojto 170:19eb464bc2be 47 /*! @brief SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
Kojto 170:19eb464bc2be 48 enum _spi_dma_states_t
Kojto 170:19eb464bc2be 49 {
Kojto 170:19eb464bc2be 50 kSPI_Idle = 0x0, /*!< SPI is idle state */
Kojto 170:19eb464bc2be 51 kSPI_Busy /*!< SPI is busy tranferring data. */
Kojto 170:19eb464bc2be 52 };
Kojto 170:19eb464bc2be 53
Kojto 170:19eb464bc2be 54 typedef struct _spi_dma_txdummy
Kojto 170:19eb464bc2be 55 {
Kojto 170:19eb464bc2be 56 uint32_t lastWord;
Kojto 170:19eb464bc2be 57 uint32_t word;
Kojto 170:19eb464bc2be 58 } spi_dma_txdummy_t;
Kojto 170:19eb464bc2be 59
Kojto 170:19eb464bc2be 60 /*<! Private handle only used for internally. */
Kojto 170:19eb464bc2be 61 static spi_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_SPI_COUNT];
Kojto 170:19eb464bc2be 62 /*******************************************************************************
Kojto 170:19eb464bc2be 63 * Prototypes
Kojto 170:19eb464bc2be 64 ******************************************************************************/
Kojto 170:19eb464bc2be 65
Kojto 170:19eb464bc2be 66 /*!
Kojto 170:19eb464bc2be 67 * @brief SPI private function to return SPI configuration
Kojto 170:19eb464bc2be 68 *
Kojto 170:19eb464bc2be 69 * @param base SPI base address.
Kojto 170:19eb464bc2be 70 */
Kojto 170:19eb464bc2be 71 void *SPI_GetConfig(SPI_Type *base);
Kojto 170:19eb464bc2be 72
Kojto 170:19eb464bc2be 73 /*!
Kojto 170:19eb464bc2be 74 * @brief DMA callback function for SPI send transfer.
Kojto 170:19eb464bc2be 75 *
Kojto 170:19eb464bc2be 76 * @param handle DMA handle pointer.
Kojto 170:19eb464bc2be 77 * @param userData User data for DMA callback function.
Kojto 170:19eb464bc2be 78 */
Kojto 170:19eb464bc2be 79 static void SPI_TxDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode);
Kojto 170:19eb464bc2be 80
Kojto 170:19eb464bc2be 81 /*!
Kojto 170:19eb464bc2be 82 * @brief DMA callback function for SPI receive transfer.
Kojto 170:19eb464bc2be 83 *
Kojto 170:19eb464bc2be 84 * @param handle DMA handle pointer.
Kojto 170:19eb464bc2be 85 * @param userData User data for DMA callback function.
Kojto 170:19eb464bc2be 86 */
Kojto 170:19eb464bc2be 87 static void SPI_RxDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode);
Kojto 170:19eb464bc2be 88
Kojto 170:19eb464bc2be 89 /*******************************************************************************
Kojto 170:19eb464bc2be 90 * Variables
Kojto 170:19eb464bc2be 91 ******************************************************************************/
Kojto 170:19eb464bc2be 92 #if defined(__ICCARM__)
Kojto 170:19eb464bc2be 93 #pragma data_alignment = 4
Kojto 170:19eb464bc2be 94 static spi_dma_txdummy_t s_txDummy[FSL_FEATURE_SOC_SPI_COUNT] = {0};
Kojto 170:19eb464bc2be 95 #elif defined(__CC_ARM)
Kojto 170:19eb464bc2be 96 __attribute__((aligned(4))) static spi_dma_txdummy_t s_txDummy[FSL_FEATURE_SOC_SPI_COUNT] = {0};
Kojto 170:19eb464bc2be 97 #elif defined(__GNUC__)
Kojto 170:19eb464bc2be 98 __attribute__((aligned(4))) static spi_dma_txdummy_t s_txDummy[FSL_FEATURE_SOC_SPI_COUNT] = {0};
Kojto 170:19eb464bc2be 99 #endif
Kojto 170:19eb464bc2be 100
Kojto 170:19eb464bc2be 101 #if defined(__ICCARM__)
Kojto 170:19eb464bc2be 102 #pragma data_alignment = 4
Kojto 170:19eb464bc2be 103 static uint16_t s_rxDummy;
AnnaBridge 182:a56a73fd2a6f 104 static uint32_t s_txLastWord[FSL_FEATURE_SOC_SPI_COUNT];
Kojto 170:19eb464bc2be 105 #elif defined(__CC_ARM)
Kojto 170:19eb464bc2be 106 __attribute__((aligned(4))) static uint16_t s_rxDummy;
AnnaBridge 182:a56a73fd2a6f 107 __attribute__((aligned(4))) static uint32_t s_txLastWord[FSL_FEATURE_SOC_SPI_COUNT];
Kojto 170:19eb464bc2be 108 #elif defined(__GNUC__)
Kojto 170:19eb464bc2be 109 __attribute__((aligned(4))) static uint16_t s_rxDummy;
AnnaBridge 182:a56a73fd2a6f 110 __attribute__((aligned(4))) static uint32_t s_txLastWord[FSL_FEATURE_SOC_SPI_COUNT];
Kojto 170:19eb464bc2be 111 #endif
Kojto 170:19eb464bc2be 112
Kojto 170:19eb464bc2be 113 #if defined(__ICCARM__)
Kojto 170:19eb464bc2be 114 #pragma data_alignment = 16
Kojto 170:19eb464bc2be 115 static dma_descriptor_t s_spi_descriptor_table[FSL_FEATURE_SOC_SPI_COUNT] = {0};
Kojto 170:19eb464bc2be 116 #elif defined(__CC_ARM)
Kojto 170:19eb464bc2be 117 __attribute__((aligned(16))) static dma_descriptor_t s_spi_descriptor_table[FSL_FEATURE_SOC_SPI_COUNT] = {0};
Kojto 170:19eb464bc2be 118 #elif defined(__GNUC__)
Kojto 170:19eb464bc2be 119 __attribute__((aligned(16))) static dma_descriptor_t s_spi_descriptor_table[FSL_FEATURE_SOC_SPI_COUNT] = {0};
Kojto 170:19eb464bc2be 120 #endif
Kojto 170:19eb464bc2be 121
AnnaBridge 182:a56a73fd2a6f 122 /*! @brief Global variable for dummy data value setting. */
AnnaBridge 182:a56a73fd2a6f 123 extern volatile uint8_t s_dummyData[];
Kojto 170:19eb464bc2be 124 /*******************************************************************************
Kojto 170:19eb464bc2be 125 * Code
Kojto 170:19eb464bc2be 126 ******************************************************************************/
Kojto 170:19eb464bc2be 127
Kojto 170:19eb464bc2be 128 static void XferToFifoWR(spi_transfer_t *xfer, uint32_t *fifowr)
Kojto 170:19eb464bc2be 129 {
Kojto 170:19eb464bc2be 130 *fifowr |= xfer->configFlags & (uint32_t)kSPI_FrameDelay ? (uint32_t)kSPI_FrameDelay : 0;
Kojto 170:19eb464bc2be 131 *fifowr |= xfer->configFlags & (uint32_t)kSPI_FrameAssert ? (uint32_t)kSPI_FrameAssert : 0;
Kojto 170:19eb464bc2be 132 }
Kojto 170:19eb464bc2be 133
Kojto 170:19eb464bc2be 134 static void SpiConfigToFifoWR(spi_config_t *config, uint32_t *fifowr)
Kojto 170:19eb464bc2be 135 {
Kojto 170:19eb464bc2be 136 *fifowr |= (SPI_DEASSERT_ALL & (~SPI_DEASSERTNUM_SSEL(config->sselNum)));
Kojto 170:19eb464bc2be 137 /* set width of data - range asserted at entry */
Kojto 170:19eb464bc2be 138 *fifowr |= SPI_FIFOWR_LEN(config->dataWidth);
Kojto 170:19eb464bc2be 139 }
Kojto 170:19eb464bc2be 140
AnnaBridge 182:a56a73fd2a6f 141 static void PrepareTxLastWord(spi_transfer_t *xfer, uint32_t *txLastWord, spi_config_t *config)
Kojto 170:19eb464bc2be 142 {
AnnaBridge 182:a56a73fd2a6f 143 if (config->dataWidth > kSPI_Data8Bits)
Kojto 170:19eb464bc2be 144 {
AnnaBridge 182:a56a73fd2a6f 145 *txLastWord = (((uint32_t)xfer->txData[xfer->dataSize - 1] << 8U) | (xfer->txData[xfer->dataSize - 2]));
Kojto 170:19eb464bc2be 146 }
AnnaBridge 182:a56a73fd2a6f 147 else
Kojto 170:19eb464bc2be 148 {
AnnaBridge 182:a56a73fd2a6f 149 *txLastWord = xfer->txData[xfer->dataSize - 1];
Kojto 170:19eb464bc2be 150 }
AnnaBridge 182:a56a73fd2a6f 151 XferToFifoWR(xfer, txLastWord);
AnnaBridge 182:a56a73fd2a6f 152 SpiConfigToFifoWR(config, txLastWord);
Kojto 170:19eb464bc2be 153 }
Kojto 170:19eb464bc2be 154
AnnaBridge 182:a56a73fd2a6f 155 static void SPI_SetupDummy(SPI_Type *base, spi_dma_txdummy_t *dummy, spi_transfer_t *xfer, spi_config_t *spi_config_p)
Kojto 170:19eb464bc2be 156 {
AnnaBridge 182:a56a73fd2a6f 157 uint32_t instance = SPI_GetInstance(base);
AnnaBridge 182:a56a73fd2a6f 158 dummy->word = ((uint32_t)s_dummyData[instance] << 8U | s_dummyData[instance]);
AnnaBridge 182:a56a73fd2a6f 159 dummy->lastWord = ((uint32_t)s_dummyData[instance] << 8U | s_dummyData[instance]);
AnnaBridge 182:a56a73fd2a6f 160 XferToFifoWR(xfer, &dummy->word);
AnnaBridge 182:a56a73fd2a6f 161 XferToFifoWR(xfer, &dummy->lastWord);
AnnaBridge 182:a56a73fd2a6f 162 SpiConfigToFifoWR(spi_config_p, &dummy->word);
AnnaBridge 182:a56a73fd2a6f 163 SpiConfigToFifoWR(spi_config_p, &dummy->lastWord);
AnnaBridge 182:a56a73fd2a6f 164 /* Clear the end of transfer bit for continue word transfer. */
AnnaBridge 182:a56a73fd2a6f 165 dummy->word &= (uint32_t)(~kSPI_FrameAssert);
Kojto 170:19eb464bc2be 166 }
Kojto 170:19eb464bc2be 167
Kojto 170:19eb464bc2be 168 status_t SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
Kojto 170:19eb464bc2be 169 spi_dma_handle_t *handle,
Kojto 170:19eb464bc2be 170 spi_dma_callback_t callback,
Kojto 170:19eb464bc2be 171 void *userData,
Kojto 170:19eb464bc2be 172 dma_handle_t *txHandle,
Kojto 170:19eb464bc2be 173 dma_handle_t *rxHandle)
Kojto 170:19eb464bc2be 174 {
Kojto 170:19eb464bc2be 175 int32_t instance = 0;
Kojto 170:19eb464bc2be 176
Kojto 170:19eb464bc2be 177 /* check 'base' */
Kojto 170:19eb464bc2be 178 assert(!(NULL == base));
Kojto 170:19eb464bc2be 179 if (NULL == base)
Kojto 170:19eb464bc2be 180 {
Kojto 170:19eb464bc2be 181 return kStatus_InvalidArgument;
Kojto 170:19eb464bc2be 182 }
Kojto 170:19eb464bc2be 183 /* check 'handle' */
Kojto 170:19eb464bc2be 184 assert(!(NULL == handle));
Kojto 170:19eb464bc2be 185 if (NULL == handle)
Kojto 170:19eb464bc2be 186 {
Kojto 170:19eb464bc2be 187 return kStatus_InvalidArgument;
Kojto 170:19eb464bc2be 188 }
Kojto 170:19eb464bc2be 189
Kojto 170:19eb464bc2be 190 instance = SPI_GetInstance(base);
Kojto 170:19eb464bc2be 191
Kojto 170:19eb464bc2be 192 memset(handle, 0, sizeof(*handle));
Kojto 170:19eb464bc2be 193 /* Set spi base to handle */
Kojto 170:19eb464bc2be 194 handle->txHandle = txHandle;
Kojto 170:19eb464bc2be 195 handle->rxHandle = rxHandle;
Kojto 170:19eb464bc2be 196 handle->callback = callback;
Kojto 170:19eb464bc2be 197 handle->userData = userData;
Kojto 170:19eb464bc2be 198
Kojto 170:19eb464bc2be 199 /* Set SPI state to idle */
Kojto 170:19eb464bc2be 200 handle->state = kSPI_Idle;
Kojto 170:19eb464bc2be 201
Kojto 170:19eb464bc2be 202 /* Set handle to global state */
Kojto 170:19eb464bc2be 203 s_dmaPrivateHandle[instance].base = base;
Kojto 170:19eb464bc2be 204 s_dmaPrivateHandle[instance].handle = handle;
Kojto 170:19eb464bc2be 205
Kojto 170:19eb464bc2be 206 /* Install callback for Tx dma channel */
Kojto 170:19eb464bc2be 207 DMA_SetCallback(handle->txHandle, SPI_TxDMACallback, &s_dmaPrivateHandle[instance]);
Kojto 170:19eb464bc2be 208 DMA_SetCallback(handle->rxHandle, SPI_RxDMACallback, &s_dmaPrivateHandle[instance]);
Kojto 170:19eb464bc2be 209
Kojto 170:19eb464bc2be 210 return kStatus_Success;
Kojto 170:19eb464bc2be 211 }
Kojto 170:19eb464bc2be 212
Kojto 170:19eb464bc2be 213 status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_transfer_t *xfer)
Kojto 170:19eb464bc2be 214 {
Kojto 170:19eb464bc2be 215 int32_t instance;
Kojto 170:19eb464bc2be 216 status_t result = kStatus_Success;
Kojto 170:19eb464bc2be 217 spi_config_t *spi_config_p;
Kojto 170:19eb464bc2be 218
Kojto 170:19eb464bc2be 219 assert(!((NULL == handle) || (NULL == xfer)));
Kojto 170:19eb464bc2be 220 if ((NULL == handle) || (NULL == xfer))
Kojto 170:19eb464bc2be 221 {
Kojto 170:19eb464bc2be 222 return kStatus_InvalidArgument;
Kojto 170:19eb464bc2be 223 }
AnnaBridge 182:a56a73fd2a6f 224
AnnaBridge 182:a56a73fd2a6f 225 /* Byte size is zero. */
AnnaBridge 182:a56a73fd2a6f 226 assert(!(xfer->dataSize == 0));
AnnaBridge 182:a56a73fd2a6f 227 if (xfer->dataSize == 0)
Kojto 170:19eb464bc2be 228 {
Kojto 170:19eb464bc2be 229 return kStatus_InvalidArgument;
Kojto 170:19eb464bc2be 230 }
Kojto 170:19eb464bc2be 231 /* cannot get instance from base address */
Kojto 170:19eb464bc2be 232 instance = SPI_GetInstance(base);
Kojto 170:19eb464bc2be 233 assert(!(instance < 0));
Kojto 170:19eb464bc2be 234 if (instance < 0)
Kojto 170:19eb464bc2be 235 {
Kojto 170:19eb464bc2be 236 return kStatus_InvalidArgument;
Kojto 170:19eb464bc2be 237 }
Kojto 170:19eb464bc2be 238
Kojto 170:19eb464bc2be 239 /* Check if the device is busy */
Kojto 170:19eb464bc2be 240 if (handle->state == kSPI_Busy)
Kojto 170:19eb464bc2be 241 {
Kojto 170:19eb464bc2be 242 return kStatus_SPI_Busy;
Kojto 170:19eb464bc2be 243 }
Kojto 170:19eb464bc2be 244 else
Kojto 170:19eb464bc2be 245 {
Kojto 170:19eb464bc2be 246 uint32_t tmp;
Kojto 170:19eb464bc2be 247 dma_transfer_config_t xferConfig = {0};
Kojto 170:19eb464bc2be 248 spi_config_p = (spi_config_t *)SPI_GetConfig(base);
Kojto 170:19eb464bc2be 249
Kojto 170:19eb464bc2be 250 handle->state = kStatus_SPI_Busy;
Kojto 170:19eb464bc2be 251 handle->transferSize = xfer->dataSize;
Kojto 170:19eb464bc2be 252
Kojto 170:19eb464bc2be 253 /* receive */
Kojto 170:19eb464bc2be 254 SPI_EnableRxDMA(base, true);
Kojto 170:19eb464bc2be 255 if (xfer->rxData)
Kojto 170:19eb464bc2be 256 {
AnnaBridge 182:a56a73fd2a6f 257 DMA_PrepareTransfer(&xferConfig, (void *)&base->FIFORD, xfer->rxData,
AnnaBridge 182:a56a73fd2a6f 258 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (sizeof(uint16_t)) : (sizeof(uint8_t))),
AnnaBridge 182:a56a73fd2a6f 259 xfer->dataSize, kDMA_PeripheralToMemory, NULL);
Kojto 170:19eb464bc2be 260 }
Kojto 170:19eb464bc2be 261 else
Kojto 170:19eb464bc2be 262 {
AnnaBridge 182:a56a73fd2a6f 263 DMA_PrepareTransfer(&xferConfig, (void *)&base->FIFORD, &s_rxDummy,
AnnaBridge 182:a56a73fd2a6f 264 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (sizeof(uint16_t)) : (sizeof(uint8_t))),
AnnaBridge 182:a56a73fd2a6f 265 xfer->dataSize, kDMA_StaticToStatic, NULL);
Kojto 170:19eb464bc2be 266 }
Kojto 170:19eb464bc2be 267 DMA_SubmitTransfer(handle->rxHandle, &xferConfig);
Kojto 170:19eb464bc2be 268 handle->rxInProgress = true;
Kojto 170:19eb464bc2be 269 DMA_StartTransfer(handle->rxHandle);
Kojto 170:19eb464bc2be 270
Kojto 170:19eb464bc2be 271 /* transmit */
Kojto 170:19eb464bc2be 272 SPI_EnableTxDMA(base, true);
AnnaBridge 182:a56a73fd2a6f 273
AnnaBridge 182:a56a73fd2a6f 274 if (xfer->configFlags & kSPI_FrameAssert)
AnnaBridge 182:a56a73fd2a6f 275 {
AnnaBridge 182:a56a73fd2a6f 276 PrepareTxLastWord(xfer, &s_txLastWord[instance], spi_config_p);
AnnaBridge 182:a56a73fd2a6f 277 }
AnnaBridge 182:a56a73fd2a6f 278
Kojto 170:19eb464bc2be 279 if (xfer->txData)
Kojto 170:19eb464bc2be 280 {
AnnaBridge 182:a56a73fd2a6f 281 /* If end of tranfer function is enabled and data transfer frame is bigger then 1, use dma
AnnaBridge 182:a56a73fd2a6f 282 * descriptor to send the last data.
AnnaBridge 182:a56a73fd2a6f 283 */
AnnaBridge 182:a56a73fd2a6f 284 if ((xfer->configFlags & kSPI_FrameAssert) &&
AnnaBridge 182:a56a73fd2a6f 285 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (xfer->dataSize > 2) : (xfer->dataSize > 1)))
Kojto 170:19eb464bc2be 286 {
AnnaBridge 182:a56a73fd2a6f 287 dma_xfercfg_t tmp_xfercfg = {0};
Kojto 170:19eb464bc2be 288 tmp_xfercfg.valid = true;
Kojto 170:19eb464bc2be 289 tmp_xfercfg.swtrig = true;
Kojto 170:19eb464bc2be 290 tmp_xfercfg.intA = true;
Kojto 170:19eb464bc2be 291 tmp_xfercfg.byteWidth = sizeof(uint32_t);
Kojto 170:19eb464bc2be 292 tmp_xfercfg.srcInc = 0;
Kojto 170:19eb464bc2be 293 tmp_xfercfg.dstInc = 0;
Kojto 170:19eb464bc2be 294 tmp_xfercfg.transferCount = 1;
AnnaBridge 182:a56a73fd2a6f 295 /* Create chained descriptor to transmit last word */
AnnaBridge 182:a56a73fd2a6f 296 DMA_CreateDescriptor(&s_spi_descriptor_table[instance], &tmp_xfercfg, &s_txLastWord[instance],
AnnaBridge 182:a56a73fd2a6f 297 (void *)&base->FIFOWR, NULL);
AnnaBridge 182:a56a73fd2a6f 298
AnnaBridge 182:a56a73fd2a6f 299 DMA_PrepareTransfer(
AnnaBridge 182:a56a73fd2a6f 300 &xferConfig, xfer->txData, (void *)&base->FIFOWR,
AnnaBridge 182:a56a73fd2a6f 301 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (sizeof(uint16_t)) : (sizeof(uint8_t))),
AnnaBridge 182:a56a73fd2a6f 302 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (xfer->dataSize - 2) : (xfer->dataSize - 1)),
AnnaBridge 182:a56a73fd2a6f 303 kDMA_MemoryToPeripheral, &s_spi_descriptor_table[instance]);
AnnaBridge 182:a56a73fd2a6f 304 /* Disable interrupts for first descriptor to avoid calling callback twice. */
Kojto 170:19eb464bc2be 305 xferConfig.xfercfg.intA = false;
Kojto 170:19eb464bc2be 306 xferConfig.xfercfg.intB = false;
Kojto 170:19eb464bc2be 307 result = DMA_SubmitTransfer(handle->txHandle, &xferConfig);
Kojto 170:19eb464bc2be 308 if (result != kStatus_Success)
Kojto 170:19eb464bc2be 309 {
Kojto 170:19eb464bc2be 310 return result;
Kojto 170:19eb464bc2be 311 }
Kojto 170:19eb464bc2be 312 }
Kojto 170:19eb464bc2be 313 else
Kojto 170:19eb464bc2be 314 {
AnnaBridge 182:a56a73fd2a6f 315 DMA_PrepareTransfer(
AnnaBridge 182:a56a73fd2a6f 316 &xferConfig, xfer->txData, (void *)&base->FIFOWR,
AnnaBridge 182:a56a73fd2a6f 317 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (sizeof(uint16_t)) : (sizeof(uint8_t))),
AnnaBridge 182:a56a73fd2a6f 318 xfer->dataSize, kDMA_MemoryToPeripheral, NULL);
AnnaBridge 182:a56a73fd2a6f 319 DMA_SubmitTransfer(handle->txHandle, &xferConfig);
AnnaBridge 182:a56a73fd2a6f 320 }
AnnaBridge 182:a56a73fd2a6f 321 }
AnnaBridge 182:a56a73fd2a6f 322 else
AnnaBridge 182:a56a73fd2a6f 323 {
AnnaBridge 182:a56a73fd2a6f 324 /* Setup tx dummy data. */
AnnaBridge 182:a56a73fd2a6f 325 SPI_SetupDummy(base, &s_txDummy[instance], xfer, spi_config_p);
AnnaBridge 182:a56a73fd2a6f 326 if ((xfer->configFlags & kSPI_FrameAssert) &&
AnnaBridge 182:a56a73fd2a6f 327 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (xfer->dataSize > 2) : (xfer->dataSize > 1)))
AnnaBridge 182:a56a73fd2a6f 328 {
AnnaBridge 182:a56a73fd2a6f 329 dma_xfercfg_t tmp_xfercfg = {0};
AnnaBridge 182:a56a73fd2a6f 330 tmp_xfercfg.valid = true;
AnnaBridge 182:a56a73fd2a6f 331 tmp_xfercfg.swtrig = true;
AnnaBridge 182:a56a73fd2a6f 332 tmp_xfercfg.intA = true;
AnnaBridge 182:a56a73fd2a6f 333 tmp_xfercfg.byteWidth = sizeof(uint32_t);
AnnaBridge 182:a56a73fd2a6f 334 tmp_xfercfg.srcInc = 0;
AnnaBridge 182:a56a73fd2a6f 335 tmp_xfercfg.dstInc = 0;
AnnaBridge 182:a56a73fd2a6f 336 tmp_xfercfg.transferCount = 1;
AnnaBridge 182:a56a73fd2a6f 337 /* Create chained descriptor to transmit last word */
AnnaBridge 182:a56a73fd2a6f 338 DMA_CreateDescriptor(&s_spi_descriptor_table[instance], &tmp_xfercfg, &s_txDummy[instance].lastWord,
AnnaBridge 182:a56a73fd2a6f 339 (uint32_t *)&base->FIFOWR, NULL);
AnnaBridge 182:a56a73fd2a6f 340 /* Use common API to setup first descriptor */
AnnaBridge 182:a56a73fd2a6f 341 DMA_PrepareTransfer(
AnnaBridge 182:a56a73fd2a6f 342 &xferConfig, &s_txDummy[instance].word, (void *)&base->FIFOWR,
AnnaBridge 182:a56a73fd2a6f 343 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (sizeof(uint16_t)) : (sizeof(uint8_t))),
AnnaBridge 182:a56a73fd2a6f 344 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (xfer->dataSize - 2) : (xfer->dataSize - 1)),
AnnaBridge 182:a56a73fd2a6f 345 kDMA_StaticToStatic, &s_spi_descriptor_table[instance]);
AnnaBridge 182:a56a73fd2a6f 346 /* Disable interrupts for first descriptor to avoid calling callback twice */
AnnaBridge 182:a56a73fd2a6f 347 xferConfig.xfercfg.intA = false;
AnnaBridge 182:a56a73fd2a6f 348 xferConfig.xfercfg.intB = false;
AnnaBridge 182:a56a73fd2a6f 349 result = DMA_SubmitTransfer(handle->txHandle, &xferConfig);
AnnaBridge 182:a56a73fd2a6f 350 if (result != kStatus_Success)
AnnaBridge 182:a56a73fd2a6f 351 {
AnnaBridge 182:a56a73fd2a6f 352 return result;
AnnaBridge 182:a56a73fd2a6f 353 }
AnnaBridge 182:a56a73fd2a6f 354 }
AnnaBridge 182:a56a73fd2a6f 355 else
AnnaBridge 182:a56a73fd2a6f 356 {
AnnaBridge 182:a56a73fd2a6f 357 DMA_PrepareTransfer(
AnnaBridge 182:a56a73fd2a6f 358 &xferConfig, &s_txDummy[instance].word, (void *)&base->FIFOWR,
AnnaBridge 182:a56a73fd2a6f 359 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (sizeof(uint16_t)) : (sizeof(uint8_t))),
AnnaBridge 182:a56a73fd2a6f 360 xfer->dataSize, kDMA_StaticToStatic, NULL);
Kojto 170:19eb464bc2be 361 result = DMA_SubmitTransfer(handle->txHandle, &xferConfig);
Kojto 170:19eb464bc2be 362 if (result != kStatus_Success)
Kojto 170:19eb464bc2be 363 {
Kojto 170:19eb464bc2be 364 return result;
Kojto 170:19eb464bc2be 365 }
Kojto 170:19eb464bc2be 366 }
Kojto 170:19eb464bc2be 367 }
AnnaBridge 182:a56a73fd2a6f 368
Kojto 170:19eb464bc2be 369 handle->txInProgress = true;
AnnaBridge 182:a56a73fd2a6f 370 tmp = 0;
AnnaBridge 182:a56a73fd2a6f 371 XferToFifoWR(xfer, &tmp);
AnnaBridge 182:a56a73fd2a6f 372 SpiConfigToFifoWR(spi_config_p, &tmp);
AnnaBridge 182:a56a73fd2a6f 373
AnnaBridge 182:a56a73fd2a6f 374 /* Setup the control info.
AnnaBridge 182:a56a73fd2a6f 375 * Halfword writes to just the control bits (offset 0xE22) doesn't push anything into the FIFO.
AnnaBridge 182:a56a73fd2a6f 376 * And the data access type of control bits must be uint16_t, byte writes or halfword writes to FIFOWR
AnnaBridge 182:a56a73fd2a6f 377 * will push the data and the current control bits into the FIFO.
AnnaBridge 182:a56a73fd2a6f 378 */
AnnaBridge 182:a56a73fd2a6f 379 if ((xfer->configFlags & kSPI_FrameAssert) &&
AnnaBridge 182:a56a73fd2a6f 380 ((spi_config_p->dataWidth > kSPI_Data8Bits) ? (xfer->dataSize == 2U) : (xfer->dataSize == 1U)))
AnnaBridge 182:a56a73fd2a6f 381 {
AnnaBridge 182:a56a73fd2a6f 382 *(((uint16_t *)&(base->FIFOWR)) + 1) = (uint16_t)(tmp >> 16U);
AnnaBridge 182:a56a73fd2a6f 383 }
AnnaBridge 182:a56a73fd2a6f 384 else
AnnaBridge 182:a56a73fd2a6f 385 {
AnnaBridge 182:a56a73fd2a6f 386 /* Clear the SPI_FIFOWR_EOT_MASK bit when data is not the last. */
AnnaBridge 182:a56a73fd2a6f 387 tmp &= (uint32_t)(~kSPI_FrameAssert);
AnnaBridge 182:a56a73fd2a6f 388 *(((uint16_t *)&(base->FIFOWR)) + 1) = (uint16_t)(tmp >> 16U);
AnnaBridge 182:a56a73fd2a6f 389 }
AnnaBridge 182:a56a73fd2a6f 390
Kojto 170:19eb464bc2be 391 DMA_StartTransfer(handle->txHandle);
Kojto 170:19eb464bc2be 392 }
Kojto 170:19eb464bc2be 393
Kojto 170:19eb464bc2be 394 return result;
Kojto 170:19eb464bc2be 395 }
Kojto 170:19eb464bc2be 396
AnnaBridge 182:a56a73fd2a6f 397 status_t SPI_MasterHalfDuplexTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_half_duplex_transfer_t *xfer)
AnnaBridge 182:a56a73fd2a6f 398 {
AnnaBridge 182:a56a73fd2a6f 399 assert(xfer);
AnnaBridge 182:a56a73fd2a6f 400 assert(handle);
AnnaBridge 182:a56a73fd2a6f 401 spi_transfer_t tempXfer = {0};
AnnaBridge 182:a56a73fd2a6f 402 status_t status;
AnnaBridge 182:a56a73fd2a6f 403
AnnaBridge 182:a56a73fd2a6f 404 if (xfer->isTransmitFirst)
AnnaBridge 182:a56a73fd2a6f 405 {
AnnaBridge 182:a56a73fd2a6f 406 tempXfer.txData = xfer->txData;
AnnaBridge 182:a56a73fd2a6f 407 tempXfer.rxData = NULL;
AnnaBridge 182:a56a73fd2a6f 408 tempXfer.dataSize = xfer->txDataSize;
AnnaBridge 182:a56a73fd2a6f 409 }
AnnaBridge 182:a56a73fd2a6f 410 else
AnnaBridge 182:a56a73fd2a6f 411 {
AnnaBridge 182:a56a73fd2a6f 412 tempXfer.txData = NULL;
AnnaBridge 182:a56a73fd2a6f 413 tempXfer.rxData = xfer->rxData;
AnnaBridge 182:a56a73fd2a6f 414 tempXfer.dataSize = xfer->rxDataSize;
AnnaBridge 182:a56a73fd2a6f 415 }
AnnaBridge 182:a56a73fd2a6f 416 /* If the pcs pin keep assert between transmit and receive. */
AnnaBridge 182:a56a73fd2a6f 417 if (xfer->isPcsAssertInTransfer)
AnnaBridge 182:a56a73fd2a6f 418 {
AnnaBridge 182:a56a73fd2a6f 419 tempXfer.configFlags = (xfer->configFlags) & (uint32_t)(~kSPI_FrameAssert);
AnnaBridge 182:a56a73fd2a6f 420 }
AnnaBridge 182:a56a73fd2a6f 421 else
AnnaBridge 182:a56a73fd2a6f 422 {
AnnaBridge 182:a56a73fd2a6f 423 tempXfer.configFlags = (xfer->configFlags) | kSPI_FrameAssert;
AnnaBridge 182:a56a73fd2a6f 424 }
AnnaBridge 182:a56a73fd2a6f 425
AnnaBridge 182:a56a73fd2a6f 426 status = SPI_MasterTransferBlocking(base, &tempXfer);
AnnaBridge 182:a56a73fd2a6f 427 if (status != kStatus_Success)
AnnaBridge 182:a56a73fd2a6f 428 {
AnnaBridge 182:a56a73fd2a6f 429 return status;
AnnaBridge 182:a56a73fd2a6f 430 }
AnnaBridge 182:a56a73fd2a6f 431
AnnaBridge 182:a56a73fd2a6f 432 if (xfer->isTransmitFirst)
AnnaBridge 182:a56a73fd2a6f 433 {
AnnaBridge 182:a56a73fd2a6f 434 tempXfer.txData = NULL;
AnnaBridge 182:a56a73fd2a6f 435 tempXfer.rxData = xfer->rxData;
AnnaBridge 182:a56a73fd2a6f 436 tempXfer.dataSize = xfer->rxDataSize;
AnnaBridge 182:a56a73fd2a6f 437 }
AnnaBridge 182:a56a73fd2a6f 438 else
AnnaBridge 182:a56a73fd2a6f 439 {
AnnaBridge 182:a56a73fd2a6f 440 tempXfer.txData = xfer->txData;
AnnaBridge 182:a56a73fd2a6f 441 tempXfer.rxData = NULL;
AnnaBridge 182:a56a73fd2a6f 442 tempXfer.dataSize = xfer->txDataSize;
AnnaBridge 182:a56a73fd2a6f 443 }
AnnaBridge 182:a56a73fd2a6f 444 tempXfer.configFlags = xfer->configFlags;
AnnaBridge 182:a56a73fd2a6f 445
AnnaBridge 182:a56a73fd2a6f 446 status = SPI_MasterTransferDMA(base, handle, &tempXfer);
AnnaBridge 182:a56a73fd2a6f 447
AnnaBridge 182:a56a73fd2a6f 448 return status;
AnnaBridge 182:a56a73fd2a6f 449 }
AnnaBridge 182:a56a73fd2a6f 450
Kojto 170:19eb464bc2be 451 static void SPI_RxDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode)
Kojto 170:19eb464bc2be 452 {
Kojto 170:19eb464bc2be 453 spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
Kojto 170:19eb464bc2be 454 spi_dma_handle_t *spiHandle = privHandle->handle;
Kojto 170:19eb464bc2be 455 SPI_Type *base = privHandle->base;
Kojto 170:19eb464bc2be 456
Kojto 170:19eb464bc2be 457 /* change the state */
Kojto 170:19eb464bc2be 458 spiHandle->rxInProgress = false;
Kojto 170:19eb464bc2be 459
Kojto 170:19eb464bc2be 460 /* All finished, call the callback */
Kojto 170:19eb464bc2be 461 if ((spiHandle->txInProgress == false) && (spiHandle->rxInProgress == false))
Kojto 170:19eb464bc2be 462 {
Kojto 170:19eb464bc2be 463 spiHandle->state = kSPI_Idle;
Kojto 170:19eb464bc2be 464 if (spiHandle->callback)
Kojto 170:19eb464bc2be 465 {
Kojto 170:19eb464bc2be 466 (spiHandle->callback)(base, spiHandle, kStatus_Success, spiHandle->userData);
Kojto 170:19eb464bc2be 467 }
Kojto 170:19eb464bc2be 468 }
Kojto 170:19eb464bc2be 469 }
Kojto 170:19eb464bc2be 470
Kojto 170:19eb464bc2be 471 static void SPI_TxDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode)
Kojto 170:19eb464bc2be 472 {
Kojto 170:19eb464bc2be 473 spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
Kojto 170:19eb464bc2be 474 spi_dma_handle_t *spiHandle = privHandle->handle;
Kojto 170:19eb464bc2be 475 SPI_Type *base = privHandle->base;
Kojto 170:19eb464bc2be 476
Kojto 170:19eb464bc2be 477 /* change the state */
Kojto 170:19eb464bc2be 478 spiHandle->txInProgress = false;
Kojto 170:19eb464bc2be 479
Kojto 170:19eb464bc2be 480 /* All finished, call the callback */
Kojto 170:19eb464bc2be 481 if ((spiHandle->txInProgress == false) && (spiHandle->rxInProgress == false))
Kojto 170:19eb464bc2be 482 {
Kojto 170:19eb464bc2be 483 spiHandle->state = kSPI_Idle;
Kojto 170:19eb464bc2be 484 if (spiHandle->callback)
Kojto 170:19eb464bc2be 485 {
Kojto 170:19eb464bc2be 486 (spiHandle->callback)(base, spiHandle, kStatus_Success, spiHandle->userData);
Kojto 170:19eb464bc2be 487 }
Kojto 170:19eb464bc2be 488 }
Kojto 170:19eb464bc2be 489 }
Kojto 170:19eb464bc2be 490
Kojto 170:19eb464bc2be 491 void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
Kojto 170:19eb464bc2be 492 {
Kojto 170:19eb464bc2be 493 assert(NULL != handle);
Kojto 170:19eb464bc2be 494
Kojto 170:19eb464bc2be 495 /* Stop tx transfer first */
Kojto 170:19eb464bc2be 496 DMA_AbortTransfer(handle->txHandle);
Kojto 170:19eb464bc2be 497 /* Then rx transfer */
Kojto 170:19eb464bc2be 498 DMA_AbortTransfer(handle->rxHandle);
Kojto 170:19eb464bc2be 499
Kojto 170:19eb464bc2be 500 /* Set the handle state */
Kojto 170:19eb464bc2be 501 handle->txInProgress = false;
Kojto 170:19eb464bc2be 502 handle->rxInProgress = false;
Kojto 170:19eb464bc2be 503 handle->state = kSPI_Idle;
Kojto 170:19eb464bc2be 504 }
Kojto 170:19eb464bc2be 505
Kojto 170:19eb464bc2be 506 status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle, size_t *count)
Kojto 170:19eb464bc2be 507 {
Kojto 170:19eb464bc2be 508 assert(handle);
Kojto 170:19eb464bc2be 509
Kojto 170:19eb464bc2be 510 if (!count)
Kojto 170:19eb464bc2be 511 {
Kojto 170:19eb464bc2be 512 return kStatus_InvalidArgument;
Kojto 170:19eb464bc2be 513 }
Kojto 170:19eb464bc2be 514
Kojto 170:19eb464bc2be 515 /* Catch when there is not an active transfer. */
Kojto 170:19eb464bc2be 516 if (handle->state != kSPI_Busy)
Kojto 170:19eb464bc2be 517 {
Kojto 170:19eb464bc2be 518 *count = 0;
Kojto 170:19eb464bc2be 519 return kStatus_NoTransferInProgress;
Kojto 170:19eb464bc2be 520 }
Kojto 170:19eb464bc2be 521
Kojto 170:19eb464bc2be 522 size_t bytes;
Kojto 170:19eb464bc2be 523
Kojto 170:19eb464bc2be 524 bytes = DMA_GetRemainingBytes(handle->rxHandle->base, handle->rxHandle->channel);
Kojto 170:19eb464bc2be 525
Kojto 170:19eb464bc2be 526 *count = handle->transferSize - bytes;
Kojto 170:19eb464bc2be 527
Kojto 170:19eb464bc2be 528 return kStatus_Success;
Kojto 170:19eb464bc2be 529 }