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.
mbed-os/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.c@0:9fca2b23d0ba, 2019-02-23 (annotated)
- Committer:
- marcozecchini
- Date:
- Sat Feb 23 12:13:36 2019 +0000
- Revision:
- 0:9fca2b23d0ba
final commit
Who changed what in which revision?
| User | Revision | Line number | New 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 | } |