Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:59

0001 /*
0002  * Copyright (c) 2015, Freescale Semiconductor, Inc.
0003  * Copyright 2016-2020 NXP
0004  * All rights reserved.
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_flexio_uart_edma.h"
0010 
0011 /*******************************************************************************
0012  * Definitions
0013  ******************************************************************************/
0014 
0015 /* Component ID definition, used by tools. */
0016 #ifndef FSL_COMPONENT_ID
0017 #define FSL_COMPONENT_ID "platform.drivers.flexio_uart_edma"
0018 #endif
0019 
0020 /*<! Structure definition for uart_edma_private_handle_t. The structure is private. */
0021 typedef struct _flexio_uart_edma_private_handle
0022 {
0023     FLEXIO_UART_Type *base;
0024     flexio_uart_edma_handle_t *handle;
0025 } flexio_uart_edma_private_handle_t;
0026 
0027 /* UART EDMA transfer handle. */
0028 enum _flexio_uart_edma_tansfer_states
0029 {
0030     kFLEXIO_UART_TxIdle, /* TX idle. */
0031     kFLEXIO_UART_TxBusy, /* TX busy. */
0032     kFLEXIO_UART_RxIdle, /* RX idle. */
0033     kFLEXIO_UART_RxBusy  /* RX busy. */
0034 };
0035 
0036 /*******************************************************************************
0037  * Variables
0038  ******************************************************************************/
0039 
0040 /*< @brief user configurable flexio uart handle count. */
0041 #define FLEXIO_UART_HANDLE_COUNT 2
0042 
0043 /*<! Private handle only used for internally. */
0044 static flexio_uart_edma_private_handle_t s_edmaPrivateHandle[FLEXIO_UART_HANDLE_COUNT];
0045 
0046 /*******************************************************************************
0047  * Prototypes
0048  ******************************************************************************/
0049 
0050 /*!
0051  * @brief FLEXIO UART EDMA send finished callback function.
0052  *
0053  * This function is called when FLEXIO UART EDMA send finished. It disables the UART
0054  * TX EDMA request and sends @ref kStatus_FLEXIO_UART_TxIdle to FLEXIO UART callback.
0055  *
0056  * @param handle The EDMA handle.
0057  * @param param Callback function parameter.
0058  */
0059 static void FLEXIO_UART_TransferSendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
0060 
0061 /*!
0062  * @brief FLEXIO UART EDMA receive finished callback function.
0063  *
0064  * This function is called when FLEXIO UART EDMA receive finished. It disables the UART
0065  * RX EDMA request and sends @ref kStatus_FLEXIO_UART_RxIdle to UART callback.
0066  *
0067  * @param handle The EDMA handle.
0068  * @param param Callback function parameter.
0069  */
0070 static void FLEXIO_UART_TransferReceiveEDMACallback(edma_handle_t *handle,
0071                                                     void *param,
0072                                                     bool transferDone,
0073                                                     uint32_t tcds);
0074 
0075 /*******************************************************************************
0076  * Code
0077  ******************************************************************************/
0078 
0079 static void FLEXIO_UART_TransferSendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
0080 {
0081     flexio_uart_edma_private_handle_t *uartPrivateHandle = (flexio_uart_edma_private_handle_t *)param;
0082 
0083     assert(uartPrivateHandle->handle != NULL);
0084 
0085     /* Avoid the warning for unused variables. */
0086     handle = handle;
0087     tcds   = tcds;
0088 
0089     if (transferDone)
0090     {
0091         FLEXIO_UART_TransferAbortSendEDMA(uartPrivateHandle->base, uartPrivateHandle->handle);
0092 
0093         if (uartPrivateHandle->handle->callback != NULL)
0094         {
0095             uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle,
0096                                                 kStatus_FLEXIO_UART_TxIdle, uartPrivateHandle->handle->userData);
0097         }
0098     }
0099 }
0100 
0101 static void FLEXIO_UART_TransferReceiveEDMACallback(edma_handle_t *handle,
0102                                                     void *param,
0103                                                     bool transferDone,
0104                                                     uint32_t tcds)
0105 {
0106     flexio_uart_edma_private_handle_t *uartPrivateHandle = (flexio_uart_edma_private_handle_t *)param;
0107 
0108     assert(uartPrivateHandle->handle != NULL);
0109 
0110     /* Avoid the warning for unused variables. */
0111     handle = handle;
0112     tcds   = tcds;
0113 
0114     if (transferDone)
0115     {
0116         /* Disable transfer. */
0117         FLEXIO_UART_TransferAbortReceiveEDMA(uartPrivateHandle->base, uartPrivateHandle->handle);
0118 
0119         if (uartPrivateHandle->handle->callback != NULL)
0120         {
0121             uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle,
0122                                                 kStatus_FLEXIO_UART_RxIdle, uartPrivateHandle->handle->userData);
0123         }
0124     }
0125 }
0126 
0127 /*!
0128  * brief Initializes the UART handle which is used in transactional functions.
0129  *
0130  * param base Pointer to FLEXIO_UART_Type.
0131  * param handle Pointer to flexio_uart_edma_handle_t structure.
0132  * param callback The callback function.
0133  * param userData The parameter of the callback function.
0134  * param rxEdmaHandle User requested DMA handle for RX DMA transfer.
0135  * param txEdmaHandle User requested DMA handle for TX DMA transfer.
0136  * retval kStatus_Success Successfully create the handle.
0137  * retval kStatus_OutOfRange The FlexIO SPI eDMA type/handle table out of range.
0138  */
0139 status_t FLEXIO_UART_TransferCreateHandleEDMA(FLEXIO_UART_Type *base,
0140                                               flexio_uart_edma_handle_t *handle,
0141                                               flexio_uart_edma_transfer_callback_t callback,
0142                                               void *userData,
0143                                               edma_handle_t *txEdmaHandle,
0144                                               edma_handle_t *rxEdmaHandle)
0145 {
0146     assert(handle != NULL);
0147 
0148     uint8_t index = 0U;
0149 
0150     /* Find the an empty handle pointer to store the handle. */
0151     for (index = 0U; index < (uint8_t)FLEXIO_UART_HANDLE_COUNT; index++)
0152     {
0153         if (s_edmaPrivateHandle[index].base == NULL)
0154         {
0155             s_edmaPrivateHandle[index].base   = base;
0156             s_edmaPrivateHandle[index].handle = handle;
0157             break;
0158         }
0159     }
0160 
0161     if (index == (uint8_t)FLEXIO_UART_HANDLE_COUNT)
0162     {
0163         return kStatus_OutOfRange;
0164     }
0165 
0166     (void)memset(handle, 0, sizeof(*handle));
0167 
0168     handle->rxState = (uint8_t)kFLEXIO_UART_RxIdle;
0169     handle->txState = (uint8_t)kFLEXIO_UART_TxIdle;
0170 
0171     handle->rxEdmaHandle = rxEdmaHandle;
0172     handle->txEdmaHandle = txEdmaHandle;
0173 
0174     handle->callback = callback;
0175     handle->userData = userData;
0176 
0177     /* Configure TX. */
0178     if (txEdmaHandle != NULL)
0179     {
0180         EDMA_SetCallback(handle->txEdmaHandle, FLEXIO_UART_TransferSendEDMACallback, &s_edmaPrivateHandle);
0181     }
0182 
0183     /* Configure RX. */
0184     if (rxEdmaHandle != NULL)
0185     {
0186         EDMA_SetCallback(handle->rxEdmaHandle, FLEXIO_UART_TransferReceiveEDMACallback, &s_edmaPrivateHandle);
0187     }
0188 
0189     return kStatus_Success;
0190 }
0191 
0192 /*!
0193  * brief Sends data using eDMA.
0194  *
0195  * This function sends data using eDMA. This is a non-blocking function, which returns
0196  * right away. When all data is sent out, the send callback function is called.
0197  *
0198  * param base Pointer to FLEXIO_UART_Type
0199  * param handle UART handle pointer.
0200  * param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t.
0201  * retval kStatus_Success if succeed, others failed.
0202  * retval kStatus_FLEXIO_UART_TxBusy Previous transfer on going.
0203  */
0204 status_t FLEXIO_UART_TransferSendEDMA(FLEXIO_UART_Type *base,
0205                                       flexio_uart_edma_handle_t *handle,
0206                                       flexio_uart_transfer_t *xfer)
0207 {
0208     assert(handle->txEdmaHandle != NULL);
0209 
0210     edma_transfer_config_t xferConfig;
0211     status_t status;
0212 
0213     /* Return error if xfer invalid. */
0214     if ((0U == xfer->dataSize) || (NULL == xfer->data))
0215     {
0216         return kStatus_InvalidArgument;
0217     }
0218 
0219     /* If previous TX not finished. */
0220     if ((uint8_t)kFLEXIO_UART_TxBusy == handle->txState)
0221     {
0222         status = kStatus_FLEXIO_UART_TxBusy;
0223     }
0224     else
0225     {
0226         handle->txState       = (uint8_t)kFLEXIO_UART_TxBusy;
0227         handle->txDataSizeAll = xfer->dataSize;
0228 
0229         /* Prepare transfer. */
0230         EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t),
0231                              (uint32_t *)FLEXIO_UART_GetTxDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t),
0232                              xfer->dataSize, kEDMA_MemoryToPeripheral);
0233 
0234         /* Store the initially configured eDMA minor byte transfer count into the FLEXIO UART handle */
0235         handle->nbytes = 1U;
0236 
0237         /* Submit transfer. */
0238         (void)EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig);
0239         EDMA_StartTransfer(handle->txEdmaHandle);
0240 
0241         /* Enable UART TX EDMA. */
0242         FLEXIO_UART_EnableTxDMA(base, true);
0243 
0244         status = kStatus_Success;
0245     }
0246 
0247     return status;
0248 }
0249 
0250 /*!
0251  * brief Receives data using eDMA.
0252  *
0253  * This function receives data using eDMA. This is a non-blocking function, which returns
0254  * right away. When all data is received, the receive callback function is called.
0255  *
0256  * param base Pointer to FLEXIO_UART_Type
0257  * param handle Pointer to flexio_uart_edma_handle_t structure
0258  * param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t.
0259  * retval kStatus_Success if succeed, others failed.
0260  * retval kStatus_UART_RxBusy Previous transfer on going.
0261  */
0262 status_t FLEXIO_UART_TransferReceiveEDMA(FLEXIO_UART_Type *base,
0263                                          flexio_uart_edma_handle_t *handle,
0264                                          flexio_uart_transfer_t *xfer)
0265 {
0266     assert(handle->rxEdmaHandle != NULL);
0267 
0268     edma_transfer_config_t xferConfig;
0269     status_t status;
0270 
0271     /* Return error if xfer invalid. */
0272     if ((0U == xfer->dataSize) || (NULL == xfer->data))
0273     {
0274         return kStatus_InvalidArgument;
0275     }
0276 
0277     /* If previous RX not finished. */
0278     if ((uint8_t)kFLEXIO_UART_RxBusy == handle->rxState)
0279     {
0280         status = kStatus_FLEXIO_UART_RxBusy;
0281     }
0282     else
0283     {
0284         handle->rxState       = (uint8_t)kFLEXIO_UART_RxBusy;
0285         handle->rxDataSizeAll = xfer->dataSize;
0286 
0287         /* Prepare transfer. */
0288         EDMA_PrepareTransfer(&xferConfig, (uint32_t *)FLEXIO_UART_GetRxDataRegisterAddress(base), sizeof(uint8_t),
0289                              xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory);
0290 
0291         /* Store the initially configured eDMA minor byte transfer count into the FLEXIO UART handle */
0292         handle->nbytes = (uint8_t)sizeof(uint8_t);
0293 
0294         /* Submit transfer. */
0295         (void)EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig);
0296         EDMA_StartTransfer(handle->rxEdmaHandle);
0297 
0298         /* Enable UART RX EDMA. */
0299         FLEXIO_UART_EnableRxDMA(base, true);
0300 
0301         status = kStatus_Success;
0302     }
0303 
0304     return status;
0305 }
0306 
0307 /*!
0308  * brief Aborts the sent data which using eDMA.
0309  *
0310  * This function aborts sent data which using eDMA.
0311  *
0312  * param base Pointer to FLEXIO_UART_Type
0313  * param handle Pointer to flexio_uart_edma_handle_t structure
0314  */
0315 void FLEXIO_UART_TransferAbortSendEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle)
0316 {
0317     assert(handle->txEdmaHandle != NULL);
0318 
0319     /* Disable UART TX EDMA. */
0320     FLEXIO_UART_EnableTxDMA(base, false);
0321 
0322     /* Stop transfer. */
0323     EDMA_StopTransfer(handle->txEdmaHandle);
0324 
0325     handle->txState = (uint8_t)kFLEXIO_UART_TxIdle;
0326 }
0327 
0328 /*!
0329  * brief Aborts the receive data which using eDMA.
0330  *
0331  * This function aborts the receive data which using eDMA.
0332  *
0333  * param base Pointer to FLEXIO_UART_Type
0334  * param handle Pointer to flexio_uart_edma_handle_t structure
0335  */
0336 void FLEXIO_UART_TransferAbortReceiveEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle)
0337 {
0338     assert(handle->rxEdmaHandle != NULL);
0339 
0340     /* Disable UART RX EDMA. */
0341     FLEXIO_UART_EnableRxDMA(base, false);
0342 
0343     /* Stop transfer. */
0344     EDMA_StopTransfer(handle->rxEdmaHandle);
0345 
0346     handle->rxState = (uint8_t)kFLEXIO_UART_RxIdle;
0347 }
0348 
0349 /*!
0350  * brief Gets the number of bytes received.
0351  *
0352  * This function gets the number of bytes received.
0353  *
0354  * param base Pointer to FLEXIO_UART_Type
0355  * param handle Pointer to flexio_uart_edma_handle_t structure
0356  * param count Number of bytes received so far by the non-blocking transaction.
0357  * retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
0358  * retval kStatus_Success Successfully return the count.
0359  */
0360 status_t FLEXIO_UART_TransferGetReceiveCountEDMA(FLEXIO_UART_Type *base,
0361                                                  flexio_uart_edma_handle_t *handle,
0362                                                  size_t *count)
0363 {
0364     assert(handle != NULL);
0365     assert(handle->rxEdmaHandle != NULL);
0366     assert(count != NULL);
0367 
0368     if ((uint8_t)kFLEXIO_UART_RxIdle == handle->rxState)
0369     {
0370         return kStatus_NoTransferInProgress;
0371     }
0372 
0373     *count = handle->rxDataSizeAll -
0374              (uint32_t)handle->nbytes *
0375                  EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel);
0376 
0377     return kStatus_Success;
0378 }
0379 
0380 /*!
0381  * brief Gets the number of bytes sent out.
0382  *
0383  * This function gets the number of bytes sent out.
0384  *
0385  * param base Pointer to FLEXIO_UART_Type
0386  * param handle Pointer to flexio_uart_edma_handle_t structure
0387  * param count Number of bytes sent so far by the non-blocking transaction.
0388  * retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
0389  * retval kStatus_Success Successfully return the count.
0390  */
0391 status_t FLEXIO_UART_TransferGetSendCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, size_t *count)
0392 {
0393     assert(handle != NULL);
0394     assert(handle->txEdmaHandle != NULL);
0395     assert(count != NULL);
0396 
0397     if ((uint8_t)kFLEXIO_UART_TxIdle == handle->txState)
0398     {
0399         return kStatus_NoTransferInProgress;
0400     }
0401 
0402     *count = handle->txDataSizeAll -
0403              (uint32_t)handle->nbytes *
0404                  EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel);
0405 
0406     return kStatus_Success;
0407 }