summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_lpspi_edma.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_lpspi_edma.c1154
1 files changed, 0 insertions, 1154 deletions
diff --git a/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_lpspi_edma.c b/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_lpspi_edma.c
deleted file mode 100644
index 5a19ca0092..0000000000
--- a/bsps/arm/imxrt/nxp/devices/MIMXRT1052/drivers/fsl_lpspi_edma.c
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*
- * Copyright (c) 2015, Freescale Semiconductor, Inc.
- * Copyright 2016-2019 NXP
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include "fsl_lpspi_edma.h"
-
-/***********************************************************************************************************************
- * Definitions
- ***********************************************************************************************************************/
-
-/* Component ID definition, used by tools. */
-#ifndef FSL_COMPONENT_ID
-#define FSL_COMPONENT_ID "platform.drivers.lpspi_edma"
-#endif
-
-/*!
- * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private.
- */
-typedef struct _lpspi_master_edma_private_handle
-{
- LPSPI_Type *base; /*!< LPSPI peripheral base address. */
- lpspi_master_edma_handle_t *handle; /*!< lpspi_master_edma_handle_t handle */
-} lpspi_master_edma_private_handle_t;
-
-/*!
- * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private.
- */
-typedef struct _lpspi_slave_edma_private_handle
-{
- LPSPI_Type *base; /*!< LPSPI peripheral base address. */
- lpspi_slave_edma_handle_t *handle; /*!< lpspi_slave_edma_handle_t handle */
-} lpspi_slave_edma_private_handle_t;
-
-/***********************************************************************************************************************
- * Prototypes
- ***********************************************************************************************************************/
-
-/*!
- * @brief EDMA_LpspiMasterCallback after the LPSPI master transfer completed by using EDMA.
- * This is not a public API.
- */
-static void EDMA_LpspiMasterCallback(edma_handle_t *edmaHandle,
- void *g_lpspiEdmaPrivateHandle,
- bool transferDone,
- uint32_t tcds);
-
-/*!
- * @brief EDMA_LpspiSlaveCallback after the LPSPI slave transfer completed by using EDMA.
- * This is not a public API.
- */
-static void EDMA_LpspiSlaveCallback(edma_handle_t *edmaHandle,
- void *g_lpspiEdmaPrivateHandle,
- bool transferDone,
- uint32_t tcds);
-
-static void LPSPI_SeparateEdmaReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap);
-
-/***********************************************************************************************************************
- * Variables
- ***********************************************************************************************************************/
-/*! @brief Pointers to lpspi bases for each instance. */
-static LPSPI_Type *const s_lpspiBases[] = LPSPI_BASE_PTRS;
-
-/*! @brief Pointers to lpspi edma handles for each instance. */
-static lpspi_master_edma_private_handle_t s_lpspiMasterEdmaPrivateHandle[ARRAY_SIZE(s_lpspiBases)];
-static lpspi_slave_edma_private_handle_t s_lpspiSlaveEdmaPrivateHandle[ARRAY_SIZE(s_lpspiBases)];
-
-/***********************************************************************************************************************
- * Code
- ***********************************************************************************************************************/
-static void LPSPI_SeparateEdmaReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap)
-{
- assert(rxData);
-
- switch (bytesEachRead)
- {
- case 1:
- if (!isByteSwap)
- {
- *rxData = (uint8_t)readData;
- ++rxData;
- }
- else
- {
- *rxData = (uint8_t)(readData >> 24);
- ++rxData;
- }
- break;
-
- case 2:
- if (!isByteSwap)
- {
- *rxData = (uint8_t)readData;
- ++rxData;
- *rxData = (uint8_t)(readData >> 8);
- ++rxData;
- }
- else
- {
- *rxData = (uint8_t)(readData >> 16);
- ++rxData;
- *rxData = (uint8_t)(readData >> 24);
- ++rxData;
- }
- break;
-
- case 4:
-
- *rxData = (uint8_t)readData;
- ++rxData;
- *rxData = (uint8_t)(readData >> 8);
- ++rxData;
- *rxData = (uint8_t)(readData >> 16);
- ++rxData;
- *rxData = (uint8_t)(readData >> 24);
- ++rxData;
-
- break;
-
- default:
- assert(false);
- break;
- }
-}
-
-/*!
- * brief Initializes the LPSPI master eDMA handle.
- *
- * This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs. Usually, for a
- * specified LPSPI instance, call this API once to get the initialized handle.
- *
- * Note that the LPSPI eDMA has a separated (Rx and Rx as two sources) or shared (Rx and Tx are the same source) DMA
- * request source.
- * (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
- * Tx DMAMUX source for edmaIntermediaryToTxRegHandle.
- * (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle.
- *
- * param base LPSPI peripheral base address.
- * param handle LPSPI handle pointer to lpspi_master_edma_handle_t.
- * param callback LPSPI callback.
- * param userData callback function parameter.
- * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
- * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
- */
-void LPSPI_MasterTransferCreateHandleEDMA(LPSPI_Type *base,
- lpspi_master_edma_handle_t *handle,
- lpspi_master_edma_transfer_callback_t callback,
- void *userData,
- edma_handle_t *edmaRxRegToRxDataHandle,
- edma_handle_t *edmaTxDataToTxRegHandle)
-{
- assert(handle);
- assert(edmaRxRegToRxDataHandle);
- assert(edmaTxDataToTxRegHandle);
-
- /* Zero the handle. */
- (void)memset(handle, 0, sizeof(*handle));
-
- uint32_t instance = LPSPI_GetInstance(base);
-
- s_lpspiMasterEdmaPrivateHandle[instance].base = base;
- s_lpspiMasterEdmaPrivateHandle[instance].handle = handle;
-
- handle->callback = callback;
- handle->userData = userData;
-
- handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
- handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
-}
-
-/*!
- * brief LPSPI master transfer data using eDMA.
- *
- * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
- * is transferred, the callback function is called.
- *
- * Note:
- * The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
- * For bytesPerFrame greater than 4:
- * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
- * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
- *
- * param base LPSPI peripheral base address.
- * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
- * param transfer pointer to lpspi_transfer_t structure.
- * return status of status_t.
- */
-status_t LPSPI_MasterTransferEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, lpspi_transfer_t *transfer)
-{
- assert(handle);
- assert(transfer);
-
- uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1U;
- uint32_t bytesPerFrame = (bitsPerFrame + 7U) / 8U;
- uint32_t temp = 0U;
- bool isByteSwap;
- bool isPcsContinuous;
-
- if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
- {
- return kStatus_InvalidArgument;
- }
-
- /*And since the dma transfer can not support 3 bytes .*/
- if ((bytesPerFrame % 4U) == 3U)
- {
- return kStatus_InvalidArgument;
- }
-
- /* Check that we're not busy.*/
- if (handle->state == (uint8_t)kLPSPI_Busy)
- {
- return kStatus_LPSPI_Busy;
- }
-
- handle->state = (uint8_t)kLPSPI_Busy;
-
- uint32_t instance = LPSPI_GetInstance(base);
- uint32_t rxAddr = LPSPI_GetRxRegisterAddress(base);
- uint32_t txAddr = LPSPI_GetTxRegisterAddress(base);
-
- uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
-
- /*Because DMA is fast enough , so set the RX and TX watermarks to 0 .*/
- uint8_t txWatermark = 0;
- uint8_t rxWatermark = 0;
-
- /*Used for byte swap*/
- uint32_t dif = 0;
-
- uint8_t bytesLastWrite = 0;
-
- bool isThereExtraTxBytes = false;
-
- uint8_t dummyData = g_lpspiDummyData[instance];
-
- edma_transfer_config_t transferConfigRx;
- edma_transfer_config_t transferConfigTx;
-
- edma_tcd_t *softwareTCD_extraBytes = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[1]) & (~0x1FU));
- edma_tcd_t *softwareTCD_pcsContinuous = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[2]) & (~0x1FU));
-
- handle->txData = transfer->txData;
- handle->rxData = transfer->rxData;
- handle->txRemainingByteCount = transfer->dataSize;
- handle->rxRemainingByteCount = transfer->dataSize;
- handle->totalByteCount = transfer->dataSize;
-
- handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3U) / 4U);
- handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
-
- handle->txBuffIfNull =
- ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
-
- /*The TX and RX FIFO sizes are always the same*/
- handle->fifoSize = LPSPI_GetRxFifoSize(base);
-
- handle->isPcsContinuous = (bool)(transfer->configFlags & (uint32_t)kLPSPI_MasterPcsContinuous);
- handle->isByteSwap = (bool)(transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap);
- isPcsContinuous = handle->isPcsContinuous;
- isByteSwap = handle->isByteSwap;
-
- LPSPI_SetFifoWatermarks(base, txWatermark, rxWatermark);
-
- /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
- LPSPI_Enable(base, false);
- base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
- /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */
- temp = base->CFGR1;
- temp &= LPSPI_CFGR1_PINCFG_MASK;
- if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut)))
- {
- if (NULL == handle->txData)
- {
- base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK;
- }
- /* The 3-wire mode can't send and receive data at the same time. */
- if ((handle->txData != NULL) && (handle->rxData != NULL))
- {
- return kStatus_InvalidArgument;
- }
- }
-
- LPSPI_Enable(base, true);
-
- /*Flush FIFO , clear status , disable all the inerrupts.*/
- LPSPI_FlushFifo(base, true, true);
- LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
- LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
-
- /* For DMA transfer , we'd better not masked the transmit data and receive data in TCR since the transfer flow is
- * hard to controlled by software.
- */
- base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_BYSW_MASK | LPSPI_TCR_PCS_MASK)) |
- LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_CONTC(0U) | LPSPI_TCR_BYSW(isByteSwap) |
- LPSPI_TCR_PCS(whichPcs);
-
- isThereExtraTxBytes = false;
- handle->isThereExtraRxBytes = false;
-
- /*Calculate the bytes for write/read the TX/RX register each time*/
- if (bytesPerFrame <= 4U)
- {
- handle->bytesEachWrite = (uint8_t)bytesPerFrame;
- handle->bytesEachRead = (uint8_t)bytesPerFrame;
-
- handle->bytesLastRead = (uint8_t)bytesPerFrame;
- }
- else
- {
- handle->bytesEachWrite = 4U;
- handle->bytesEachRead = 4U;
-
- handle->bytesLastRead = 4U;
-
- if ((transfer->dataSize % 4U) != 0U)
- {
- bytesLastWrite = (uint8_t)(transfer->dataSize % 4U);
- handle->bytesLastRead = bytesLastWrite;
-
- isThereExtraTxBytes = true;
-
- --handle->writeRegRemainingTimes;
-
- --handle->readRegRemainingTimes;
- handle->isThereExtraRxBytes = true;
- }
- }
-
- LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
-
- EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_LpspiMasterCallback,
- &s_lpspiMasterEdmaPrivateHandle[instance]);
-
- /*Rx*/
- EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
-
- if (handle->rxData != NULL)
- {
- transferConfigRx.destAddr = (uint32_t) & (handle->rxData[0]);
- transferConfigRx.destOffset = 1;
- }
- else
- {
- transferConfigRx.destAddr = (uint32_t) & (handle->rxBuffIfNull);
- transferConfigRx.destOffset = 0;
- }
- transferConfigRx.destTransferSize = kEDMA_TransferSize1Bytes;
-
- dif = 0;
- switch (handle->bytesEachRead)
- {
- case (1U):
- transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigRx.minorLoopBytes = 1;
- if (handle->isByteSwap)
- {
- dif = 3;
- }
- break;
-
- case (2U):
- transferConfigRx.srcTransferSize = kEDMA_TransferSize2Bytes;
- transferConfigRx.minorLoopBytes = 2;
- if (handle->isByteSwap)
- {
- dif = 2;
- }
- break;
-
- case (4U):
- transferConfigRx.srcTransferSize = kEDMA_TransferSize4Bytes;
- transferConfigRx.minorLoopBytes = 4;
- break;
-
- default:
- transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigRx.minorLoopBytes = 1;
- assert(false);
- break;
- }
-
- transferConfigRx.srcAddr = (uint32_t)rxAddr + dif;
- transferConfigRx.srcOffset = 0;
-
- transferConfigRx.majorLoopCounts = handle->readRegRemainingTimes;
-
- /* Store the initially configured eDMA minor byte transfer count into the LPSPI handle */
- handle->nbytes = (uint8_t)transferConfigRx.minorLoopBytes;
-
- EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
- &transferConfigRx, NULL);
- EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
- (uint32_t)kEDMA_MajorInterruptEnable);
-
- /*Tx*/
- EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
-
- if (isThereExtraTxBytes)
- {
- if (handle->txData != NULL)
- {
- transferConfigTx.srcAddr = (uint32_t) & (transfer->txData[transfer->dataSize - bytesLastWrite]);
- transferConfigTx.srcOffset = 1;
- }
- else
- {
- transferConfigTx.srcAddr = (uint32_t)(&handle->txBuffIfNull);
- transferConfigTx.srcOffset = 0;
- }
-
- transferConfigTx.destOffset = 0;
-
- transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
-
- dif = 0;
- switch (bytesLastWrite)
- {
- case (1U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigTx.minorLoopBytes = 1;
- if (handle->isByteSwap)
- {
- dif = 3;
- }
- break;
-
- case (2U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
- transferConfigTx.minorLoopBytes = 2;
- if (handle->isByteSwap)
- {
- dif = 2;
- }
- break;
-
- default:
- transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigTx.minorLoopBytes = 1;
- assert(false);
- break;
- }
-
- transferConfigTx.destAddr = (uint32_t)txAddr + dif;
- transferConfigTx.majorLoopCounts = 1;
-
- EDMA_TcdReset(softwareTCD_extraBytes);
-
- if (handle->isPcsContinuous)
- {
- EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, softwareTCD_pcsContinuous);
- }
- else
- {
- EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, NULL);
- }
- }
-
- if (handle->isPcsContinuous)
- {
- handle->transmitCommand = base->TCR & ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK);
-
- transferConfigTx.srcAddr = (uint32_t) & (handle->transmitCommand);
- transferConfigTx.srcOffset = 0;
-
- transferConfigTx.destAddr = (uint32_t) & (base->TCR);
- transferConfigTx.destOffset = 0;
-
- transferConfigTx.srcTransferSize = kEDMA_TransferSize4Bytes;
- transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
- transferConfigTx.minorLoopBytes = 4;
- transferConfigTx.majorLoopCounts = 1;
-
- EDMA_TcdReset(softwareTCD_pcsContinuous);
- EDMA_TcdSetTransferConfig(softwareTCD_pcsContinuous, &transferConfigTx, NULL);
- }
-
- if (handle->txData != NULL)
- {
- transferConfigTx.srcAddr = (uint32_t)(handle->txData);
- transferConfigTx.srcOffset = 1;
- }
- else
- {
- transferConfigTx.srcAddr = (uint32_t)(&handle->txBuffIfNull);
- transferConfigTx.srcOffset = 0;
- }
-
- transferConfigTx.destOffset = 0;
-
- transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
-
- dif = 0U;
- switch (handle->bytesEachRead)
- {
- case (1U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigTx.minorLoopBytes = 1;
- if (handle->isByteSwap)
- {
- dif = 3;
- }
- break;
-
- case (2U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
- transferConfigTx.minorLoopBytes = 2;
-
- if (handle->isByteSwap)
- {
- dif = 2;
- }
- break;
-
- case (4U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
- transferConfigTx.minorLoopBytes = 4;
- break;
-
- default:
- transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigTx.minorLoopBytes = 1;
- assert(false);
- break;
- }
-
- transferConfigTx.destAddr = (uint32_t)txAddr + dif;
-
- transferConfigTx.majorLoopCounts = handle->writeRegRemainingTimes;
-
- if (isThereExtraTxBytes)
- {
- EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
- &transferConfigTx, softwareTCD_extraBytes);
- }
- else if (handle->isPcsContinuous)
- {
- EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
- &transferConfigTx, softwareTCD_pcsContinuous);
- }
- else
- {
- EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
- &transferConfigTx, NULL);
- }
-
- EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
- EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
-
- LPSPI_EnableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
-
- return kStatus_Success;
-}
-
-static void EDMA_LpspiMasterCallback(edma_handle_t *edmaHandle,
- void *g_lpspiEdmaPrivateHandle,
- bool transferDone,
- uint32_t tcds)
-{
- assert(edmaHandle);
- assert(g_lpspiEdmaPrivateHandle);
-
- uint32_t readData;
-
- lpspi_master_edma_private_handle_t *lpspiEdmaPrivateHandle;
-
- lpspiEdmaPrivateHandle = (lpspi_master_edma_private_handle_t *)g_lpspiEdmaPrivateHandle;
-
- size_t rxRemainingByteCount = lpspiEdmaPrivateHandle->handle->rxRemainingByteCount;
- uint8_t bytesLastRead = lpspiEdmaPrivateHandle->handle->bytesLastRead;
- bool isByteSwap = lpspiEdmaPrivateHandle->handle->isByteSwap;
-
- LPSPI_DisableDMA(lpspiEdmaPrivateHandle->base, (uint32_t)kLPSPI_TxDmaEnable | (uint32_t)kLPSPI_RxDmaEnable);
-
- if (lpspiEdmaPrivateHandle->handle->isThereExtraRxBytes)
- {
- while (LPSPI_GetRxFifoCount(lpspiEdmaPrivateHandle->base) == 0U)
- {
- }
- readData = LPSPI_ReadData(lpspiEdmaPrivateHandle->base);
-
- if (lpspiEdmaPrivateHandle->handle->rxData != NULL)
- {
- LPSPI_SeparateEdmaReadData(&(lpspiEdmaPrivateHandle->handle->rxData[rxRemainingByteCount - bytesLastRead]),
- readData, bytesLastRead, isByteSwap);
- }
- }
-
- lpspiEdmaPrivateHandle->handle->state = (uint8_t)kLPSPI_Idle;
-
- if (lpspiEdmaPrivateHandle->handle->callback != NULL)
- {
- lpspiEdmaPrivateHandle->handle->callback(lpspiEdmaPrivateHandle->base, lpspiEdmaPrivateHandle->handle,
- kStatus_Success, lpspiEdmaPrivateHandle->handle->userData);
- }
-}
-
-/*!
- * brief LPSPI master aborts a transfer which is using eDMA.
- *
- * This function aborts a transfer which is using eDMA.
- *
- * param base LPSPI peripheral base address.
- * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
- */
-void LPSPI_MasterTransferAbortEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle)
-{
- assert(handle);
-
- LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
-
- EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
- EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
-
- handle->state = (uint8_t)kLPSPI_Idle;
-}
-
-/*!
- * brief Gets the master eDMA transfer remaining bytes.
- *
- * This function gets the master eDMA transfer remaining bytes.
- *
- * param base LPSPI peripheral base address.
- * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
- * param count Number of bytes transferred so far by the EDMA transaction.
- * return status of status_t.
- */
-status_t LPSPI_MasterTransferGetCountEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, size_t *count)
-{
- assert(handle);
-
- if (NULL == count)
- {
- return kStatus_InvalidArgument;
- }
-
- /* Catch when there is not an active transfer. */
- if (handle->state != (uint8_t)kLPSPI_Busy)
- {
- *count = 0;
- return kStatus_NoTransferInProgress;
- }
-
- size_t remainingByte;
-
- remainingByte =
- (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
- handle->edmaRxRegToRxDataHandle->channel);
-
- *count = handle->totalByteCount - remainingByte;
-
- return kStatus_Success;
-}
-
-/*!
- * brief Initializes the LPSPI slave eDMA handle.
- *
- * This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs. Usually, for a
- * specified LPSPI instance, call this API once to get the initialized handle.
- *
- * Note that LPSPI eDMA has a separated (Rx and Tx as two sources) or shared (Rx and Tx as the same source) DMA request
- * source.
- *
- * (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
- * Tx DMAMUX source for edmaTxDataToTxRegHandle.
- * (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle .
- *
- * param base LPSPI peripheral base address.
- * param handle LPSPI handle pointer to lpspi_slave_edma_handle_t.
- * param callback LPSPI callback.
- * param userData callback function parameter.
- * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
- * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
- */
-void LPSPI_SlaveTransferCreateHandleEDMA(LPSPI_Type *base,
- lpspi_slave_edma_handle_t *handle,
- lpspi_slave_edma_transfer_callback_t callback,
- void *userData,
- edma_handle_t *edmaRxRegToRxDataHandle,
- edma_handle_t *edmaTxDataToTxRegHandle)
-{
- assert(handle);
- assert(edmaRxRegToRxDataHandle);
- assert(edmaTxDataToTxRegHandle);
-
- /* Zero the handle. */
- (void)memset(handle, 0, sizeof(*handle));
-
- uint32_t instance = LPSPI_GetInstance(base);
-
- s_lpspiSlaveEdmaPrivateHandle[instance].base = base;
- s_lpspiSlaveEdmaPrivateHandle[instance].handle = handle;
-
- handle->callback = callback;
- handle->userData = userData;
-
- handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
- handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
-}
-
-/*!
- * brief LPSPI slave transfers data using eDMA.
- *
- * This function transfers data using eDMA. This is a non-blocking function, which return right away. When all data
- * is transferred, the callback function is called.
- *
- * Note:
- * The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
- * For bytesPerFrame greater than 4:
- * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
- * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
- *
- * param base LPSPI peripheral base address.
- * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
- * param transfer pointer to lpspi_transfer_t structure.
- * return status of status_t.
- */
-status_t LPSPI_SlaveTransferEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, lpspi_transfer_t *transfer)
-{
- assert(handle);
- assert(transfer);
-
- uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1U;
- uint32_t bytesPerFrame = (bitsPerFrame + 7U) / 8U;
- uint32_t temp = 0U;
- bool isByteSwap;
-
- uint8_t dummyData = g_lpspiDummyData[LPSPI_GetInstance(base)];
-
- if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
- {
- return kStatus_InvalidArgument;
- }
-
- /*And since the dma transfer can not support 3 bytes .*/
- if ((bytesPerFrame % 4U) == 3U)
- {
- return kStatus_InvalidArgument;
- }
-
- /* Check that we're not busy.*/
- if (handle->state == (uint8_t)kLPSPI_Busy)
- {
- return kStatus_LPSPI_Busy;
- }
-
- handle->state = (uint8_t)kLPSPI_Busy;
-
- uint32_t rxAddr = LPSPI_GetRxRegisterAddress(base);
- uint32_t txAddr = LPSPI_GetTxRegisterAddress(base);
-
- edma_tcd_t *softwareTCD_extraBytes = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[1]) & (~0x1FU));
-
- uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
-
- /*Because DMA is fast enough , so set the RX and TX watermarks to 0 .*/
- uint8_t txWatermark = 0;
- uint8_t rxWatermark = 0;
-
- /*Used for byte swap*/
- uint32_t dif = 0;
-
- uint8_t bytesLastWrite = 0;
-
- uint32_t instance = LPSPI_GetInstance(base);
-
- edma_transfer_config_t transferConfigRx;
- edma_transfer_config_t transferConfigTx;
-
- bool isThereExtraTxBytes = false;
-
- handle->txData = transfer->txData;
- handle->rxData = transfer->rxData;
- handle->txRemainingByteCount = transfer->dataSize;
- handle->rxRemainingByteCount = transfer->dataSize;
- handle->totalByteCount = transfer->dataSize;
-
- handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3U) / 4U);
- handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
-
- handle->txBuffIfNull =
- ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
-
- /*The TX and RX FIFO sizes are always the same*/
- handle->fifoSize = LPSPI_GetRxFifoSize(base);
-
- handle->isByteSwap = ((transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
- isByteSwap = handle->isByteSwap;
-
- LPSPI_SetFifoWatermarks(base, txWatermark, rxWatermark);
-
- /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
- LPSPI_Enable(base, false);
- base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
- /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */
- temp = base->CFGR1;
- temp &= LPSPI_CFGR1_PINCFG_MASK;
- if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut)))
- {
- if (NULL == handle->txData)
- {
- base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK;
- }
- /* The 3-wire mode can't send and receive data at the same time. */
- if ((handle->txData != NULL) && (handle->rxData != NULL))
- {
- return kStatus_InvalidArgument;
- }
- }
-
- LPSPI_Enable(base, true);
-
- /*Flush FIFO , clear status , disable all the inerrupts.*/
- LPSPI_FlushFifo(base, true, true);
- LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
- LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
-
- /* For DMA transfer , we'd better not masked the transmit data and receive data in TCR since the transfer flow is
- * hard to controlled by software.
- */
- base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_BYSW_MASK)) |
- LPSPI_TCR_CONTC(0U) | LPSPI_TCR_BYSW(isByteSwap) | LPSPI_TCR_PCS(whichPcs);
-
- isThereExtraTxBytes = false;
- handle->isThereExtraRxBytes = false;
-
- /*Calculate the bytes for write/read the TX/RX register each time*/
- if (bytesPerFrame <= 4U)
- {
- handle->bytesEachWrite = (uint8_t)bytesPerFrame;
- handle->bytesEachRead = (uint8_t)bytesPerFrame;
-
- handle->bytesLastRead = (uint8_t)bytesPerFrame;
- }
- else
- {
- handle->bytesEachWrite = 4U;
- handle->bytesEachRead = 4U;
-
- handle->bytesLastRead = 4U;
-
- if ((transfer->dataSize % 4U) != 0U)
- {
- bytesLastWrite = (uint8_t)(transfer->dataSize % 4U);
- handle->bytesLastRead = bytesLastWrite;
-
- isThereExtraTxBytes = true;
- --handle->writeRegRemainingTimes;
-
- handle->isThereExtraRxBytes = true;
- --handle->readRegRemainingTimes;
- }
- }
-
- LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
-
- EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_LpspiSlaveCallback,
- &s_lpspiSlaveEdmaPrivateHandle[instance]);
-
- /*Rx*/
- if (handle->readRegRemainingTimes > 0U)
- {
- EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
-
- if (handle->rxData != NULL)
- {
- transferConfigRx.destAddr = (uint32_t) & (handle->rxData[0]);
- transferConfigRx.destOffset = 1;
- }
- else
- {
- transferConfigRx.destAddr = (uint32_t) & (handle->rxBuffIfNull);
- transferConfigRx.destOffset = 0;
- }
- transferConfigRx.destTransferSize = kEDMA_TransferSize1Bytes;
-
- dif = 0;
- switch (handle->bytesEachRead)
- {
- case (1U):
- transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigRx.minorLoopBytes = 1;
- if (handle->isByteSwap)
- {
- dif = 3;
- }
- break;
-
- case (2U):
- transferConfigRx.srcTransferSize = kEDMA_TransferSize2Bytes;
- transferConfigRx.minorLoopBytes = 2;
- if (handle->isByteSwap)
- {
- dif = 2;
- }
- break;
-
- case (4U):
- transferConfigRx.srcTransferSize = kEDMA_TransferSize4Bytes;
- transferConfigRx.minorLoopBytes = 4;
- break;
-
- default:
- transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigRx.minorLoopBytes = 1;
- assert(false);
- break;
- }
-
- transferConfigRx.srcAddr = (uint32_t)rxAddr + dif;
- transferConfigRx.srcOffset = 0;
-
- transferConfigRx.majorLoopCounts = handle->readRegRemainingTimes;
-
- /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
- handle->nbytes = (uint8_t)transferConfigRx.minorLoopBytes;
-
- EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
- &transferConfigRx, NULL);
- EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
- (uint32_t)kEDMA_MajorInterruptEnable);
- }
-
- /*Tx*/
- EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
-
- if (isThereExtraTxBytes)
- {
- if (handle->txData != NULL)
- {
- transferConfigTx.srcAddr = (uint32_t) & (transfer->txData[transfer->dataSize - bytesLastWrite]);
- transferConfigTx.srcOffset = 1;
- }
- else
- {
- transferConfigTx.srcAddr = (uint32_t)(&handle->txBuffIfNull);
- transferConfigTx.srcOffset = 0;
- }
-
- transferConfigTx.destOffset = 0;
-
- transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
-
- dif = 0;
- switch (bytesLastWrite)
- {
- case (1U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigTx.minorLoopBytes = 1;
- if (handle->isByteSwap)
- {
- dif = 3;
- }
- break;
-
- case (2U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
- transferConfigTx.minorLoopBytes = 2;
- if (handle->isByteSwap)
- {
- dif = 2;
- }
- break;
-
- default:
- transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigTx.minorLoopBytes = 1;
- assert(false);
- break;
- }
-
- transferConfigTx.destAddr = (uint32_t)txAddr + dif;
- transferConfigTx.majorLoopCounts = 1;
-
- EDMA_TcdReset(softwareTCD_extraBytes);
-
- EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, NULL);
- }
-
- if (handle->txData != NULL)
- {
- transferConfigTx.srcAddr = (uint32_t)(handle->txData);
- transferConfigTx.srcOffset = 1;
- }
- else
- {
- transferConfigTx.srcAddr = (uint32_t)(&handle->txBuffIfNull);
- transferConfigTx.srcOffset = 0;
- }
-
- transferConfigTx.destOffset = 0;
-
- transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
-
- dif = 0;
- switch (handle->bytesEachRead)
- {
- case (1U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigTx.minorLoopBytes = 1;
- if (handle->isByteSwap)
- {
- dif = 3;
- }
- break;
-
- case (2U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
- transferConfigTx.minorLoopBytes = 2;
-
- if (handle->isByteSwap)
- {
- dif = 2;
- }
- break;
-
- case (4U):
- transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
- transferConfigTx.minorLoopBytes = 4;
- break;
-
- default:
- transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
- transferConfigTx.minorLoopBytes = 1;
- assert(false);
- break;
- }
-
- transferConfigTx.destAddr = (uint32_t)txAddr + dif;
-
- transferConfigTx.majorLoopCounts = handle->writeRegRemainingTimes;
-
- if (isThereExtraTxBytes)
- {
- EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
- &transferConfigTx, softwareTCD_extraBytes);
- }
- else
- {
- EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
- &transferConfigTx, NULL);
- }
-
- EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
- EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
-
- LPSPI_EnableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
-
- return kStatus_Success;
-}
-
-static void EDMA_LpspiSlaveCallback(edma_handle_t *edmaHandle,
- void *g_lpspiEdmaPrivateHandle,
- bool transferDone,
- uint32_t tcds)
-{
- assert(edmaHandle);
- assert(g_lpspiEdmaPrivateHandle);
-
- uint32_t readData;
-
- lpspi_slave_edma_private_handle_t *lpspiEdmaPrivateHandle;
-
- lpspiEdmaPrivateHandle = (lpspi_slave_edma_private_handle_t *)g_lpspiEdmaPrivateHandle;
-
- size_t rxRemainingByteCount = lpspiEdmaPrivateHandle->handle->rxRemainingByteCount;
- uint8_t bytesLastRead = lpspiEdmaPrivateHandle->handle->bytesLastRead;
- bool isByteSwap = lpspiEdmaPrivateHandle->handle->isByteSwap;
-
- LPSPI_DisableDMA(lpspiEdmaPrivateHandle->base, (uint32_t)kLPSPI_TxDmaEnable | (uint32_t)kLPSPI_RxDmaEnable);
-
- if (lpspiEdmaPrivateHandle->handle->isThereExtraRxBytes)
- {
- while (LPSPI_GetRxFifoCount(lpspiEdmaPrivateHandle->base) == 0U)
- {
- }
- readData = LPSPI_ReadData(lpspiEdmaPrivateHandle->base);
-
- if (lpspiEdmaPrivateHandle->handle->rxData != NULL)
- {
- LPSPI_SeparateEdmaReadData(&(lpspiEdmaPrivateHandle->handle->rxData[rxRemainingByteCount - bytesLastRead]),
- readData, bytesLastRead, isByteSwap);
- }
- }
-
- lpspiEdmaPrivateHandle->handle->state = (uint8_t)kLPSPI_Idle;
-
- if (lpspiEdmaPrivateHandle->handle->callback != NULL)
- {
- lpspiEdmaPrivateHandle->handle->callback(lpspiEdmaPrivateHandle->base, lpspiEdmaPrivateHandle->handle,
- kStatus_Success, lpspiEdmaPrivateHandle->handle->userData);
- }
-}
-
-/*!
- * brief LPSPI slave aborts a transfer which is using eDMA.
- *
- * This function aborts a transfer which is using eDMA.
- *
- * param base LPSPI peripheral base address.
- * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
- */
-void LPSPI_SlaveTransferAbortEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle)
-{
- assert(handle);
-
- LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
-
- EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
- EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
-
- handle->state = (uint8_t)kLPSPI_Idle;
-}
-
-/*!
- * brief Gets the slave eDMA transfer remaining bytes.
- *
- * This function gets the slave eDMA transfer remaining bytes.
- *
- * param base LPSPI peripheral base address.
- * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
- * param count Number of bytes transferred so far by the eDMA transaction.
- * return status of status_t.
- */
-status_t LPSPI_SlaveTransferGetCountEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, size_t *count)
-{
- assert(handle);
-
- if (NULL == count)
- {
- return kStatus_InvalidArgument;
- }
-
- /* Catch when there is not an active transfer. */
- if (handle->state != (uint8_t)kLPSPI_Busy)
- {
- *count = 0;
- return kStatus_NoTransferInProgress;
- }
-
- size_t remainingByte;
-
- remainingByte =
- (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
- handle->edmaRxRegToRxDataHandle->channel);
-
- *count = handle->totalByteCount - remainingByte;
-
- return kStatus_Success;
-}