Marco Zecchini / Mbed OS Example_RTOS
Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcozecchini 0:9fca2b23d0ba 1 /*
marcozecchini 0:9fca2b23d0ba 2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
marcozecchini 0:9fca2b23d0ba 3 * Copyright 2016-2017 NXP
marcozecchini 0:9fca2b23d0ba 4 *
marcozecchini 0:9fca2b23d0ba 5 * Redistribution and use in source and binary forms, with or without modification,
marcozecchini 0:9fca2b23d0ba 6 * are permitted provided that the following conditions are met:
marcozecchini 0:9fca2b23d0ba 7 *
marcozecchini 0:9fca2b23d0ba 8 * o Redistributions of source code must retain the above copyright notice, this list
marcozecchini 0:9fca2b23d0ba 9 * of conditions and the following disclaimer.
marcozecchini 0:9fca2b23d0ba 10 *
marcozecchini 0:9fca2b23d0ba 11 * o Redistributions in binary form must reproduce the above copyright notice, this
marcozecchini 0:9fca2b23d0ba 12 * list of conditions and the following disclaimer in the documentation and/or
marcozecchini 0:9fca2b23d0ba 13 * other materials provided with the distribution.
marcozecchini 0:9fca2b23d0ba 14 *
marcozecchini 0:9fca2b23d0ba 15 * o Neither the name of the copyright holder nor the names of its
marcozecchini 0:9fca2b23d0ba 16 * contributors may be used to endorse or promote products derived from this
marcozecchini 0:9fca2b23d0ba 17 * software without specific prior written permission.
marcozecchini 0:9fca2b23d0ba 18 *
marcozecchini 0:9fca2b23d0ba 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
marcozecchini 0:9fca2b23d0ba 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
marcozecchini 0:9fca2b23d0ba 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
marcozecchini 0:9fca2b23d0ba 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
marcozecchini 0:9fca2b23d0ba 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
marcozecchini 0:9fca2b23d0ba 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
marcozecchini 0:9fca2b23d0ba 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
marcozecchini 0:9fca2b23d0ba 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
marcozecchini 0:9fca2b23d0ba 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
marcozecchini 0:9fca2b23d0ba 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
marcozecchini 0:9fca2b23d0ba 29 */
marcozecchini 0:9fca2b23d0ba 30
marcozecchini 0:9fca2b23d0ba 31 #include "fsl_dspi_edma.h"
marcozecchini 0:9fca2b23d0ba 32
marcozecchini 0:9fca2b23d0ba 33 /***********************************************************************************************************************
marcozecchini 0:9fca2b23d0ba 34 * Definitons
marcozecchini 0:9fca2b23d0ba 35 ***********************************************************************************************************************/
marcozecchini 0:9fca2b23d0ba 36
marcozecchini 0:9fca2b23d0ba 37 /*!
marcozecchini 0:9fca2b23d0ba 38 * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private.
marcozecchini 0:9fca2b23d0ba 39 */
marcozecchini 0:9fca2b23d0ba 40 typedef struct _dspi_master_edma_private_handle
marcozecchini 0:9fca2b23d0ba 41 {
marcozecchini 0:9fca2b23d0ba 42 SPI_Type *base; /*!< DSPI peripheral base address. */
marcozecchini 0:9fca2b23d0ba 43 dspi_master_edma_handle_t *handle; /*!< dspi_master_edma_handle_t handle */
marcozecchini 0:9fca2b23d0ba 44 } dspi_master_edma_private_handle_t;
marcozecchini 0:9fca2b23d0ba 45
marcozecchini 0:9fca2b23d0ba 46 /*!
marcozecchini 0:9fca2b23d0ba 47 * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private.
marcozecchini 0:9fca2b23d0ba 48 */
marcozecchini 0:9fca2b23d0ba 49 typedef struct _dspi_slave_edma_private_handle
marcozecchini 0:9fca2b23d0ba 50 {
marcozecchini 0:9fca2b23d0ba 51 SPI_Type *base; /*!< DSPI peripheral base address. */
marcozecchini 0:9fca2b23d0ba 52 dspi_slave_edma_handle_t *handle; /*!< dspi_master_edma_handle_t handle */
marcozecchini 0:9fca2b23d0ba 53 } dspi_slave_edma_private_handle_t;
marcozecchini 0:9fca2b23d0ba 54
marcozecchini 0:9fca2b23d0ba 55 /***********************************************************************************************************************
marcozecchini 0:9fca2b23d0ba 56 * Prototypes
marcozecchini 0:9fca2b23d0ba 57 ***********************************************************************************************************************/
marcozecchini 0:9fca2b23d0ba 58 /*!
marcozecchini 0:9fca2b23d0ba 59 * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA.
marcozecchini 0:9fca2b23d0ba 60 * This is not a public API.
marcozecchini 0:9fca2b23d0ba 61 */
marcozecchini 0:9fca2b23d0ba 62 static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle,
marcozecchini 0:9fca2b23d0ba 63 void *g_dspiEdmaPrivateHandle,
marcozecchini 0:9fca2b23d0ba 64 bool transferDone,
marcozecchini 0:9fca2b23d0ba 65 uint32_t tcds);
marcozecchini 0:9fca2b23d0ba 66
marcozecchini 0:9fca2b23d0ba 67 /*!
marcozecchini 0:9fca2b23d0ba 68 * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA.
marcozecchini 0:9fca2b23d0ba 69 * This is not a public API.
marcozecchini 0:9fca2b23d0ba 70 */
marcozecchini 0:9fca2b23d0ba 71 static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle,
marcozecchini 0:9fca2b23d0ba 72 void *g_dspiEdmaPrivateHandle,
marcozecchini 0:9fca2b23d0ba 73 bool transferDone,
marcozecchini 0:9fca2b23d0ba 74 uint32_t tcds);
marcozecchini 0:9fca2b23d0ba 75 /*!
marcozecchini 0:9fca2b23d0ba 76 * @brief Get instance number for DSPI module.
marcozecchini 0:9fca2b23d0ba 77 *
marcozecchini 0:9fca2b23d0ba 78 * This is not a public API and it's extern from fsl_dspi.c.
marcozecchini 0:9fca2b23d0ba 79 *
marcozecchini 0:9fca2b23d0ba 80 * @param base DSPI peripheral base address
marcozecchini 0:9fca2b23d0ba 81 */
marcozecchini 0:9fca2b23d0ba 82 extern uint32_t DSPI_GetInstance(SPI_Type *base);
marcozecchini 0:9fca2b23d0ba 83
marcozecchini 0:9fca2b23d0ba 84 /***********************************************************************************************************************
marcozecchini 0:9fca2b23d0ba 85 * Variables
marcozecchini 0:9fca2b23d0ba 86 ***********************************************************************************************************************/
marcozecchini 0:9fca2b23d0ba 87
marcozecchini 0:9fca2b23d0ba 88 /*! @brief Pointers to dspi edma handles for each instance. */
marcozecchini 0:9fca2b23d0ba 89 static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT];
marcozecchini 0:9fca2b23d0ba 90 static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT];
marcozecchini 0:9fca2b23d0ba 91
marcozecchini 0:9fca2b23d0ba 92 /*! @brief Global variable for dummy data value setting. */
marcozecchini 0:9fca2b23d0ba 93 extern volatile uint8_t s_dummyData[];
marcozecchini 0:9fca2b23d0ba 94 /***********************************************************************************************************************
marcozecchini 0:9fca2b23d0ba 95 * Code
marcozecchini 0:9fca2b23d0ba 96 ***********************************************************************************************************************/
marcozecchini 0:9fca2b23d0ba 97
marcozecchini 0:9fca2b23d0ba 98 void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base,
marcozecchini 0:9fca2b23d0ba 99 dspi_master_edma_handle_t *handle,
marcozecchini 0:9fca2b23d0ba 100 dspi_master_edma_transfer_callback_t callback,
marcozecchini 0:9fca2b23d0ba 101 void *userData,
marcozecchini 0:9fca2b23d0ba 102 edma_handle_t *edmaRxRegToRxDataHandle,
marcozecchini 0:9fca2b23d0ba 103 edma_handle_t *edmaTxDataToIntermediaryHandle,
marcozecchini 0:9fca2b23d0ba 104 edma_handle_t *edmaIntermediaryToTxRegHandle)
marcozecchini 0:9fca2b23d0ba 105 {
marcozecchini 0:9fca2b23d0ba 106 assert(handle);
marcozecchini 0:9fca2b23d0ba 107 assert(edmaRxRegToRxDataHandle);
marcozecchini 0:9fca2b23d0ba 108 #if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET))
marcozecchini 0:9fca2b23d0ba 109 assert(edmaTxDataToIntermediaryHandle);
marcozecchini 0:9fca2b23d0ba 110 #endif
marcozecchini 0:9fca2b23d0ba 111 assert(edmaIntermediaryToTxRegHandle);
marcozecchini 0:9fca2b23d0ba 112
marcozecchini 0:9fca2b23d0ba 113 /* Zero the handle. */
marcozecchini 0:9fca2b23d0ba 114 memset(handle, 0, sizeof(*handle));
marcozecchini 0:9fca2b23d0ba 115
marcozecchini 0:9fca2b23d0ba 116 uint32_t instance = DSPI_GetInstance(base);
marcozecchini 0:9fca2b23d0ba 117
marcozecchini 0:9fca2b23d0ba 118 s_dspiMasterEdmaPrivateHandle[instance].base = base;
marcozecchini 0:9fca2b23d0ba 119 s_dspiMasterEdmaPrivateHandle[instance].handle = handle;
marcozecchini 0:9fca2b23d0ba 120
marcozecchini 0:9fca2b23d0ba 121 handle->callback = callback;
marcozecchini 0:9fca2b23d0ba 122 handle->userData = userData;
marcozecchini 0:9fca2b23d0ba 123
marcozecchini 0:9fca2b23d0ba 124 handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
marcozecchini 0:9fca2b23d0ba 125 handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle;
marcozecchini 0:9fca2b23d0ba 126 handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle;
marcozecchini 0:9fca2b23d0ba 127 }
marcozecchini 0:9fca2b23d0ba 128
marcozecchini 0:9fca2b23d0ba 129 status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer)
marcozecchini 0:9fca2b23d0ba 130 {
marcozecchini 0:9fca2b23d0ba 131 assert(handle);
marcozecchini 0:9fca2b23d0ba 132 assert(transfer);
marcozecchini 0:9fca2b23d0ba 133
marcozecchini 0:9fca2b23d0ba 134 /* If the transfer count is zero, then return immediately.*/
marcozecchini 0:9fca2b23d0ba 135 if (transfer->dataSize == 0)
marcozecchini 0:9fca2b23d0ba 136 {
marcozecchini 0:9fca2b23d0ba 137 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 138 }
marcozecchini 0:9fca2b23d0ba 139
marcozecchini 0:9fca2b23d0ba 140 /* If both send buffer and receive buffer is null */
marcozecchini 0:9fca2b23d0ba 141 if ((!(transfer->txData)) && (!(transfer->rxData)))
marcozecchini 0:9fca2b23d0ba 142 {
marcozecchini 0:9fca2b23d0ba 143 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 144 }
marcozecchini 0:9fca2b23d0ba 145
marcozecchini 0:9fca2b23d0ba 146 /* Check that we're not busy.*/
marcozecchini 0:9fca2b23d0ba 147 if (handle->state == kDSPI_Busy)
marcozecchini 0:9fca2b23d0ba 148 {
marcozecchini 0:9fca2b23d0ba 149 return kStatus_DSPI_Busy;
marcozecchini 0:9fca2b23d0ba 150 }
marcozecchini 0:9fca2b23d0ba 151
marcozecchini 0:9fca2b23d0ba 152 handle->state = kDSPI_Busy;
marcozecchini 0:9fca2b23d0ba 153
marcozecchini 0:9fca2b23d0ba 154 uint32_t instance = DSPI_GetInstance(base);
marcozecchini 0:9fca2b23d0ba 155 uint16_t wordToSend = 0;
marcozecchini 0:9fca2b23d0ba 156 uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)];
marcozecchini 0:9fca2b23d0ba 157 uint8_t dataAlreadyFed = 0;
marcozecchini 0:9fca2b23d0ba 158 uint8_t dataFedMax = 2;
marcozecchini 0:9fca2b23d0ba 159
marcozecchini 0:9fca2b23d0ba 160 uint32_t rxAddr = DSPI_GetRxRegisterAddress(base);
marcozecchini 0:9fca2b23d0ba 161 uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base);
marcozecchini 0:9fca2b23d0ba 162
marcozecchini 0:9fca2b23d0ba 163 edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU));
marcozecchini 0:9fca2b23d0ba 164
marcozecchini 0:9fca2b23d0ba 165 edma_transfer_config_t transferConfigA;
marcozecchini 0:9fca2b23d0ba 166 edma_transfer_config_t transferConfigB;
marcozecchini 0:9fca2b23d0ba 167
marcozecchini 0:9fca2b23d0ba 168 handle->txBuffIfNull = ((uint32_t)dummyData << 8) | dummyData;
marcozecchini 0:9fca2b23d0ba 169
marcozecchini 0:9fca2b23d0ba 170 dspi_command_data_config_t commandStruct;
marcozecchini 0:9fca2b23d0ba 171 DSPI_StopTransfer(base);
marcozecchini 0:9fca2b23d0ba 172 DSPI_FlushFifo(base, true, true);
marcozecchini 0:9fca2b23d0ba 173 DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag);
marcozecchini 0:9fca2b23d0ba 174
marcozecchini 0:9fca2b23d0ba 175 commandStruct.whichPcs =
marcozecchini 0:9fca2b23d0ba 176 (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
marcozecchini 0:9fca2b23d0ba 177 commandStruct.isEndOfQueue = false;
marcozecchini 0:9fca2b23d0ba 178 commandStruct.clearTransferCount = false;
marcozecchini 0:9fca2b23d0ba 179 commandStruct.whichCtar =
marcozecchini 0:9fca2b23d0ba 180 (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
marcozecchini 0:9fca2b23d0ba 181 commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous);
marcozecchini 0:9fca2b23d0ba 182 handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct));
marcozecchini 0:9fca2b23d0ba 183
marcozecchini 0:9fca2b23d0ba 184 commandStruct.isEndOfQueue = true;
marcozecchini 0:9fca2b23d0ba 185 commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer);
marcozecchini 0:9fca2b23d0ba 186 handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
marcozecchini 0:9fca2b23d0ba 187
marcozecchini 0:9fca2b23d0ba 188 handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1;
marcozecchini 0:9fca2b23d0ba 189
marcozecchini 0:9fca2b23d0ba 190 if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK))
marcozecchini 0:9fca2b23d0ba 191 {
marcozecchini 0:9fca2b23d0ba 192 handle->fifoSize = 1;
marcozecchini 0:9fca2b23d0ba 193 }
marcozecchini 0:9fca2b23d0ba 194 else
marcozecchini 0:9fca2b23d0ba 195 {
marcozecchini 0:9fca2b23d0ba 196 handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base);
marcozecchini 0:9fca2b23d0ba 197 }
marcozecchini 0:9fca2b23d0ba 198 handle->txData = transfer->txData;
marcozecchini 0:9fca2b23d0ba 199 handle->rxData = transfer->rxData;
marcozecchini 0:9fca2b23d0ba 200 handle->remainingSendByteCount = transfer->dataSize;
marcozecchini 0:9fca2b23d0ba 201 handle->remainingReceiveByteCount = transfer->dataSize;
marcozecchini 0:9fca2b23d0ba 202 handle->totalByteCount = transfer->dataSize;
marcozecchini 0:9fca2b23d0ba 203
marcozecchini 0:9fca2b23d0ba 204 /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer
marcozecchini 0:9fca2b23d0ba 205 * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame
marcozecchini 0:9fca2b23d0ba 206 */
marcozecchini 0:9fca2b23d0ba 207 uint32_t limited_size = 0;
marcozecchini 0:9fca2b23d0ba 208 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 209 {
marcozecchini 0:9fca2b23d0ba 210 limited_size = 32767u;
marcozecchini 0:9fca2b23d0ba 211 }
marcozecchini 0:9fca2b23d0ba 212 else
marcozecchini 0:9fca2b23d0ba 213 {
marcozecchini 0:9fca2b23d0ba 214 limited_size = 511u;
marcozecchini 0:9fca2b23d0ba 215 }
marcozecchini 0:9fca2b23d0ba 216
marcozecchini 0:9fca2b23d0ba 217 if (handle->bitsPerFrame > 8)
marcozecchini 0:9fca2b23d0ba 218 {
marcozecchini 0:9fca2b23d0ba 219 if (transfer->dataSize > (limited_size << 1u))
marcozecchini 0:9fca2b23d0ba 220 {
marcozecchini 0:9fca2b23d0ba 221 handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 222 return kStatus_DSPI_OutOfRange;
marcozecchini 0:9fca2b23d0ba 223 }
marcozecchini 0:9fca2b23d0ba 224 }
marcozecchini 0:9fca2b23d0ba 225 else
marcozecchini 0:9fca2b23d0ba 226 {
marcozecchini 0:9fca2b23d0ba 227 if (transfer->dataSize > limited_size)
marcozecchini 0:9fca2b23d0ba 228 {
marcozecchini 0:9fca2b23d0ba 229 handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 230 return kStatus_DSPI_OutOfRange;
marcozecchini 0:9fca2b23d0ba 231 }
marcozecchini 0:9fca2b23d0ba 232 }
marcozecchini 0:9fca2b23d0ba 233
marcozecchini 0:9fca2b23d0ba 234 /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */
marcozecchini 0:9fca2b23d0ba 235 if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1))
marcozecchini 0:9fca2b23d0ba 236 {
marcozecchini 0:9fca2b23d0ba 237 handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 238 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 239 }
marcozecchini 0:9fca2b23d0ba 240
marcozecchini 0:9fca2b23d0ba 241 DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 242
marcozecchini 0:9fca2b23d0ba 243 EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback,
marcozecchini 0:9fca2b23d0ba 244 &s_dspiMasterEdmaPrivateHandle[instance]);
marcozecchini 0:9fca2b23d0ba 245
marcozecchini 0:9fca2b23d0ba 246 /*
marcozecchini 0:9fca2b23d0ba 247 (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C.
marcozecchini 0:9fca2b23d0ba 248 channel_A minor link to channel_B , channel_B minor link to channel_C.
marcozecchini 0:9fca2b23d0ba 249
marcozecchini 0:9fca2b23d0ba 250 Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer.
marcozecchini 0:9fca2b23d0ba 251 channel_A:SPI_POPR to rxData,
marcozecchini 0:9fca2b23d0ba 252 channel_B:next txData to handle->command (low 16 bits),
marcozecchini 0:9fca2b23d0ba 253 channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data
marcozecchini 0:9fca2b23d0ba 254 (handle->lastCommand to SPI_PUSHR).
marcozecchini 0:9fca2b23d0ba 255
marcozecchini 0:9fca2b23d0ba 256 (2)For DSPI instances with separate RX and TX DMA requests:
marcozecchini 0:9fca2b23d0ba 257 Rx DMA request -> channel_A
marcozecchini 0:9fca2b23d0ba 258 Tx DMA request -> channel_C -> channel_B .
marcozecchini 0:9fca2b23d0ba 259 channel_C major link to channel_B.
marcozecchini 0:9fca2b23d0ba 260 So need prepare the first data in "intermediary" before the DMA
marcozecchini 0:9fca2b23d0ba 261 transfer and then channel_B is used to prepare the next data to "intermediary"
marcozecchini 0:9fca2b23d0ba 262
marcozecchini 0:9fca2b23d0ba 263 channel_A:SPI_POPR to rxData,
marcozecchini 0:9fca2b23d0ba 264 channel_C: handle->command (32 bits) to SPI_PUSHR,
marcozecchini 0:9fca2b23d0ba 265 channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data
marcozecchini 0:9fca2b23d0ba 266 (handle->lastCommand to handle->Command).
marcozecchini 0:9fca2b23d0ba 267 */
marcozecchini 0:9fca2b23d0ba 268
marcozecchini 0:9fca2b23d0ba 269 /*If dspi has separate dma request , prepare the first data in "intermediary" .
marcozecchini 0:9fca2b23d0ba 270 else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/
marcozecchini 0:9fca2b23d0ba 271 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 272 {
marcozecchini 0:9fca2b23d0ba 273 /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to
marcozecchini 0:9fca2b23d0ba 274 * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel
marcozecchini 0:9fca2b23d0ba 275 */
marcozecchini 0:9fca2b23d0ba 276
marcozecchini 0:9fca2b23d0ba 277 /*Prepare the firt data*/
marcozecchini 0:9fca2b23d0ba 278 if (handle->bitsPerFrame > 8)
marcozecchini 0:9fca2b23d0ba 279 {
marcozecchini 0:9fca2b23d0ba 280 /* If it's the last word */
marcozecchini 0:9fca2b23d0ba 281 if (handle->remainingSendByteCount <= 2)
marcozecchini 0:9fca2b23d0ba 282 {
marcozecchini 0:9fca2b23d0ba 283 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 284 {
marcozecchini 0:9fca2b23d0ba 285 wordToSend = *(handle->txData);
marcozecchini 0:9fca2b23d0ba 286 ++handle->txData; /* increment to next data byte */
marcozecchini 0:9fca2b23d0ba 287 wordToSend |= (unsigned)(*(handle->txData)) << 8U;
marcozecchini 0:9fca2b23d0ba 288 }
marcozecchini 0:9fca2b23d0ba 289 else
marcozecchini 0:9fca2b23d0ba 290 {
marcozecchini 0:9fca2b23d0ba 291 wordToSend = ((uint32_t)dummyData << 8) | dummyData;
marcozecchini 0:9fca2b23d0ba 292 }
marcozecchini 0:9fca2b23d0ba 293 handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 294 handle->command = handle->lastCommand;
marcozecchini 0:9fca2b23d0ba 295 }
marcozecchini 0:9fca2b23d0ba 296 else /* For all words except the last word , frame > 8bits */
marcozecchini 0:9fca2b23d0ba 297 {
marcozecchini 0:9fca2b23d0ba 298 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 299 {
marcozecchini 0:9fca2b23d0ba 300 wordToSend = *(handle->txData);
marcozecchini 0:9fca2b23d0ba 301 ++handle->txData; /* increment to next data byte */
marcozecchini 0:9fca2b23d0ba 302 wordToSend |= (unsigned)(*(handle->txData)) << 8U;
marcozecchini 0:9fca2b23d0ba 303 ++handle->txData; /* increment to next data byte */
marcozecchini 0:9fca2b23d0ba 304 }
marcozecchini 0:9fca2b23d0ba 305 else
marcozecchini 0:9fca2b23d0ba 306 {
marcozecchini 0:9fca2b23d0ba 307 wordToSend = ((uint32_t)dummyData << 8) | dummyData;
marcozecchini 0:9fca2b23d0ba 308 }
marcozecchini 0:9fca2b23d0ba 309 handle->command = (handle->command & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 310 }
marcozecchini 0:9fca2b23d0ba 311 }
marcozecchini 0:9fca2b23d0ba 312 else /* Optimized for bits/frame less than or equal to one byte. */
marcozecchini 0:9fca2b23d0ba 313 {
marcozecchini 0:9fca2b23d0ba 314 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 315 {
marcozecchini 0:9fca2b23d0ba 316 wordToSend = *(handle->txData);
marcozecchini 0:9fca2b23d0ba 317 ++handle->txData; /* increment to next data word*/
marcozecchini 0:9fca2b23d0ba 318 }
marcozecchini 0:9fca2b23d0ba 319 else
marcozecchini 0:9fca2b23d0ba 320 {
marcozecchini 0:9fca2b23d0ba 321 wordToSend = dummyData;
marcozecchini 0:9fca2b23d0ba 322 }
marcozecchini 0:9fca2b23d0ba 323
marcozecchini 0:9fca2b23d0ba 324 if (handle->remainingSendByteCount == 1)
marcozecchini 0:9fca2b23d0ba 325 {
marcozecchini 0:9fca2b23d0ba 326 handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 327 handle->command = handle->lastCommand;
marcozecchini 0:9fca2b23d0ba 328 }
marcozecchini 0:9fca2b23d0ba 329 else
marcozecchini 0:9fca2b23d0ba 330 {
marcozecchini 0:9fca2b23d0ba 331 handle->command = (handle->command & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 332 }
marcozecchini 0:9fca2b23d0ba 333 }
marcozecchini 0:9fca2b23d0ba 334 }
marcozecchini 0:9fca2b23d0ba 335
marcozecchini 0:9fca2b23d0ba 336 else /*dspi has shared dma request*/
marcozecchini 0:9fca2b23d0ba 337 {
marcozecchini 0:9fca2b23d0ba 338 /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to
marcozecchini 0:9fca2b23d0ba 339 * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel.
marcozecchini 0:9fca2b23d0ba 340 */
marcozecchini 0:9fca2b23d0ba 341
marcozecchini 0:9fca2b23d0ba 342 /* If bits/frame is greater than one byte */
marcozecchini 0:9fca2b23d0ba 343 if (handle->bitsPerFrame > 8)
marcozecchini 0:9fca2b23d0ba 344 {
marcozecchini 0:9fca2b23d0ba 345 while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
marcozecchini 0:9fca2b23d0ba 346 {
marcozecchini 0:9fca2b23d0ba 347 if (handle->remainingSendByteCount <= 2)
marcozecchini 0:9fca2b23d0ba 348 {
marcozecchini 0:9fca2b23d0ba 349 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 350 {
marcozecchini 0:9fca2b23d0ba 351 wordToSend = *(handle->txData);
marcozecchini 0:9fca2b23d0ba 352 ++handle->txData;
marcozecchini 0:9fca2b23d0ba 353 wordToSend |= (unsigned)(*(handle->txData)) << 8U;
marcozecchini 0:9fca2b23d0ba 354 }
marcozecchini 0:9fca2b23d0ba 355 else
marcozecchini 0:9fca2b23d0ba 356 {
marcozecchini 0:9fca2b23d0ba 357 wordToSend = ((uint32_t)dummyData << 8) | dummyData;
marcozecchini 0:9fca2b23d0ba 358 }
marcozecchini 0:9fca2b23d0ba 359 handle->remainingSendByteCount = 0;
marcozecchini 0:9fca2b23d0ba 360 base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 361 }
marcozecchini 0:9fca2b23d0ba 362 /* For all words except the last word */
marcozecchini 0:9fca2b23d0ba 363 else
marcozecchini 0:9fca2b23d0ba 364 {
marcozecchini 0:9fca2b23d0ba 365 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 366 {
marcozecchini 0:9fca2b23d0ba 367 wordToSend = *(handle->txData);
marcozecchini 0:9fca2b23d0ba 368 ++handle->txData;
marcozecchini 0:9fca2b23d0ba 369 wordToSend |= (unsigned)(*(handle->txData)) << 8U;
marcozecchini 0:9fca2b23d0ba 370 ++handle->txData;
marcozecchini 0:9fca2b23d0ba 371 }
marcozecchini 0:9fca2b23d0ba 372 else
marcozecchini 0:9fca2b23d0ba 373 {
marcozecchini 0:9fca2b23d0ba 374 wordToSend = ((uint32_t)dummyData << 8) | dummyData;
marcozecchini 0:9fca2b23d0ba 375 }
marcozecchini 0:9fca2b23d0ba 376 handle->remainingSendByteCount -= 2;
marcozecchini 0:9fca2b23d0ba 377 base->PUSHR = (handle->command & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 378 }
marcozecchini 0:9fca2b23d0ba 379
marcozecchini 0:9fca2b23d0ba 380 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
marcozecchini 0:9fca2b23d0ba 381 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
marcozecchini 0:9fca2b23d0ba 382
marcozecchini 0:9fca2b23d0ba 383 dataAlreadyFed += 2;
marcozecchini 0:9fca2b23d0ba 384
marcozecchini 0:9fca2b23d0ba 385 /* exit loop if send count is zero, else update local variables for next loop */
marcozecchini 0:9fca2b23d0ba 386 if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2)))
marcozecchini 0:9fca2b23d0ba 387 {
marcozecchini 0:9fca2b23d0ba 388 break;
marcozecchini 0:9fca2b23d0ba 389 }
marcozecchini 0:9fca2b23d0ba 390 } /* End of TX FIFO fill while loop */
marcozecchini 0:9fca2b23d0ba 391 }
marcozecchini 0:9fca2b23d0ba 392 else /* Optimized for bits/frame less than or equal to one byte. */
marcozecchini 0:9fca2b23d0ba 393 {
marcozecchini 0:9fca2b23d0ba 394 while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
marcozecchini 0:9fca2b23d0ba 395 {
marcozecchini 0:9fca2b23d0ba 396 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 397 {
marcozecchini 0:9fca2b23d0ba 398 wordToSend = *(handle->txData);
marcozecchini 0:9fca2b23d0ba 399 ++handle->txData;
marcozecchini 0:9fca2b23d0ba 400 }
marcozecchini 0:9fca2b23d0ba 401 else
marcozecchini 0:9fca2b23d0ba 402 {
marcozecchini 0:9fca2b23d0ba 403 wordToSend = dummyData;
marcozecchini 0:9fca2b23d0ba 404 }
marcozecchini 0:9fca2b23d0ba 405
marcozecchini 0:9fca2b23d0ba 406 if (handle->remainingSendByteCount == 1)
marcozecchini 0:9fca2b23d0ba 407 {
marcozecchini 0:9fca2b23d0ba 408 base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 409 }
marcozecchini 0:9fca2b23d0ba 410 else
marcozecchini 0:9fca2b23d0ba 411 {
marcozecchini 0:9fca2b23d0ba 412 base->PUSHR = (handle->command & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 413 }
marcozecchini 0:9fca2b23d0ba 414
marcozecchini 0:9fca2b23d0ba 415 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
marcozecchini 0:9fca2b23d0ba 416 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
marcozecchini 0:9fca2b23d0ba 417
marcozecchini 0:9fca2b23d0ba 418 --handle->remainingSendByteCount;
marcozecchini 0:9fca2b23d0ba 419
marcozecchini 0:9fca2b23d0ba 420 dataAlreadyFed++;
marcozecchini 0:9fca2b23d0ba 421
marcozecchini 0:9fca2b23d0ba 422 /* exit loop if send count is zero, else update local variables for next loop */
marcozecchini 0:9fca2b23d0ba 423 if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax))
marcozecchini 0:9fca2b23d0ba 424 {
marcozecchini 0:9fca2b23d0ba 425 break;
marcozecchini 0:9fca2b23d0ba 426 }
marcozecchini 0:9fca2b23d0ba 427 } /* End of TX FIFO fill while loop */
marcozecchini 0:9fca2b23d0ba 428 }
marcozecchini 0:9fca2b23d0ba 429 }
marcozecchini 0:9fca2b23d0ba 430
marcozecchini 0:9fca2b23d0ba 431 /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/
marcozecchini 0:9fca2b23d0ba 432 EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
marcozecchini 0:9fca2b23d0ba 433
marcozecchini 0:9fca2b23d0ba 434 transferConfigA.srcAddr = (uint32_t)rxAddr;
marcozecchini 0:9fca2b23d0ba 435 transferConfigA.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 436
marcozecchini 0:9fca2b23d0ba 437 if (handle->rxData)
marcozecchini 0:9fca2b23d0ba 438 {
marcozecchini 0:9fca2b23d0ba 439 transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]);
marcozecchini 0:9fca2b23d0ba 440 transferConfigA.destOffset = 1;
marcozecchini 0:9fca2b23d0ba 441 }
marcozecchini 0:9fca2b23d0ba 442 else
marcozecchini 0:9fca2b23d0ba 443 {
marcozecchini 0:9fca2b23d0ba 444 transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull);
marcozecchini 0:9fca2b23d0ba 445 transferConfigA.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 446 }
marcozecchini 0:9fca2b23d0ba 447
marcozecchini 0:9fca2b23d0ba 448 transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 449
marcozecchini 0:9fca2b23d0ba 450 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 451 {
marcozecchini 0:9fca2b23d0ba 452 transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 453 transferConfigA.minorLoopBytes = 1;
marcozecchini 0:9fca2b23d0ba 454 transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount;
marcozecchini 0:9fca2b23d0ba 455 }
marcozecchini 0:9fca2b23d0ba 456 else
marcozecchini 0:9fca2b23d0ba 457 {
marcozecchini 0:9fca2b23d0ba 458 transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes;
marcozecchini 0:9fca2b23d0ba 459 transferConfigA.minorLoopBytes = 2;
marcozecchini 0:9fca2b23d0ba 460 transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2;
marcozecchini 0:9fca2b23d0ba 461 }
marcozecchini 0:9fca2b23d0ba 462
marcozecchini 0:9fca2b23d0ba 463 /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
marcozecchini 0:9fca2b23d0ba 464 handle->nbytes = transferConfigA.minorLoopBytes;
marcozecchini 0:9fca2b23d0ba 465
marcozecchini 0:9fca2b23d0ba 466 EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 467 &transferConfigA, NULL);
marcozecchini 0:9fca2b23d0ba 468 EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 469 kEDMA_MajorInterruptEnable);
marcozecchini 0:9fca2b23d0ba 470
marcozecchini 0:9fca2b23d0ba 471 /*Calculate the last data : handle->lastCommand*/
marcozecchini 0:9fca2b23d0ba 472 if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) ||
marcozecchini 0:9fca2b23d0ba 473 ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) ||
marcozecchini 0:9fca2b23d0ba 474 ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) &&
marcozecchini 0:9fca2b23d0ba 475 (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))))
marcozecchini 0:9fca2b23d0ba 476 {
marcozecchini 0:9fca2b23d0ba 477 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 478 {
marcozecchini 0:9fca2b23d0ba 479 uint32_t bufferIndex = 0;
marcozecchini 0:9fca2b23d0ba 480
marcozecchini 0:9fca2b23d0ba 481 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 482 {
marcozecchini 0:9fca2b23d0ba 483 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 484 {
marcozecchini 0:9fca2b23d0ba 485 bufferIndex = handle->remainingSendByteCount - 1;
marcozecchini 0:9fca2b23d0ba 486 }
marcozecchini 0:9fca2b23d0ba 487 else
marcozecchini 0:9fca2b23d0ba 488 {
marcozecchini 0:9fca2b23d0ba 489 bufferIndex = handle->remainingSendByteCount - 2;
marcozecchini 0:9fca2b23d0ba 490 }
marcozecchini 0:9fca2b23d0ba 491 }
marcozecchini 0:9fca2b23d0ba 492 else
marcozecchini 0:9fca2b23d0ba 493 {
marcozecchini 0:9fca2b23d0ba 494 bufferIndex = handle->remainingSendByteCount;
marcozecchini 0:9fca2b23d0ba 495 }
marcozecchini 0:9fca2b23d0ba 496
marcozecchini 0:9fca2b23d0ba 497 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 498 {
marcozecchini 0:9fca2b23d0ba 499 handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1];
marcozecchini 0:9fca2b23d0ba 500 }
marcozecchini 0:9fca2b23d0ba 501 else
marcozecchini 0:9fca2b23d0ba 502 {
marcozecchini 0:9fca2b23d0ba 503 handle->lastCommand = (handle->lastCommand & 0xffff0000U) |
marcozecchini 0:9fca2b23d0ba 504 ((uint32_t)handle->txData[bufferIndex - 1] << 8) |
marcozecchini 0:9fca2b23d0ba 505 handle->txData[bufferIndex - 2];
marcozecchini 0:9fca2b23d0ba 506 }
marcozecchini 0:9fca2b23d0ba 507 }
marcozecchini 0:9fca2b23d0ba 508 else
marcozecchini 0:9fca2b23d0ba 509 {
marcozecchini 0:9fca2b23d0ba 510 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 511 {
marcozecchini 0:9fca2b23d0ba 512 wordToSend = dummyData;
marcozecchini 0:9fca2b23d0ba 513 }
marcozecchini 0:9fca2b23d0ba 514 else
marcozecchini 0:9fca2b23d0ba 515 {
marcozecchini 0:9fca2b23d0ba 516 wordToSend = ((uint32_t)dummyData << 8) | dummyData;
marcozecchini 0:9fca2b23d0ba 517 }
marcozecchini 0:9fca2b23d0ba 518 handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
marcozecchini 0:9fca2b23d0ba 519 }
marcozecchini 0:9fca2b23d0ba 520 }
marcozecchini 0:9fca2b23d0ba 521
marcozecchini 0:9fca2b23d0ba 522 /* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO,
marcozecchini 0:9fca2b23d0ba 523 * allowing a single write to the command word followed by multiple writes to the transmit word.
marcozecchini 0:9fca2b23d0ba 524 * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the
marcozecchini 0:9fca2b23d0ba 525 * transmit word into a 32-bit write that pushes both the command word and transmit word into
marcozecchini 0:9fca2b23d0ba 526 * the TX FIFO (PUSH TX FIFO Register In Master Mode)
marcozecchini 0:9fca2b23d0ba 527 * So, if this feature is supported, we can use use one channel to carry the receive data from
marcozecchini 0:9fca2b23d0ba 528 * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer
marcozecchini 0:9fca2b23d0ba 529 * to transmit register,and use the scatter/gather function to prepare the last data.
marcozecchini 0:9fca2b23d0ba 530 * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data.
marcozecchini 0:9fca2b23d0ba 531 */
marcozecchini 0:9fca2b23d0ba 532 #if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET
marcozecchini 0:9fca2b23d0ba 533 /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data
marcozecchini 0:9fca2b23d0ba 534 * (handle->lastCommand) to PUSHR register.
marcozecchini 0:9fca2b23d0ba 535 */
marcozecchini 0:9fca2b23d0ba 536
marcozecchini 0:9fca2b23d0ba 537 EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel);
marcozecchini 0:9fca2b23d0ba 538
marcozecchini 0:9fca2b23d0ba 539 if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) ||
marcozecchini 0:9fca2b23d0ba 540 ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))))
marcozecchini 0:9fca2b23d0ba 541 {
marcozecchini 0:9fca2b23d0ba 542 transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand);
marcozecchini 0:9fca2b23d0ba 543 transferConfigB.destAddr = (uint32_t)txAddr;
marcozecchini 0:9fca2b23d0ba 544 transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes;
marcozecchini 0:9fca2b23d0ba 545 transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes;
marcozecchini 0:9fca2b23d0ba 546 transferConfigB.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 547 transferConfigB.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 548 transferConfigB.minorLoopBytes = 4;
marcozecchini 0:9fca2b23d0ba 549 transferConfigB.majorLoopCounts = 1;
marcozecchini 0:9fca2b23d0ba 550
marcozecchini 0:9fca2b23d0ba 551 EDMA_TcdReset(softwareTCD);
marcozecchini 0:9fca2b23d0ba 552 EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL);
marcozecchini 0:9fca2b23d0ba 553 }
marcozecchini 0:9fca2b23d0ba 554
marcozecchini 0:9fca2b23d0ba 555 /*User_Send_Buffer(txData) to PUSHR register. */
marcozecchini 0:9fca2b23d0ba 556 if (((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) ||
marcozecchini 0:9fca2b23d0ba 557 ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8)))
marcozecchini 0:9fca2b23d0ba 558 {
marcozecchini 0:9fca2b23d0ba 559 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 560 {
marcozecchini 0:9fca2b23d0ba 561 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 562 {
marcozecchini 0:9fca2b23d0ba 563 /* For DSPI with separate RX and TX DMA requests, one frame data has been carry
marcozecchini 0:9fca2b23d0ba 564 * to handle->command, so need to reduce the pointer of txData.
marcozecchini 0:9fca2b23d0ba 565 */
marcozecchini 0:9fca2b23d0ba 566 transferConfigB.srcAddr =
marcozecchini 0:9fca2b23d0ba 567 (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8) ? (1U) : (2U)));
marcozecchini 0:9fca2b23d0ba 568 transferConfigB.srcOffset = 1;
marcozecchini 0:9fca2b23d0ba 569 }
marcozecchini 0:9fca2b23d0ba 570 else
marcozecchini 0:9fca2b23d0ba 571 {
marcozecchini 0:9fca2b23d0ba 572 /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry
marcozecchini 0:9fca2b23d0ba 573 * to PUSHR register, so no need to change the pointer of txData.
marcozecchini 0:9fca2b23d0ba 574 */
marcozecchini 0:9fca2b23d0ba 575 transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData));
marcozecchini 0:9fca2b23d0ba 576 transferConfigB.srcOffset = 1;
marcozecchini 0:9fca2b23d0ba 577 }
marcozecchini 0:9fca2b23d0ba 578 }
marcozecchini 0:9fca2b23d0ba 579 else
marcozecchini 0:9fca2b23d0ba 580 {
marcozecchini 0:9fca2b23d0ba 581 transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull);
marcozecchini 0:9fca2b23d0ba 582 transferConfigB.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 583 }
marcozecchini 0:9fca2b23d0ba 584
marcozecchini 0:9fca2b23d0ba 585 transferConfigB.destAddr = (uint32_t)txAddr;
marcozecchini 0:9fca2b23d0ba 586 transferConfigB.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 587
marcozecchini 0:9fca2b23d0ba 588 transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 589
marcozecchini 0:9fca2b23d0ba 590 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 591 {
marcozecchini 0:9fca2b23d0ba 592 transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 593 transferConfigB.minorLoopBytes = 1;
marcozecchini 0:9fca2b23d0ba 594
marcozecchini 0:9fca2b23d0ba 595 transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1;
marcozecchini 0:9fca2b23d0ba 596 }
marcozecchini 0:9fca2b23d0ba 597 else
marcozecchini 0:9fca2b23d0ba 598 {
marcozecchini 0:9fca2b23d0ba 599 transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes;
marcozecchini 0:9fca2b23d0ba 600 transferConfigB.minorLoopBytes = 2;
marcozecchini 0:9fca2b23d0ba 601 transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2) - 1;
marcozecchini 0:9fca2b23d0ba 602 }
marcozecchini 0:9fca2b23d0ba 603
marcozecchini 0:9fca2b23d0ba 604 EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 605 handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD);
marcozecchini 0:9fca2b23d0ba 606 }
marcozecchini 0:9fca2b23d0ba 607 /* If only one word to transmit, only carry the lastcommand. */
marcozecchini 0:9fca2b23d0ba 608 else
marcozecchini 0:9fca2b23d0ba 609 {
marcozecchini 0:9fca2b23d0ba 610 EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 611 handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL);
marcozecchini 0:9fca2b23d0ba 612 }
marcozecchini 0:9fca2b23d0ba 613
marcozecchini 0:9fca2b23d0ba 614 /*Start the EDMA channel_A , channel_C. */
marcozecchini 0:9fca2b23d0ba 615 EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
marcozecchini 0:9fca2b23d0ba 616 EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle);
marcozecchini 0:9fca2b23d0ba 617
marcozecchini 0:9fca2b23d0ba 618 /* Set the channel link.
marcozecchini 0:9fca2b23d0ba 619 * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the
marcozecchini 0:9fca2b23d0ba 620 * receive register, and then carry transmit data to PUSHER register.
marcozecchini 0:9fca2b23d0ba 621 * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link.
marcozecchini 0:9fca2b23d0ba 622 */
marcozecchini 0:9fca2b23d0ba 623 if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 624 {
marcozecchini 0:9fca2b23d0ba 625 /*Set channel priority*/
marcozecchini 0:9fca2b23d0ba 626 uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel;
marcozecchini 0:9fca2b23d0ba 627 uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel;
marcozecchini 0:9fca2b23d0ba 628 uint8_t t = 0;
marcozecchini 0:9fca2b23d0ba 629
marcozecchini 0:9fca2b23d0ba 630 if (channelPriorityLow > channelPriorityHigh)
marcozecchini 0:9fca2b23d0ba 631 {
marcozecchini 0:9fca2b23d0ba 632 t = channelPriorityLow;
marcozecchini 0:9fca2b23d0ba 633 channelPriorityLow = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 634 channelPriorityHigh = t;
marcozecchini 0:9fca2b23d0ba 635 }
marcozecchini 0:9fca2b23d0ba 636
marcozecchini 0:9fca2b23d0ba 637 edma_channel_Preemption_config_t preemption_config_t;
marcozecchini 0:9fca2b23d0ba 638 preemption_config_t.enableChannelPreemption = true;
marcozecchini 0:9fca2b23d0ba 639 preemption_config_t.enablePreemptAbility = true;
marcozecchini 0:9fca2b23d0ba 640 preemption_config_t.channelPriority = channelPriorityLow;
marcozecchini 0:9fca2b23d0ba 641
marcozecchini 0:9fca2b23d0ba 642 EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 643 &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 644
marcozecchini 0:9fca2b23d0ba 645 preemption_config_t.channelPriority = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 646 EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 647 handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 648 /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to
marcozecchini 0:9fca2b23d0ba 649 channelC to carry the next data to PUSHER register.(txData to PUSHER) */
marcozecchini 0:9fca2b23d0ba 650 if (handle->remainingSendByteCount > 0)
marcozecchini 0:9fca2b23d0ba 651 {
marcozecchini 0:9fca2b23d0ba 652 EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 653 kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel);
marcozecchini 0:9fca2b23d0ba 654 }
marcozecchini 0:9fca2b23d0ba 655 }
marcozecchini 0:9fca2b23d0ba 656
marcozecchini 0:9fca2b23d0ba 657 DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 658
marcozecchini 0:9fca2b23d0ba 659 /* Setup control info to PUSHER register. */
marcozecchini 0:9fca2b23d0ba 660 *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U);
marcozecchini 0:9fca2b23d0ba 661 #else
marcozecchini 0:9fca2b23d0ba 662
marcozecchini 0:9fca2b23d0ba 663 /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should
marcozecchini 0:9fca2b23d0ba 664 write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the
marcozecchini 0:9fca2b23d0ba 665 SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */
marcozecchini 0:9fca2b23d0ba 666
marcozecchini 0:9fca2b23d0ba 667 EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel);
marcozecchini 0:9fca2b23d0ba 668
marcozecchini 0:9fca2b23d0ba 669 /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data
marcozecchini 0:9fca2b23d0ba 670 * (handle->lastCommand) to handle->Command*/
marcozecchini 0:9fca2b23d0ba 671 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 672 {
marcozecchini 0:9fca2b23d0ba 673 transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand);
marcozecchini 0:9fca2b23d0ba 674 transferConfigB.destAddr = (uint32_t) & (handle->command);
marcozecchini 0:9fca2b23d0ba 675 transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes;
marcozecchini 0:9fca2b23d0ba 676 transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes;
marcozecchini 0:9fca2b23d0ba 677 transferConfigB.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 678 transferConfigB.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 679 transferConfigB.minorLoopBytes = 4;
marcozecchini 0:9fca2b23d0ba 680 transferConfigB.majorLoopCounts = 1;
marcozecchini 0:9fca2b23d0ba 681
marcozecchini 0:9fca2b23d0ba 682 EDMA_TcdReset(softwareTCD);
marcozecchini 0:9fca2b23d0ba 683 EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL);
marcozecchini 0:9fca2b23d0ba 684 }
marcozecchini 0:9fca2b23d0ba 685
marcozecchini 0:9fca2b23d0ba 686 /*User_Send_Buffer(txData) to intermediary(handle->command)*/
marcozecchini 0:9fca2b23d0ba 687 if (((((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) ||
marcozecchini 0:9fca2b23d0ba 688 ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) &&
marcozecchini 0:9fca2b23d0ba 689 (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) ||
marcozecchini 0:9fca2b23d0ba 690 (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))
marcozecchini 0:9fca2b23d0ba 691 {
marcozecchini 0:9fca2b23d0ba 692 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 693 {
marcozecchini 0:9fca2b23d0ba 694 transferConfigB.srcAddr = (uint32_t)(handle->txData);
marcozecchini 0:9fca2b23d0ba 695 transferConfigB.srcOffset = 1;
marcozecchini 0:9fca2b23d0ba 696 }
marcozecchini 0:9fca2b23d0ba 697 else
marcozecchini 0:9fca2b23d0ba 698 {
marcozecchini 0:9fca2b23d0ba 699 transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull);
marcozecchini 0:9fca2b23d0ba 700 transferConfigB.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 701 }
marcozecchini 0:9fca2b23d0ba 702
marcozecchini 0:9fca2b23d0ba 703 transferConfigB.destAddr = (uint32_t)(&handle->command);
marcozecchini 0:9fca2b23d0ba 704 transferConfigB.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 705
marcozecchini 0:9fca2b23d0ba 706 transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 707
marcozecchini 0:9fca2b23d0ba 708 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 709 {
marcozecchini 0:9fca2b23d0ba 710 transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 711 transferConfigB.minorLoopBytes = 1;
marcozecchini 0:9fca2b23d0ba 712
marcozecchini 0:9fca2b23d0ba 713 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 714 {
marcozecchini 0:9fca2b23d0ba 715 transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2;
marcozecchini 0:9fca2b23d0ba 716 }
marcozecchini 0:9fca2b23d0ba 717 else
marcozecchini 0:9fca2b23d0ba 718 {
marcozecchini 0:9fca2b23d0ba 719 /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is
marcozecchini 0:9fca2b23d0ba 720 majorlink , the majorlink would not trigger the channel_C*/
marcozecchini 0:9fca2b23d0ba 721 transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1;
marcozecchini 0:9fca2b23d0ba 722 }
marcozecchini 0:9fca2b23d0ba 723 }
marcozecchini 0:9fca2b23d0ba 724 else
marcozecchini 0:9fca2b23d0ba 725 {
marcozecchini 0:9fca2b23d0ba 726 transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes;
marcozecchini 0:9fca2b23d0ba 727 transferConfigB.minorLoopBytes = 2;
marcozecchini 0:9fca2b23d0ba 728 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 729 {
marcozecchini 0:9fca2b23d0ba 730 transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 2;
marcozecchini 0:9fca2b23d0ba 731 }
marcozecchini 0:9fca2b23d0ba 732 else
marcozecchini 0:9fca2b23d0ba 733 {
marcozecchini 0:9fca2b23d0ba 734 /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is
marcozecchini 0:9fca2b23d0ba 735 * majorlink*/
marcozecchini 0:9fca2b23d0ba 736 transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1;
marcozecchini 0:9fca2b23d0ba 737 }
marcozecchini 0:9fca2b23d0ba 738 }
marcozecchini 0:9fca2b23d0ba 739
marcozecchini 0:9fca2b23d0ba 740 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 741 {
marcozecchini 0:9fca2b23d0ba 742 EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
marcozecchini 0:9fca2b23d0ba 743 handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, softwareTCD);
marcozecchini 0:9fca2b23d0ba 744 EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 745 handle->edmaIntermediaryToTxRegHandle->channel, false);
marcozecchini 0:9fca2b23d0ba 746 }
marcozecchini 0:9fca2b23d0ba 747 else
marcozecchini 0:9fca2b23d0ba 748 {
marcozecchini 0:9fca2b23d0ba 749 EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
marcozecchini 0:9fca2b23d0ba 750 handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL);
marcozecchini 0:9fca2b23d0ba 751 }
marcozecchini 0:9fca2b23d0ba 752 }
marcozecchini 0:9fca2b23d0ba 753 else
marcozecchini 0:9fca2b23d0ba 754 {
marcozecchini 0:9fca2b23d0ba 755 EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
marcozecchini 0:9fca2b23d0ba 756 handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL);
marcozecchini 0:9fca2b23d0ba 757 }
marcozecchini 0:9fca2b23d0ba 758
marcozecchini 0:9fca2b23d0ba 759 /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to
marcozecchini 0:9fca2b23d0ba 760 handle the last data */
marcozecchini 0:9fca2b23d0ba 761
marcozecchini 0:9fca2b23d0ba 762 edma_transfer_config_t transferConfigC;
marcozecchini 0:9fca2b23d0ba 763 EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel);
marcozecchini 0:9fca2b23d0ba 764
marcozecchini 0:9fca2b23d0ba 765 /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data
marcozecchini 0:9fca2b23d0ba 766 * (handle->lastCommand) to SPI_PUSHR*/
marcozecchini 0:9fca2b23d0ba 767 if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0)))
marcozecchini 0:9fca2b23d0ba 768 {
marcozecchini 0:9fca2b23d0ba 769 transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand);
marcozecchini 0:9fca2b23d0ba 770 transferConfigC.destAddr = (uint32_t)txAddr;
marcozecchini 0:9fca2b23d0ba 771 transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes;
marcozecchini 0:9fca2b23d0ba 772 transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes;
marcozecchini 0:9fca2b23d0ba 773 transferConfigC.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 774 transferConfigC.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 775 transferConfigC.minorLoopBytes = 4;
marcozecchini 0:9fca2b23d0ba 776 transferConfigC.majorLoopCounts = 1;
marcozecchini 0:9fca2b23d0ba 777
marcozecchini 0:9fca2b23d0ba 778 EDMA_TcdReset(softwareTCD);
marcozecchini 0:9fca2b23d0ba 779 EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL);
marcozecchini 0:9fca2b23d0ba 780 }
marcozecchini 0:9fca2b23d0ba 781
marcozecchini 0:9fca2b23d0ba 782 if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) ||
marcozecchini 0:9fca2b23d0ba 783 ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8)) ||
marcozecchini 0:9fca2b23d0ba 784 (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))
marcozecchini 0:9fca2b23d0ba 785 {
marcozecchini 0:9fca2b23d0ba 786 transferConfigC.srcAddr = (uint32_t)(&(handle->command));
marcozecchini 0:9fca2b23d0ba 787 transferConfigC.destAddr = (uint32_t)txAddr;
marcozecchini 0:9fca2b23d0ba 788
marcozecchini 0:9fca2b23d0ba 789 transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes;
marcozecchini 0:9fca2b23d0ba 790 transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes;
marcozecchini 0:9fca2b23d0ba 791 transferConfigC.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 792 transferConfigC.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 793 transferConfigC.minorLoopBytes = 4;
marcozecchini 0:9fca2b23d0ba 794 if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 795 {
marcozecchini 0:9fca2b23d0ba 796 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 797 {
marcozecchini 0:9fca2b23d0ba 798 transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1;
marcozecchini 0:9fca2b23d0ba 799 }
marcozecchini 0:9fca2b23d0ba 800 else
marcozecchini 0:9fca2b23d0ba 801 {
marcozecchini 0:9fca2b23d0ba 802 transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1;
marcozecchini 0:9fca2b23d0ba 803 }
marcozecchini 0:9fca2b23d0ba 804
marcozecchini 0:9fca2b23d0ba 805 EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 806 handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD);
marcozecchini 0:9fca2b23d0ba 807 }
marcozecchini 0:9fca2b23d0ba 808 else
marcozecchini 0:9fca2b23d0ba 809 {
marcozecchini 0:9fca2b23d0ba 810 transferConfigC.majorLoopCounts = 1;
marcozecchini 0:9fca2b23d0ba 811
marcozecchini 0:9fca2b23d0ba 812 EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 813 handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL);
marcozecchini 0:9fca2b23d0ba 814 }
marcozecchini 0:9fca2b23d0ba 815
marcozecchini 0:9fca2b23d0ba 816 EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 817 handle->edmaIntermediaryToTxRegHandle->channel, false);
marcozecchini 0:9fca2b23d0ba 818 }
marcozecchini 0:9fca2b23d0ba 819 else
marcozecchini 0:9fca2b23d0ba 820 {
marcozecchini 0:9fca2b23d0ba 821 EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 822 handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL);
marcozecchini 0:9fca2b23d0ba 823 }
marcozecchini 0:9fca2b23d0ba 824
marcozecchini 0:9fca2b23d0ba 825 /*Start the EDMA channel_A , channel_B , channel_C transfer*/
marcozecchini 0:9fca2b23d0ba 826 EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
marcozecchini 0:9fca2b23d0ba 827 EDMA_StartTransfer(handle->edmaTxDataToIntermediaryHandle);
marcozecchini 0:9fca2b23d0ba 828 EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle);
marcozecchini 0:9fca2b23d0ba 829
marcozecchini 0:9fca2b23d0ba 830 /*Set channel priority*/
marcozecchini 0:9fca2b23d0ba 831 uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel;
marcozecchini 0:9fca2b23d0ba 832 uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel;
marcozecchini 0:9fca2b23d0ba 833 uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel;
marcozecchini 0:9fca2b23d0ba 834 uint8_t t = 0;
marcozecchini 0:9fca2b23d0ba 835 if (channelPriorityLow > channelPriorityMid)
marcozecchini 0:9fca2b23d0ba 836 {
marcozecchini 0:9fca2b23d0ba 837 t = channelPriorityLow;
marcozecchini 0:9fca2b23d0ba 838 channelPriorityLow = channelPriorityMid;
marcozecchini 0:9fca2b23d0ba 839 channelPriorityMid = t;
marcozecchini 0:9fca2b23d0ba 840 }
marcozecchini 0:9fca2b23d0ba 841
marcozecchini 0:9fca2b23d0ba 842 if (channelPriorityLow > channelPriorityHigh)
marcozecchini 0:9fca2b23d0ba 843 {
marcozecchini 0:9fca2b23d0ba 844 t = channelPriorityLow;
marcozecchini 0:9fca2b23d0ba 845 channelPriorityLow = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 846 channelPriorityHigh = t;
marcozecchini 0:9fca2b23d0ba 847 }
marcozecchini 0:9fca2b23d0ba 848
marcozecchini 0:9fca2b23d0ba 849 if (channelPriorityMid > channelPriorityHigh)
marcozecchini 0:9fca2b23d0ba 850 {
marcozecchini 0:9fca2b23d0ba 851 t = channelPriorityMid;
marcozecchini 0:9fca2b23d0ba 852 channelPriorityMid = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 853 channelPriorityHigh = t;
marcozecchini 0:9fca2b23d0ba 854 }
marcozecchini 0:9fca2b23d0ba 855 edma_channel_Preemption_config_t preemption_config_t;
marcozecchini 0:9fca2b23d0ba 856 preemption_config_t.enableChannelPreemption = true;
marcozecchini 0:9fca2b23d0ba 857 preemption_config_t.enablePreemptAbility = true;
marcozecchini 0:9fca2b23d0ba 858 preemption_config_t.channelPriority = channelPriorityLow;
marcozecchini 0:9fca2b23d0ba 859
marcozecchini 0:9fca2b23d0ba 860 if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 861 {
marcozecchini 0:9fca2b23d0ba 862 EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 863 &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 864
marcozecchini 0:9fca2b23d0ba 865 preemption_config_t.channelPriority = channelPriorityMid;
marcozecchini 0:9fca2b23d0ba 866 EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base,
marcozecchini 0:9fca2b23d0ba 867 handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 868
marcozecchini 0:9fca2b23d0ba 869 preemption_config_t.channelPriority = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 870 EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 871 handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 872 }
marcozecchini 0:9fca2b23d0ba 873 else
marcozecchini 0:9fca2b23d0ba 874 {
marcozecchini 0:9fca2b23d0ba 875 EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 876 handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 877
marcozecchini 0:9fca2b23d0ba 878 preemption_config_t.channelPriority = channelPriorityMid;
marcozecchini 0:9fca2b23d0ba 879 EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base,
marcozecchini 0:9fca2b23d0ba 880 handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 881
marcozecchini 0:9fca2b23d0ba 882 preemption_config_t.channelPriority = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 883 EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 884 &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 885 }
marcozecchini 0:9fca2b23d0ba 886
marcozecchini 0:9fca2b23d0ba 887 /*Set the channel link.*/
marcozecchini 0:9fca2b23d0ba 888 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 889 {
marcozecchini 0:9fca2b23d0ba 890 /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB
marcozecchini 0:9fca2b23d0ba 891 to prepare the next 32bits data (txData to handle->command) */
marcozecchini 0:9fca2b23d0ba 892 if (handle->remainingSendByteCount > 1)
marcozecchini 0:9fca2b23d0ba 893 {
marcozecchini 0:9fca2b23d0ba 894 EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base,
marcozecchini 0:9fca2b23d0ba 895 handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink,
marcozecchini 0:9fca2b23d0ba 896 handle->edmaTxDataToIntermediaryHandle->channel);
marcozecchini 0:9fca2b23d0ba 897 }
marcozecchini 0:9fca2b23d0ba 898
marcozecchini 0:9fca2b23d0ba 899 DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 900 }
marcozecchini 0:9fca2b23d0ba 901 else
marcozecchini 0:9fca2b23d0ba 902 {
marcozecchini 0:9fca2b23d0ba 903 if (handle->remainingSendByteCount > 0)
marcozecchini 0:9fca2b23d0ba 904 {
marcozecchini 0:9fca2b23d0ba 905 EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 906 kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel);
marcozecchini 0:9fca2b23d0ba 907
marcozecchini 0:9fca2b23d0ba 908 EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base,
marcozecchini 0:9fca2b23d0ba 909 handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink,
marcozecchini 0:9fca2b23d0ba 910 handle->edmaIntermediaryToTxRegHandle->channel);
marcozecchini 0:9fca2b23d0ba 911 }
marcozecchini 0:9fca2b23d0ba 912
marcozecchini 0:9fca2b23d0ba 913 DSPI_EnableDMA(base, kDSPI_RxDmaEnable);
marcozecchini 0:9fca2b23d0ba 914 }
marcozecchini 0:9fca2b23d0ba 915 #endif
marcozecchini 0:9fca2b23d0ba 916 DSPI_StartTransfer(base);
marcozecchini 0:9fca2b23d0ba 917
marcozecchini 0:9fca2b23d0ba 918 return kStatus_Success;
marcozecchini 0:9fca2b23d0ba 919 }
marcozecchini 0:9fca2b23d0ba 920
marcozecchini 0:9fca2b23d0ba 921 static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle,
marcozecchini 0:9fca2b23d0ba 922 void *g_dspiEdmaPrivateHandle,
marcozecchini 0:9fca2b23d0ba 923 bool transferDone,
marcozecchini 0:9fca2b23d0ba 924 uint32_t tcds)
marcozecchini 0:9fca2b23d0ba 925 {
marcozecchini 0:9fca2b23d0ba 926 assert(edmaHandle);
marcozecchini 0:9fca2b23d0ba 927 assert(g_dspiEdmaPrivateHandle);
marcozecchini 0:9fca2b23d0ba 928
marcozecchini 0:9fca2b23d0ba 929 dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle;
marcozecchini 0:9fca2b23d0ba 930
marcozecchini 0:9fca2b23d0ba 931 dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle;
marcozecchini 0:9fca2b23d0ba 932
marcozecchini 0:9fca2b23d0ba 933 DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 934
marcozecchini 0:9fca2b23d0ba 935 dspiEdmaPrivateHandle->handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 936
marcozecchini 0:9fca2b23d0ba 937 if (dspiEdmaPrivateHandle->handle->callback)
marcozecchini 0:9fca2b23d0ba 938 {
marcozecchini 0:9fca2b23d0ba 939 dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle,
marcozecchini 0:9fca2b23d0ba 940 kStatus_Success, dspiEdmaPrivateHandle->handle->userData);
marcozecchini 0:9fca2b23d0ba 941 }
marcozecchini 0:9fca2b23d0ba 942 }
marcozecchini 0:9fca2b23d0ba 943
marcozecchini 0:9fca2b23d0ba 944 void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle)
marcozecchini 0:9fca2b23d0ba 945 {
marcozecchini 0:9fca2b23d0ba 946 assert(handle);
marcozecchini 0:9fca2b23d0ba 947
marcozecchini 0:9fca2b23d0ba 948 DSPI_StopTransfer(base);
marcozecchini 0:9fca2b23d0ba 949
marcozecchini 0:9fca2b23d0ba 950 DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 951
marcozecchini 0:9fca2b23d0ba 952 EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
marcozecchini 0:9fca2b23d0ba 953 EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle);
marcozecchini 0:9fca2b23d0ba 954 EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle);
marcozecchini 0:9fca2b23d0ba 955
marcozecchini 0:9fca2b23d0ba 956 handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 957 }
marcozecchini 0:9fca2b23d0ba 958
marcozecchini 0:9fca2b23d0ba 959 status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count)
marcozecchini 0:9fca2b23d0ba 960 {
marcozecchini 0:9fca2b23d0ba 961 assert(handle);
marcozecchini 0:9fca2b23d0ba 962
marcozecchini 0:9fca2b23d0ba 963 if (!count)
marcozecchini 0:9fca2b23d0ba 964 {
marcozecchini 0:9fca2b23d0ba 965 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 966 }
marcozecchini 0:9fca2b23d0ba 967
marcozecchini 0:9fca2b23d0ba 968 /* Catch when there is not an active transfer. */
marcozecchini 0:9fca2b23d0ba 969 if (handle->state != kDSPI_Busy)
marcozecchini 0:9fca2b23d0ba 970 {
marcozecchini 0:9fca2b23d0ba 971 *count = 0;
marcozecchini 0:9fca2b23d0ba 972 return kStatus_NoTransferInProgress;
marcozecchini 0:9fca2b23d0ba 973 }
marcozecchini 0:9fca2b23d0ba 974
marcozecchini 0:9fca2b23d0ba 975 size_t bytes;
marcozecchini 0:9fca2b23d0ba 976
marcozecchini 0:9fca2b23d0ba 977 bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
marcozecchini 0:9fca2b23d0ba 978 handle->edmaRxRegToRxDataHandle->channel);
marcozecchini 0:9fca2b23d0ba 979
marcozecchini 0:9fca2b23d0ba 980 *count = handle->totalByteCount - bytes;
marcozecchini 0:9fca2b23d0ba 981
marcozecchini 0:9fca2b23d0ba 982 return kStatus_Success;
marcozecchini 0:9fca2b23d0ba 983 }
marcozecchini 0:9fca2b23d0ba 984
marcozecchini 0:9fca2b23d0ba 985 void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base,
marcozecchini 0:9fca2b23d0ba 986 dspi_slave_edma_handle_t *handle,
marcozecchini 0:9fca2b23d0ba 987 dspi_slave_edma_transfer_callback_t callback,
marcozecchini 0:9fca2b23d0ba 988 void *userData,
marcozecchini 0:9fca2b23d0ba 989 edma_handle_t *edmaRxRegToRxDataHandle,
marcozecchini 0:9fca2b23d0ba 990 edma_handle_t *edmaTxDataToTxRegHandle)
marcozecchini 0:9fca2b23d0ba 991 {
marcozecchini 0:9fca2b23d0ba 992 assert(handle);
marcozecchini 0:9fca2b23d0ba 993 assert(edmaRxRegToRxDataHandle);
marcozecchini 0:9fca2b23d0ba 994 assert(edmaTxDataToTxRegHandle);
marcozecchini 0:9fca2b23d0ba 995
marcozecchini 0:9fca2b23d0ba 996 /* Zero the handle. */
marcozecchini 0:9fca2b23d0ba 997 memset(handle, 0, sizeof(*handle));
marcozecchini 0:9fca2b23d0ba 998
marcozecchini 0:9fca2b23d0ba 999 uint32_t instance = DSPI_GetInstance(base);
marcozecchini 0:9fca2b23d0ba 1000
marcozecchini 0:9fca2b23d0ba 1001 s_dspiSlaveEdmaPrivateHandle[instance].base = base;
marcozecchini 0:9fca2b23d0ba 1002 s_dspiSlaveEdmaPrivateHandle[instance].handle = handle;
marcozecchini 0:9fca2b23d0ba 1003
marcozecchini 0:9fca2b23d0ba 1004 handle->callback = callback;
marcozecchini 0:9fca2b23d0ba 1005 handle->userData = userData;
marcozecchini 0:9fca2b23d0ba 1006
marcozecchini 0:9fca2b23d0ba 1007 handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
marcozecchini 0:9fca2b23d0ba 1008 handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
marcozecchini 0:9fca2b23d0ba 1009 }
marcozecchini 0:9fca2b23d0ba 1010
marcozecchini 0:9fca2b23d0ba 1011 status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer)
marcozecchini 0:9fca2b23d0ba 1012 {
marcozecchini 0:9fca2b23d0ba 1013 assert(handle);
marcozecchini 0:9fca2b23d0ba 1014 assert(transfer);
marcozecchini 0:9fca2b23d0ba 1015
marcozecchini 0:9fca2b23d0ba 1016 /* If send/receive length is zero */
marcozecchini 0:9fca2b23d0ba 1017 if (transfer->dataSize == 0)
marcozecchini 0:9fca2b23d0ba 1018 {
marcozecchini 0:9fca2b23d0ba 1019 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 1020 }
marcozecchini 0:9fca2b23d0ba 1021
marcozecchini 0:9fca2b23d0ba 1022 /* If both send buffer and receive buffer is null */
marcozecchini 0:9fca2b23d0ba 1023 if ((!(transfer->txData)) && (!(transfer->rxData)))
marcozecchini 0:9fca2b23d0ba 1024 {
marcozecchini 0:9fca2b23d0ba 1025 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 1026 }
marcozecchini 0:9fca2b23d0ba 1027
marcozecchini 0:9fca2b23d0ba 1028 /* Check that we're not busy.*/
marcozecchini 0:9fca2b23d0ba 1029 if (handle->state == kDSPI_Busy)
marcozecchini 0:9fca2b23d0ba 1030 {
marcozecchini 0:9fca2b23d0ba 1031 return kStatus_DSPI_Busy;
marcozecchini 0:9fca2b23d0ba 1032 }
marcozecchini 0:9fca2b23d0ba 1033
marcozecchini 0:9fca2b23d0ba 1034 handle->state = kDSPI_Busy;
marcozecchini 0:9fca2b23d0ba 1035
marcozecchini 0:9fca2b23d0ba 1036 uint32_t instance = DSPI_GetInstance(base);
marcozecchini 0:9fca2b23d0ba 1037 uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT;
marcozecchini 0:9fca2b23d0ba 1038 handle->bitsPerFrame =
marcozecchini 0:9fca2b23d0ba 1039 (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1;
marcozecchini 0:9fca2b23d0ba 1040
marcozecchini 0:9fca2b23d0ba 1041 /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer
marcozecchini 0:9fca2b23d0ba 1042 * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame
marcozecchini 0:9fca2b23d0ba 1043 */
marcozecchini 0:9fca2b23d0ba 1044 uint32_t limited_size = 0;
marcozecchini 0:9fca2b23d0ba 1045 if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 1046 {
marcozecchini 0:9fca2b23d0ba 1047 limited_size = 32767u;
marcozecchini 0:9fca2b23d0ba 1048 }
marcozecchini 0:9fca2b23d0ba 1049 else
marcozecchini 0:9fca2b23d0ba 1050 {
marcozecchini 0:9fca2b23d0ba 1051 limited_size = 511u;
marcozecchini 0:9fca2b23d0ba 1052 }
marcozecchini 0:9fca2b23d0ba 1053
marcozecchini 0:9fca2b23d0ba 1054 if (handle->bitsPerFrame > 8)
marcozecchini 0:9fca2b23d0ba 1055 {
marcozecchini 0:9fca2b23d0ba 1056 if (transfer->dataSize > (limited_size << 1u))
marcozecchini 0:9fca2b23d0ba 1057 {
marcozecchini 0:9fca2b23d0ba 1058 handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 1059 return kStatus_DSPI_OutOfRange;
marcozecchini 0:9fca2b23d0ba 1060 }
marcozecchini 0:9fca2b23d0ba 1061 }
marcozecchini 0:9fca2b23d0ba 1062 else
marcozecchini 0:9fca2b23d0ba 1063 {
marcozecchini 0:9fca2b23d0ba 1064 if (transfer->dataSize > limited_size)
marcozecchini 0:9fca2b23d0ba 1065 {
marcozecchini 0:9fca2b23d0ba 1066 handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 1067 return kStatus_DSPI_OutOfRange;
marcozecchini 0:9fca2b23d0ba 1068 }
marcozecchini 0:9fca2b23d0ba 1069 }
marcozecchini 0:9fca2b23d0ba 1070
marcozecchini 0:9fca2b23d0ba 1071 /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */
marcozecchini 0:9fca2b23d0ba 1072 if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1))
marcozecchini 0:9fca2b23d0ba 1073 {
marcozecchini 0:9fca2b23d0ba 1074 handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 1075 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 1076 }
marcozecchini 0:9fca2b23d0ba 1077
marcozecchini 0:9fca2b23d0ba 1078 EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]);
marcozecchini 0:9fca2b23d0ba 1079
marcozecchini 0:9fca2b23d0ba 1080 /* Store transfer information */
marcozecchini 0:9fca2b23d0ba 1081 handle->txData = transfer->txData;
marcozecchini 0:9fca2b23d0ba 1082 handle->rxData = transfer->rxData;
marcozecchini 0:9fca2b23d0ba 1083 handle->remainingSendByteCount = transfer->dataSize;
marcozecchini 0:9fca2b23d0ba 1084 handle->remainingReceiveByteCount = transfer->dataSize;
marcozecchini 0:9fca2b23d0ba 1085 handle->totalByteCount = transfer->dataSize;
marcozecchini 0:9fca2b23d0ba 1086
marcozecchini 0:9fca2b23d0ba 1087 uint16_t wordToSend = 0;
marcozecchini 0:9fca2b23d0ba 1088 uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)];
marcozecchini 0:9fca2b23d0ba 1089 uint8_t dataAlreadyFed = 0;
marcozecchini 0:9fca2b23d0ba 1090 uint8_t dataFedMax = 2;
marcozecchini 0:9fca2b23d0ba 1091
marcozecchini 0:9fca2b23d0ba 1092 uint32_t rxAddr = DSPI_GetRxRegisterAddress(base);
marcozecchini 0:9fca2b23d0ba 1093 uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base);
marcozecchini 0:9fca2b23d0ba 1094
marcozecchini 0:9fca2b23d0ba 1095 edma_transfer_config_t transferConfigA;
marcozecchini 0:9fca2b23d0ba 1096 edma_transfer_config_t transferConfigC;
marcozecchini 0:9fca2b23d0ba 1097
marcozecchini 0:9fca2b23d0ba 1098 DSPI_StopTransfer(base);
marcozecchini 0:9fca2b23d0ba 1099
marcozecchini 0:9fca2b23d0ba 1100 DSPI_FlushFifo(base, true, true);
marcozecchini 0:9fca2b23d0ba 1101 DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag);
marcozecchini 0:9fca2b23d0ba 1102
marcozecchini 0:9fca2b23d0ba 1103 DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 1104
marcozecchini 0:9fca2b23d0ba 1105 DSPI_StartTransfer(base);
marcozecchini 0:9fca2b23d0ba 1106
marcozecchini 0:9fca2b23d0ba 1107 /*if dspi has separate dma request , need not prepare data first .
marcozecchini 0:9fca2b23d0ba 1108 else (dspi has shared dma request) , send first 2 data into fifo if there is fifo or send first 1 data to
marcozecchini 0:9fca2b23d0ba 1109 slaveGetTxRegister if there is no fifo*/
marcozecchini 0:9fca2b23d0ba 1110 if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 1111 {
marcozecchini 0:9fca2b23d0ba 1112 /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to
marcozecchini 0:9fca2b23d0ba 1113 * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel.
marcozecchini 0:9fca2b23d0ba 1114 */
marcozecchini 0:9fca2b23d0ba 1115 /* If bits/frame is greater than one byte */
marcozecchini 0:9fca2b23d0ba 1116 if (handle->bitsPerFrame > 8)
marcozecchini 0:9fca2b23d0ba 1117 {
marcozecchini 0:9fca2b23d0ba 1118 while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
marcozecchini 0:9fca2b23d0ba 1119 {
marcozecchini 0:9fca2b23d0ba 1120 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 1121 {
marcozecchini 0:9fca2b23d0ba 1122 wordToSend = *(handle->txData);
marcozecchini 0:9fca2b23d0ba 1123 ++handle->txData; /* Increment to next data byte */
marcozecchini 0:9fca2b23d0ba 1124
marcozecchini 0:9fca2b23d0ba 1125 wordToSend |= (unsigned)(*(handle->txData)) << 8U;
marcozecchini 0:9fca2b23d0ba 1126 ++handle->txData; /* Increment to next data byte */
marcozecchini 0:9fca2b23d0ba 1127 }
marcozecchini 0:9fca2b23d0ba 1128 else
marcozecchini 0:9fca2b23d0ba 1129 {
marcozecchini 0:9fca2b23d0ba 1130 wordToSend = ((uint32_t)dummyData << 8) | dummyData;
marcozecchini 0:9fca2b23d0ba 1131 }
marcozecchini 0:9fca2b23d0ba 1132 handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */
marcozecchini 0:9fca2b23d0ba 1133 base->PUSHR_SLAVE = wordToSend;
marcozecchini 0:9fca2b23d0ba 1134
marcozecchini 0:9fca2b23d0ba 1135 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
marcozecchini 0:9fca2b23d0ba 1136 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
marcozecchini 0:9fca2b23d0ba 1137
marcozecchini 0:9fca2b23d0ba 1138 dataAlreadyFed += 2;
marcozecchini 0:9fca2b23d0ba 1139
marcozecchini 0:9fca2b23d0ba 1140 /* Exit loop if send count is zero, else update local variables for next loop */
marcozecchini 0:9fca2b23d0ba 1141 if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2)))
marcozecchini 0:9fca2b23d0ba 1142 {
marcozecchini 0:9fca2b23d0ba 1143 break;
marcozecchini 0:9fca2b23d0ba 1144 }
marcozecchini 0:9fca2b23d0ba 1145 } /* End of TX FIFO fill while loop */
marcozecchini 0:9fca2b23d0ba 1146 }
marcozecchini 0:9fca2b23d0ba 1147 else /* Optimized for bits/frame less than or equal to one byte. */
marcozecchini 0:9fca2b23d0ba 1148 {
marcozecchini 0:9fca2b23d0ba 1149 while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
marcozecchini 0:9fca2b23d0ba 1150 {
marcozecchini 0:9fca2b23d0ba 1151 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 1152 {
marcozecchini 0:9fca2b23d0ba 1153 wordToSend = *(handle->txData);
marcozecchini 0:9fca2b23d0ba 1154 /* Increment to next data word*/
marcozecchini 0:9fca2b23d0ba 1155 ++handle->txData;
marcozecchini 0:9fca2b23d0ba 1156 }
marcozecchini 0:9fca2b23d0ba 1157 else
marcozecchini 0:9fca2b23d0ba 1158 {
marcozecchini 0:9fca2b23d0ba 1159 wordToSend = dummyData;
marcozecchini 0:9fca2b23d0ba 1160 }
marcozecchini 0:9fca2b23d0ba 1161
marcozecchini 0:9fca2b23d0ba 1162 base->PUSHR_SLAVE = wordToSend;
marcozecchini 0:9fca2b23d0ba 1163
marcozecchini 0:9fca2b23d0ba 1164 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
marcozecchini 0:9fca2b23d0ba 1165 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
marcozecchini 0:9fca2b23d0ba 1166 /* Decrement remainingSendByteCount*/
marcozecchini 0:9fca2b23d0ba 1167 --handle->remainingSendByteCount;
marcozecchini 0:9fca2b23d0ba 1168
marcozecchini 0:9fca2b23d0ba 1169 dataAlreadyFed++;
marcozecchini 0:9fca2b23d0ba 1170
marcozecchini 0:9fca2b23d0ba 1171 /* Exit loop if send count is zero, else update local variables for next loop */
marcozecchini 0:9fca2b23d0ba 1172 if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax))
marcozecchini 0:9fca2b23d0ba 1173 {
marcozecchini 0:9fca2b23d0ba 1174 break;
marcozecchini 0:9fca2b23d0ba 1175 }
marcozecchini 0:9fca2b23d0ba 1176 } /* End of TX FIFO fill while loop */
marcozecchini 0:9fca2b23d0ba 1177 }
marcozecchini 0:9fca2b23d0ba 1178 }
marcozecchini 0:9fca2b23d0ba 1179
marcozecchini 0:9fca2b23d0ba 1180 /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/
marcozecchini 0:9fca2b23d0ba 1181 if (handle->remainingReceiveByteCount > 0)
marcozecchini 0:9fca2b23d0ba 1182 {
marcozecchini 0:9fca2b23d0ba 1183 EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
marcozecchini 0:9fca2b23d0ba 1184
marcozecchini 0:9fca2b23d0ba 1185 transferConfigA.srcAddr = (uint32_t)rxAddr;
marcozecchini 0:9fca2b23d0ba 1186 transferConfigA.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 1187
marcozecchini 0:9fca2b23d0ba 1188 if (handle->rxData)
marcozecchini 0:9fca2b23d0ba 1189 {
marcozecchini 0:9fca2b23d0ba 1190 transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]);
marcozecchini 0:9fca2b23d0ba 1191 transferConfigA.destOffset = 1;
marcozecchini 0:9fca2b23d0ba 1192 }
marcozecchini 0:9fca2b23d0ba 1193 else
marcozecchini 0:9fca2b23d0ba 1194 {
marcozecchini 0:9fca2b23d0ba 1195 transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull);
marcozecchini 0:9fca2b23d0ba 1196 transferConfigA.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 1197 }
marcozecchini 0:9fca2b23d0ba 1198
marcozecchini 0:9fca2b23d0ba 1199 transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 1200
marcozecchini 0:9fca2b23d0ba 1201 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 1202 {
marcozecchini 0:9fca2b23d0ba 1203 transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 1204 transferConfigA.minorLoopBytes = 1;
marcozecchini 0:9fca2b23d0ba 1205 transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount;
marcozecchini 0:9fca2b23d0ba 1206 }
marcozecchini 0:9fca2b23d0ba 1207 else
marcozecchini 0:9fca2b23d0ba 1208 {
marcozecchini 0:9fca2b23d0ba 1209 transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes;
marcozecchini 0:9fca2b23d0ba 1210 transferConfigA.minorLoopBytes = 2;
marcozecchini 0:9fca2b23d0ba 1211 transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2;
marcozecchini 0:9fca2b23d0ba 1212 }
marcozecchini 0:9fca2b23d0ba 1213
marcozecchini 0:9fca2b23d0ba 1214 /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
marcozecchini 0:9fca2b23d0ba 1215 handle->nbytes = transferConfigA.minorLoopBytes;
marcozecchini 0:9fca2b23d0ba 1216
marcozecchini 0:9fca2b23d0ba 1217 EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 1218 &transferConfigA, NULL);
marcozecchini 0:9fca2b23d0ba 1219 EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 1220 kEDMA_MajorInterruptEnable);
marcozecchini 0:9fca2b23d0ba 1221 }
marcozecchini 0:9fca2b23d0ba 1222
marcozecchini 0:9fca2b23d0ba 1223 if (handle->remainingSendByteCount > 0)
marcozecchini 0:9fca2b23d0ba 1224 {
marcozecchini 0:9fca2b23d0ba 1225 /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/
marcozecchini 0:9fca2b23d0ba 1226 EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
marcozecchini 0:9fca2b23d0ba 1227
marcozecchini 0:9fca2b23d0ba 1228 transferConfigC.destAddr = (uint32_t)txAddr;
marcozecchini 0:9fca2b23d0ba 1229 transferConfigC.destOffset = 0;
marcozecchini 0:9fca2b23d0ba 1230
marcozecchini 0:9fca2b23d0ba 1231 if (handle->txData)
marcozecchini 0:9fca2b23d0ba 1232 {
marcozecchini 0:9fca2b23d0ba 1233 transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0]));
marcozecchini 0:9fca2b23d0ba 1234 transferConfigC.srcOffset = 1;
marcozecchini 0:9fca2b23d0ba 1235 }
marcozecchini 0:9fca2b23d0ba 1236 else
marcozecchini 0:9fca2b23d0ba 1237 {
marcozecchini 0:9fca2b23d0ba 1238 transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull);
marcozecchini 0:9fca2b23d0ba 1239 transferConfigC.srcOffset = 0;
marcozecchini 0:9fca2b23d0ba 1240 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 1241 {
marcozecchini 0:9fca2b23d0ba 1242 handle->txBuffIfNull = dummyData;
marcozecchini 0:9fca2b23d0ba 1243 }
marcozecchini 0:9fca2b23d0ba 1244 else
marcozecchini 0:9fca2b23d0ba 1245 {
marcozecchini 0:9fca2b23d0ba 1246 handle->txBuffIfNull = ((uint32_t)dummyData << 8) | dummyData;
marcozecchini 0:9fca2b23d0ba 1247 }
marcozecchini 0:9fca2b23d0ba 1248 }
marcozecchini 0:9fca2b23d0ba 1249
marcozecchini 0:9fca2b23d0ba 1250 transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 1251
marcozecchini 0:9fca2b23d0ba 1252 if (handle->bitsPerFrame <= 8)
marcozecchini 0:9fca2b23d0ba 1253 {
marcozecchini 0:9fca2b23d0ba 1254 transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes;
marcozecchini 0:9fca2b23d0ba 1255 transferConfigC.minorLoopBytes = 1;
marcozecchini 0:9fca2b23d0ba 1256 transferConfigC.majorLoopCounts = handle->remainingSendByteCount;
marcozecchini 0:9fca2b23d0ba 1257 }
marcozecchini 0:9fca2b23d0ba 1258 else
marcozecchini 0:9fca2b23d0ba 1259 {
marcozecchini 0:9fca2b23d0ba 1260 transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes;
marcozecchini 0:9fca2b23d0ba 1261 transferConfigC.minorLoopBytes = 2;
marcozecchini 0:9fca2b23d0ba 1262 transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2;
marcozecchini 0:9fca2b23d0ba 1263 }
marcozecchini 0:9fca2b23d0ba 1264
marcozecchini 0:9fca2b23d0ba 1265 EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
marcozecchini 0:9fca2b23d0ba 1266 &transferConfigC, NULL);
marcozecchini 0:9fca2b23d0ba 1267
marcozecchini 0:9fca2b23d0ba 1268 EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
marcozecchini 0:9fca2b23d0ba 1269 }
marcozecchini 0:9fca2b23d0ba 1270
marcozecchini 0:9fca2b23d0ba 1271 EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
marcozecchini 0:9fca2b23d0ba 1272
marcozecchini 0:9fca2b23d0ba 1273 /*Set channel priority*/
marcozecchini 0:9fca2b23d0ba 1274 uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel;
marcozecchini 0:9fca2b23d0ba 1275 uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel;
marcozecchini 0:9fca2b23d0ba 1276 uint8_t t = 0;
marcozecchini 0:9fca2b23d0ba 1277
marcozecchini 0:9fca2b23d0ba 1278 if (channelPriorityLow > channelPriorityHigh)
marcozecchini 0:9fca2b23d0ba 1279 {
marcozecchini 0:9fca2b23d0ba 1280 t = channelPriorityLow;
marcozecchini 0:9fca2b23d0ba 1281 channelPriorityLow = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 1282 channelPriorityHigh = t;
marcozecchini 0:9fca2b23d0ba 1283 }
marcozecchini 0:9fca2b23d0ba 1284
marcozecchini 0:9fca2b23d0ba 1285 edma_channel_Preemption_config_t preemption_config_t;
marcozecchini 0:9fca2b23d0ba 1286 preemption_config_t.enableChannelPreemption = true;
marcozecchini 0:9fca2b23d0ba 1287 preemption_config_t.enablePreemptAbility = true;
marcozecchini 0:9fca2b23d0ba 1288 preemption_config_t.channelPriority = channelPriorityLow;
marcozecchini 0:9fca2b23d0ba 1289
marcozecchini 0:9fca2b23d0ba 1290 if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 1291 {
marcozecchini 0:9fca2b23d0ba 1292 EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 1293 &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 1294
marcozecchini 0:9fca2b23d0ba 1295 preemption_config_t.channelPriority = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 1296 EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
marcozecchini 0:9fca2b23d0ba 1297 &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 1298 }
marcozecchini 0:9fca2b23d0ba 1299 else
marcozecchini 0:9fca2b23d0ba 1300 {
marcozecchini 0:9fca2b23d0ba 1301 EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
marcozecchini 0:9fca2b23d0ba 1302 &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 1303
marcozecchini 0:9fca2b23d0ba 1304 preemption_config_t.channelPriority = channelPriorityHigh;
marcozecchini 0:9fca2b23d0ba 1305 EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 1306 &preemption_config_t);
marcozecchini 0:9fca2b23d0ba 1307 }
marcozecchini 0:9fca2b23d0ba 1308
marcozecchini 0:9fca2b23d0ba 1309 /*Set the channel link.
marcozecchini 0:9fca2b23d0ba 1310 For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_C.
marcozecchini 0:9fca2b23d0ba 1311 For DSPI instances with separate RX and TX DMA requests:
marcozecchini 0:9fca2b23d0ba 1312 Rx DMA request -> channel_A
marcozecchini 0:9fca2b23d0ba 1313 Tx DMA request -> channel_C */
marcozecchini 0:9fca2b23d0ba 1314 if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
marcozecchini 0:9fca2b23d0ba 1315 {
marcozecchini 0:9fca2b23d0ba 1316 if (handle->remainingSendByteCount > 0)
marcozecchini 0:9fca2b23d0ba 1317 {
marcozecchini 0:9fca2b23d0ba 1318 EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
marcozecchini 0:9fca2b23d0ba 1319 kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel);
marcozecchini 0:9fca2b23d0ba 1320 }
marcozecchini 0:9fca2b23d0ba 1321 DSPI_EnableDMA(base, kDSPI_RxDmaEnable);
marcozecchini 0:9fca2b23d0ba 1322 }
marcozecchini 0:9fca2b23d0ba 1323 else
marcozecchini 0:9fca2b23d0ba 1324 {
marcozecchini 0:9fca2b23d0ba 1325 DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 1326 }
marcozecchini 0:9fca2b23d0ba 1327
marcozecchini 0:9fca2b23d0ba 1328 return kStatus_Success;
marcozecchini 0:9fca2b23d0ba 1329 }
marcozecchini 0:9fca2b23d0ba 1330
marcozecchini 0:9fca2b23d0ba 1331 static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle,
marcozecchini 0:9fca2b23d0ba 1332 void *g_dspiEdmaPrivateHandle,
marcozecchini 0:9fca2b23d0ba 1333 bool transferDone,
marcozecchini 0:9fca2b23d0ba 1334 uint32_t tcds)
marcozecchini 0:9fca2b23d0ba 1335 {
marcozecchini 0:9fca2b23d0ba 1336 assert(edmaHandle);
marcozecchini 0:9fca2b23d0ba 1337 assert(g_dspiEdmaPrivateHandle);
marcozecchini 0:9fca2b23d0ba 1338
marcozecchini 0:9fca2b23d0ba 1339 dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle;
marcozecchini 0:9fca2b23d0ba 1340
marcozecchini 0:9fca2b23d0ba 1341 dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle;
marcozecchini 0:9fca2b23d0ba 1342
marcozecchini 0:9fca2b23d0ba 1343 DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 1344
marcozecchini 0:9fca2b23d0ba 1345 dspiEdmaPrivateHandle->handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 1346
marcozecchini 0:9fca2b23d0ba 1347 if (dspiEdmaPrivateHandle->handle->callback)
marcozecchini 0:9fca2b23d0ba 1348 {
marcozecchini 0:9fca2b23d0ba 1349 dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle,
marcozecchini 0:9fca2b23d0ba 1350 kStatus_Success, dspiEdmaPrivateHandle->handle->userData);
marcozecchini 0:9fca2b23d0ba 1351 }
marcozecchini 0:9fca2b23d0ba 1352 }
marcozecchini 0:9fca2b23d0ba 1353
marcozecchini 0:9fca2b23d0ba 1354 void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle)
marcozecchini 0:9fca2b23d0ba 1355 {
marcozecchini 0:9fca2b23d0ba 1356 assert(handle);
marcozecchini 0:9fca2b23d0ba 1357
marcozecchini 0:9fca2b23d0ba 1358 DSPI_StopTransfer(base);
marcozecchini 0:9fca2b23d0ba 1359
marcozecchini 0:9fca2b23d0ba 1360 DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
marcozecchini 0:9fca2b23d0ba 1361
marcozecchini 0:9fca2b23d0ba 1362 EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
marcozecchini 0:9fca2b23d0ba 1363 EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
marcozecchini 0:9fca2b23d0ba 1364
marcozecchini 0:9fca2b23d0ba 1365 handle->state = kDSPI_Idle;
marcozecchini 0:9fca2b23d0ba 1366 }
marcozecchini 0:9fca2b23d0ba 1367
marcozecchini 0:9fca2b23d0ba 1368 status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count)
marcozecchini 0:9fca2b23d0ba 1369 {
marcozecchini 0:9fca2b23d0ba 1370 assert(handle);
marcozecchini 0:9fca2b23d0ba 1371
marcozecchini 0:9fca2b23d0ba 1372 if (!count)
marcozecchini 0:9fca2b23d0ba 1373 {
marcozecchini 0:9fca2b23d0ba 1374 return kStatus_InvalidArgument;
marcozecchini 0:9fca2b23d0ba 1375 }
marcozecchini 0:9fca2b23d0ba 1376
marcozecchini 0:9fca2b23d0ba 1377 /* Catch when there is not an active transfer. */
marcozecchini 0:9fca2b23d0ba 1378 if (handle->state != kDSPI_Busy)
marcozecchini 0:9fca2b23d0ba 1379 {
marcozecchini 0:9fca2b23d0ba 1380 *count = 0;
marcozecchini 0:9fca2b23d0ba 1381 return kStatus_NoTransferInProgress;
marcozecchini 0:9fca2b23d0ba 1382 }
marcozecchini 0:9fca2b23d0ba 1383
marcozecchini 0:9fca2b23d0ba 1384 size_t bytes;
marcozecchini 0:9fca2b23d0ba 1385
marcozecchini 0:9fca2b23d0ba 1386 bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
marcozecchini 0:9fca2b23d0ba 1387 handle->edmaRxRegToRxDataHandle->channel);
marcozecchini 0:9fca2b23d0ba 1388
marcozecchini 0:9fca2b23d0ba 1389 *count = handle->totalByteCount - bytes;
marcozecchini 0:9fca2b23d0ba 1390
marcozecchini 0:9fca2b23d0ba 1391 return kStatus_Success;
marcozecchini 0:9fca2b23d0ba 1392 }