123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- /*
- * Copyright (c) 2015, Freescale Semiconductor, Inc.
- * Copyright 2016-2017 NXP
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * o Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "fsl_flexio_spi_edma.h"
- /*******************************************************************************
- * Definitons
- ******************************************************************************/
- /*<! Structure definition for spi_edma_private_handle_t. The structure is private. */
- typedef struct _flexio_spi_master_edma_private_handle
- {
- FLEXIO_SPI_Type *base;
- flexio_spi_master_edma_handle_t *handle;
- } flexio_spi_master_edma_private_handle_t;
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*!
- * @brief EDMA callback function for FLEXIO SPI send transfer.
- *
- * @param handle EDMA handle pointer.
- * @param param Callback function parameter.
- */
- static void FLEXIO_SPI_TxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
- /*!
- * @brief EDMA callback function for FLEXIO SPI receive transfer.
- *
- * @param handle EDMA handle pointer.
- * @param param Callback function parameter.
- */
- static void FLEXIO_SPI_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
- /*!
- * @brief EDMA config for FLEXIO SPI transfer.
- *
- * @param base pointer to FLEXIO_SPI_Type structure.
- * @param handle pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
- * @param xfer Pointer to flexio spi transfer structure.
- */
- static void FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base,
- flexio_spi_master_edma_handle_t *handle,
- flexio_spi_transfer_t *xfer);
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /* Dummy data used to send */
- static const uint16_t s_dummyData = FLEXIO_SPI_DUMMYDATA;
- /*< @brief user configurable flexio spi handle count. */
- #define FLEXIO_SPI_HANDLE_COUNT 2
- /*<! Private handle only used for internally. */
- static flexio_spi_master_edma_private_handle_t s_edmaPrivateHandle[FLEXIO_SPI_HANDLE_COUNT];
- /*******************************************************************************
- * Code
- ******************************************************************************/
- static void FLEXIO_SPI_TxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
- {
- tcds = tcds;
- flexio_spi_master_edma_private_handle_t *spiPrivateHandle = (flexio_spi_master_edma_private_handle_t *)param;
- /* Disable Tx DMA */
- if (transferDone)
- {
- FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, kFLEXIO_SPI_TxDmaEnable, false);
- /* change the state */
- spiPrivateHandle->handle->txInProgress = false;
- /* All finished, call the callback */
- if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
- {
- if (spiPrivateHandle->handle->callback)
- {
- (spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
- spiPrivateHandle->handle->userData);
- }
- }
- }
- }
- static void FLEXIO_SPI_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
- {
- tcds = tcds;
- flexio_spi_master_edma_private_handle_t *spiPrivateHandle = (flexio_spi_master_edma_private_handle_t *)param;
- if (transferDone)
- {
- /* Disable Rx dma */
- FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, kFLEXIO_SPI_RxDmaEnable, false);
- /* change the state */
- spiPrivateHandle->handle->rxInProgress = false;
- /* All finished, call the callback */
- if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
- {
- if (spiPrivateHandle->handle->callback)
- {
- (spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
- spiPrivateHandle->handle->userData);
- }
- }
- }
- }
- static void FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base,
- flexio_spi_master_edma_handle_t *handle,
- flexio_spi_transfer_t *xfer)
- {
- edma_transfer_config_t xferConfig;
- flexio_spi_shift_direction_t direction;
- uint8_t bytesPerFrame;
- /* Configure the values in handle. */
- switch (xfer->flags)
- {
- case kFLEXIO_SPI_8bitMsb:
- bytesPerFrame = 1;
- direction = kFLEXIO_SPI_MsbFirst;
- break;
- case kFLEXIO_SPI_8bitLsb:
- bytesPerFrame = 1;
- direction = kFLEXIO_SPI_LsbFirst;
- break;
- case kFLEXIO_SPI_16bitMsb:
- bytesPerFrame = 2;
- direction = kFLEXIO_SPI_MsbFirst;
- break;
- case kFLEXIO_SPI_16bitLsb:
- bytesPerFrame = 2;
- direction = kFLEXIO_SPI_LsbFirst;
- break;
- default:
- bytesPerFrame = 1U;
- direction = kFLEXIO_SPI_MsbFirst;
- assert(true);
- break;
- }
- /* Save total transfer size. */
- handle->transferSize = xfer->dataSize;
- /* Configure tx transfer EDMA. */
- xferConfig.destAddr = FLEXIO_SPI_GetTxDataRegisterAddress(base, direction);
- xferConfig.destOffset = 0;
- if (bytesPerFrame == 1U)
- {
- xferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
- xferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
- xferConfig.minorLoopBytes = 1;
- }
- else
- {
- if (direction == kFLEXIO_SPI_MsbFirst)
- {
- xferConfig.destAddr -= 1U;
- }
- xferConfig.srcTransferSize = kEDMA_TransferSize2Bytes;
- xferConfig.destTransferSize = kEDMA_TransferSize2Bytes;
- xferConfig.minorLoopBytes = 2;
- }
- /* Configure DMA channel. */
- if (xfer->txData)
- {
- xferConfig.srcOffset = bytesPerFrame;
- xferConfig.srcAddr = (uint32_t)(xfer->txData);
- }
- else
- {
- /* Disable the source increasement and source set to dummyData. */
- xferConfig.srcOffset = 0;
- xferConfig.srcAddr = (uint32_t)(&s_dummyData);
- }
- xferConfig.majorLoopCounts = (xfer->dataSize / xferConfig.minorLoopBytes);
- /* Store the initially configured eDMA minor byte transfer count into the FLEXIO SPI handle */
- handle->nbytes = xferConfig.minorLoopBytes;
- if (handle->txHandle)
- {
- EDMA_SubmitTransfer(handle->txHandle, &xferConfig);
- }
- /* Configure tx transfer EDMA. */
- if (xfer->rxData)
- {
- xferConfig.srcAddr = FLEXIO_SPI_GetRxDataRegisterAddress(base, direction);
- if (bytesPerFrame == 2U)
- {
- if (direction == kFLEXIO_SPI_LsbFirst)
- {
- xferConfig.srcAddr -= 1U;
- }
- }
- xferConfig.srcOffset = 0;
- xferConfig.destAddr = (uint32_t)(xfer->rxData);
- xferConfig.destOffset = bytesPerFrame;
- EDMA_SubmitTransfer(handle->rxHandle, &xferConfig);
- handle->rxInProgress = true;
- FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_RxDmaEnable, true);
- EDMA_StartTransfer(handle->rxHandle);
- }
- /* Always start Tx transfer. */
- if (handle->txHandle)
- {
- handle->txInProgress = true;
- FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_TxDmaEnable, true);
- EDMA_StartTransfer(handle->txHandle);
- }
- }
- status_t FLEXIO_SPI_MasterTransferCreateHandleEDMA(FLEXIO_SPI_Type *base,
- flexio_spi_master_edma_handle_t *handle,
- flexio_spi_master_edma_transfer_callback_t callback,
- void *userData,
- edma_handle_t *txHandle,
- edma_handle_t *rxHandle)
- {
- assert(handle);
- uint8_t index = 0;
- /* Find the an empty handle pointer to store the handle. */
- for (index = 0; index < FLEXIO_SPI_HANDLE_COUNT; index++)
- {
- if (s_edmaPrivateHandle[index].base == NULL)
- {
- s_edmaPrivateHandle[index].base = base;
- s_edmaPrivateHandle[index].handle = handle;
- break;
- }
- }
- if (index == FLEXIO_SPI_HANDLE_COUNT)
- {
- return kStatus_OutOfRange;
- }
- /* Set spi base to handle. */
- handle->txHandle = txHandle;
- handle->rxHandle = rxHandle;
- /* Register callback and userData. */
- handle->callback = callback;
- handle->userData = userData;
- /* Set SPI state to idle. */
- handle->txInProgress = false;
- handle->rxInProgress = false;
- /* Install callback for Tx/Rx dma channel. */
- if (handle->txHandle)
- {
- EDMA_SetCallback(handle->txHandle, FLEXIO_SPI_TxEDMACallback, &s_edmaPrivateHandle[index]);
- }
- if (handle->rxHandle)
- {
- EDMA_SetCallback(handle->rxHandle, FLEXIO_SPI_RxEDMACallback, &s_edmaPrivateHandle[index]);
- }
- return kStatus_Success;
- }
- status_t FLEXIO_SPI_MasterTransferEDMA(FLEXIO_SPI_Type *base,
- flexio_spi_master_edma_handle_t *handle,
- flexio_spi_transfer_t *xfer)
- {
- assert(handle);
- assert(xfer);
- uint32_t dataMode = 0;
- uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
- timerCmp &= 0x00FFU;
- /* Check if the device is busy. */
- if ((handle->txInProgress) || (handle->rxInProgress))
- {
- return kStatus_FLEXIO_SPI_Busy;
- }
- /* Check if input parameter invalid. */
- if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
- {
- return kStatus_InvalidArgument;
- }
- /* configure data mode. */
- if ((xfer->flags == kFLEXIO_SPI_8bitMsb) || (xfer->flags == kFLEXIO_SPI_8bitLsb))
- {
- dataMode = (8 * 2 - 1U) << 8U;
- }
- else if ((xfer->flags == kFLEXIO_SPI_16bitMsb) || (xfer->flags == kFLEXIO_SPI_16bitLsb))
- {
- dataMode = (16 * 2 - 1U) << 8U;
- }
- else
- {
- dataMode = 8 * 2 - 1U;
- }
- dataMode |= timerCmp;
- base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
- FLEXIO_SPI_EDMAConfig(base, handle, xfer);
- return kStatus_Success;
- }
- status_t FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type *base,
- flexio_spi_master_edma_handle_t *handle,
- size_t *count)
- {
- assert(handle);
- if (!count)
- {
- return kStatus_InvalidArgument;
- }
- if (handle->rxInProgress)
- {
- *count = (handle->transferSize -
- (uint32_t)handle->nbytes *
- EDMA_GetRemainingMajorLoopCount(handle->rxHandle->base, handle->rxHandle->channel));
- }
- else
- {
- *count = (handle->transferSize -
- (uint32_t)handle->nbytes *
- EDMA_GetRemainingMajorLoopCount(handle->txHandle->base, handle->txHandle->channel));
- }
- return kStatus_Success;
- }
- void FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_master_edma_handle_t *handle)
- {
- assert(handle);
- /* Disable dma. */
- EDMA_StopTransfer(handle->txHandle);
- EDMA_StopTransfer(handle->rxHandle);
- /* Disable DMA enable bit. */
- FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_DmaAllEnable, false);
- /* Set the handle state. */
- handle->txInProgress = false;
- handle->rxInProgress = false;
- }
- status_t FLEXIO_SPI_SlaveTransferEDMA(FLEXIO_SPI_Type *base,
- flexio_spi_slave_edma_handle_t *handle,
- flexio_spi_transfer_t *xfer)
- {
- assert(handle);
- assert(xfer);
- uint32_t dataMode = 0;
- /* Check if the device is busy. */
- if ((handle->txInProgress) || (handle->rxInProgress))
- {
- return kStatus_FLEXIO_SPI_Busy;
- }
- /* Check if input parameter invalid. */
- if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
- {
- return kStatus_InvalidArgument;
- }
- /* configure data mode. */
- if ((xfer->flags == kFLEXIO_SPI_8bitMsb) || (xfer->flags == kFLEXIO_SPI_8bitLsb))
- {
- dataMode = 8 * 2 - 1U;
- }
- else if ((xfer->flags == kFLEXIO_SPI_16bitMsb) || (xfer->flags == kFLEXIO_SPI_16bitLsb))
- {
- dataMode = 16 * 2 - 1U;
- }
- else
- {
- dataMode = 8 * 2 - 1U;
- }
- base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
- FLEXIO_SPI_EDMAConfig(base, handle, xfer);
- return kStatus_Success;
- }
|