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