Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fsl_uart_edma.c Source File

fsl_uart_edma.c

00001 /*
00002  * Copyright (c) 2015, Freescale Semiconductor, Inc.
00003  * Copyright 2016-2017 NXP
00004  * All rights reserved.
00005  *
00006  * SPDX-License-Identifier: BSD-3-Clause
00007  */
00008 
00009 #include "fsl_uart_edma.h"
00010 #include "fsl_clock.h "
00011 
00012 /*******************************************************************************
00013  * Definitions
00014  ******************************************************************************/
00015 
00016 /* Component ID definition, used by tools. */
00017 #ifndef FSL_COMPONENT_ID
00018 #define FSL_COMPONENT_ID "platform.drivers.uart_edma"
00019 #endif
00020 
00021 /* Array of UART handle. */
00022 #if (defined(UART5))
00023 #define UART_HANDLE_ARRAY_SIZE 6
00024 #else /* UART5 */
00025 #if (defined(UART4))
00026 #define UART_HANDLE_ARRAY_SIZE 5
00027 #else /* UART4 */
00028 #if (defined(UART3))
00029 #define UART_HANDLE_ARRAY_SIZE 4
00030 #else /* UART3 */
00031 #if (defined(UART2))
00032 #define UART_HANDLE_ARRAY_SIZE 3
00033 #else /* UART2 */
00034 #if (defined(UART1))
00035 #define UART_HANDLE_ARRAY_SIZE 2
00036 #else /* UART1 */
00037 #if (defined(UART0))
00038 #define UART_HANDLE_ARRAY_SIZE 1
00039 #else /* UART0 */
00040 #error No UART instance.
00041 #endif /* UART 0 */
00042 #endif /* UART 1 */
00043 #endif /* UART 2 */
00044 #endif /* UART 3 */
00045 #endif /* UART 4 */
00046 #endif /* UART 5 */
00047 
00048 /*<! Structure definition for uart_edma_private_handle_t. The structure is private. */
00049 typedef struct _uart_edma_private_handle
00050 {
00051     UART_Type *base;
00052     uart_edma_handle_t *handle;
00053 } uart_edma_private_handle_t;
00054 
00055 /* UART EDMA transfer handle. */
00056 enum _uart_edma_tansfer_states
00057 {
00058     kUART_TxIdle, /* TX idle. */
00059     kUART_TxBusy, /* TX busy. */
00060     kUART_RxIdle, /* RX idle. */
00061     kUART_RxBusy  /* RX busy. */
00062 };
00063 
00064 /*******************************************************************************
00065  * Variables
00066  ******************************************************************************/
00067 
00068 /*<! Private handle only used for internally. */
00069 static uart_edma_private_handle_t s_edmaPrivateHandle[UART_HANDLE_ARRAY_SIZE];
00070 
00071 /*******************************************************************************
00072  * Prototypes
00073  ******************************************************************************/
00074 
00075 /*!
00076  * @brief UART EDMA send finished callback function.
00077  *
00078  * This function is called when UART EDMA send finished. It disables the UART
00079  * TX EDMA request and sends @ref kStatus_UART_TxIdle to UART callback.
00080  *
00081  * @param handle The EDMA handle.
00082  * @param param Callback function parameter.
00083  */
00084 static void UART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
00085 
00086 /*!
00087  * @brief UART EDMA receive finished callback function.
00088  *
00089  * This function is called when UART EDMA receive finished. It disables the UART
00090  * RX EDMA request and sends @ref kStatus_UART_RxIdle to UART callback.
00091  *
00092  * @param handle The EDMA handle.
00093  * @param param Callback function parameter.
00094  */
00095 static void UART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
00096 
00097 /*******************************************************************************
00098  * Code
00099  ******************************************************************************/
00100 
00101 static void UART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
00102 {
00103     assert(param);
00104 
00105     uart_edma_private_handle_t *uartPrivateHandle = (uart_edma_private_handle_t *)param;
00106 
00107     /* Avoid the warning for unused variables. */
00108     handle = handle;
00109     tcds = tcds;
00110 
00111     if (transferDone)
00112     {
00113         UART_TransferAbortSendEDMA(uartPrivateHandle->base, uartPrivateHandle->handle);
00114 
00115         if (uartPrivateHandle->handle->callback)
00116         {
00117             uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle, kStatus_UART_TxIdle ,
00118                                                 uartPrivateHandle->handle->userData);
00119         }
00120     }
00121 }
00122 
00123 static void UART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
00124 {
00125     assert(param);
00126 
00127     uart_edma_private_handle_t *uartPrivateHandle = (uart_edma_private_handle_t *)param;
00128 
00129     /* Avoid warning for unused parameters. */
00130     handle = handle;
00131     tcds = tcds;
00132 
00133     if (transferDone)
00134     {
00135         /* Disable transfer. */
00136         UART_TransferAbortReceiveEDMA(uartPrivateHandle->base, uartPrivateHandle->handle);
00137 
00138         if (uartPrivateHandle->handle->callback)
00139         {
00140             uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle, kStatus_UART_RxIdle ,
00141                                                 uartPrivateHandle->handle->userData);
00142         }
00143     }
00144 }
00145 
00146 /*!
00147  * brief Initializes the UART handle which is used in transactional functions.
00148  * param base UART peripheral base address.
00149  * param handle Pointer to the uart_edma_handle_t structure.
00150  * param callback UART callback, NULL means no callback.
00151  * param userData User callback function data.
00152  * param rxEdmaHandle User-requested DMA handle for RX DMA transfer.
00153  * param txEdmaHandle User-requested DMA handle for TX DMA transfer.
00154  */
00155 void UART_TransferCreateHandleEDMA(UART_Type *base,
00156                                    uart_edma_handle_t *handle,
00157                                    uart_edma_transfer_callback_t callback,
00158                                    void *userData,
00159                                    edma_handle_t *txEdmaHandle,
00160                                    edma_handle_t *rxEdmaHandle)
00161 {
00162     assert(handle);
00163 
00164     uint32_t instance = UART_GetInstance(base);
00165 
00166     s_edmaPrivateHandle[instance].base = base;
00167     s_edmaPrivateHandle[instance].handle = handle;
00168 
00169     memset(handle, 0, sizeof(*handle));
00170 
00171     handle->rxState  = kUART_RxIdle;
00172     handle->txState  = kUART_TxIdle;
00173 
00174     handle->rxEdmaHandle  = rxEdmaHandle;
00175     handle->txEdmaHandle  = txEdmaHandle;
00176 
00177     handle->callback  = callback;
00178     handle->userData  = userData;
00179 
00180 #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
00181     /* Note:
00182        Take care of the RX FIFO, EDMA request only assert when received bytes
00183        equal or more than RX water mark, there is potential issue if RX water
00184        mark larger than 1.
00185        For example, if RX FIFO water mark is 2, upper layer needs 5 bytes and
00186        5 bytes are received. the last byte will be saved in FIFO but not trigger
00187        EDMA transfer because the water mark is 2.
00188      */
00189     if (rxEdmaHandle)
00190     {
00191         base->RWFIFO = 1U;
00192     }
00193 #endif
00194 
00195     /* Configure TX. */
00196     if (txEdmaHandle)
00197     {
00198         EDMA_SetCallback(handle->txEdmaHandle , UART_SendEDMACallback, &s_edmaPrivateHandle[instance]);
00199     }
00200 
00201     /* Configure RX. */
00202     if (rxEdmaHandle)
00203     {
00204         EDMA_SetCallback(handle->rxEdmaHandle , UART_ReceiveEDMACallback, &s_edmaPrivateHandle[instance]);
00205     }
00206 }
00207 
00208 /*!
00209  * brief Sends data using eDMA.
00210  *
00211  * This function sends data using eDMA. This is a non-blocking function, which returns
00212  * right away. When all data is sent, the send callback function is called.
00213  *
00214  * param base UART peripheral base address.
00215  * param handle UART handle pointer.
00216  * param xfer UART eDMA transfer structure. See #uart_transfer_t.
00217  * retval kStatus_Success if succeeded; otherwise failed.
00218  * retval kStatus_UART_TxBusy Previous transfer ongoing.
00219  * retval kStatus_InvalidArgument Invalid argument.
00220  */
00221 status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer)
00222 {
00223     assert(handle);
00224     assert(handle->txEdmaHandle );
00225     assert(xfer);
00226     assert(xfer->data );
00227     assert(xfer->dataSize );
00228 
00229     edma_transfer_config_t xferConfig;
00230     status_t status;
00231 
00232     /* If previous TX not finished. */
00233     if (kUART_TxBusy == handle->txState )
00234     {
00235         status = kStatus_UART_TxBusy ;
00236     }
00237     else
00238     {
00239         handle->txState  = kUART_TxBusy;
00240         handle->txDataSizeAll  = xfer->dataSize ;
00241 
00242         /* Prepare transfer. */
00243         EDMA_PrepareTransfer(&xferConfig, xfer->data , sizeof(uint8_t), (void *)UART_GetDataRegisterAddress(base),
00244                              sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize , kEDMA_MemoryToPeripheral );
00245 
00246         /* Store the initially configured eDMA minor byte transfer count into the UART handle */
00247         handle->nbytes  = sizeof(uint8_t);
00248 
00249         /* Submit transfer. */
00250         EDMA_SubmitTransfer(handle->txEdmaHandle , &xferConfig);
00251         EDMA_StartTransfer(handle->txEdmaHandle );
00252 
00253         /* Enable UART TX EDMA. */
00254         UART_EnableTxDMA(base, true);
00255 
00256         status = kStatus_Success;
00257     }
00258 
00259     return status;
00260 }
00261 
00262 /*!
00263  * brief Receives data using eDMA.
00264  *
00265  * This function receives data using eDMA. This is a non-blocking function, which returns
00266  * right away. When all data is received, the receive callback function is called.
00267  *
00268  * param base UART peripheral base address.
00269  * param handle Pointer to the uart_edma_handle_t structure.
00270  * param xfer UART eDMA transfer structure. See #uart_transfer_t.
00271  * retval kStatus_Success if succeeded; otherwise failed.
00272  * retval kStatus_UART_RxBusy Previous transfer ongoing.
00273  * retval kStatus_InvalidArgument Invalid argument.
00274  */
00275 status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer)
00276 {
00277     assert(handle);
00278     assert(handle->rxEdmaHandle );
00279     assert(xfer);
00280     assert(xfer->data );
00281     assert(xfer->dataSize );
00282 
00283     edma_transfer_config_t xferConfig;
00284     status_t status;
00285 
00286     /* If previous RX not finished. */
00287     if (kUART_RxBusy == handle->rxState )
00288     {
00289         status = kStatus_UART_RxBusy ;
00290     }
00291     else
00292     {
00293         handle->rxState  = kUART_RxBusy;
00294         handle->rxDataSizeAll  = xfer->dataSize ;
00295 
00296         /* Prepare transfer. */
00297         EDMA_PrepareTransfer(&xferConfig, (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data ,
00298                              sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize , kEDMA_PeripheralToMemory );
00299 
00300         /* Store the initially configured eDMA minor byte transfer count into the UART handle */
00301         handle->nbytes  = sizeof(uint8_t);
00302 
00303         /* Submit transfer. */
00304         EDMA_SubmitTransfer(handle->rxEdmaHandle , &xferConfig);
00305         EDMA_StartTransfer(handle->rxEdmaHandle );
00306 
00307         /* Enable UART RX EDMA. */
00308         UART_EnableRxDMA(base, true);
00309 
00310         status = kStatus_Success;
00311     }
00312 
00313     return status;
00314 }
00315 
00316 /*!
00317  * brief Aborts the sent data using eDMA.
00318  *
00319  * This function aborts sent data using eDMA.
00320  *
00321  * param base UART peripheral base address.
00322  * param handle Pointer to the uart_edma_handle_t structure.
00323  */
00324 void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle)
00325 {
00326     assert(handle);
00327     assert(handle->txEdmaHandle );
00328 
00329     /* Disable UART TX EDMA. */
00330     UART_EnableTxDMA(base, false);
00331 
00332     /* Stop transfer. */
00333     EDMA_AbortTransfer(handle->txEdmaHandle );
00334 
00335     handle->txState  = kUART_TxIdle;
00336 }
00337 
00338 /*!
00339  * brief Aborts the receive data using eDMA.
00340  *
00341  * This function aborts receive data using eDMA.
00342  *
00343  * param base UART peripheral base address.
00344  * param handle Pointer to the uart_edma_handle_t structure.
00345  */
00346 void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle)
00347 {
00348     assert(handle);
00349     assert(handle->rxEdmaHandle );
00350 
00351     /* Disable UART RX EDMA. */
00352     UART_EnableRxDMA(base, false);
00353 
00354     /* Stop transfer. */
00355     EDMA_AbortTransfer(handle->rxEdmaHandle );
00356 
00357     handle->rxState  = kUART_RxIdle;
00358 }
00359 
00360 /*!
00361  * brief Gets the number of received bytes.
00362  *
00363  * This function gets the number of received bytes.
00364  *
00365  * param base UART peripheral base address.
00366  * param handle UART handle pointer.
00367  * param count Receive bytes count.
00368  * retval kStatus_NoTransferInProgress No receive in progress.
00369  * retval kStatus_InvalidArgument Parameter is invalid.
00370  * retval kStatus_Success Get successfully through the parameter \p count;
00371  */
00372 status_t UART_TransferGetReceiveCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count)
00373 {
00374     assert(handle);
00375     assert(handle->rxEdmaHandle );
00376     assert(count);
00377 
00378     if (kUART_RxIdle == handle->rxState )
00379     {
00380         return kStatus_NoTransferInProgress;
00381     }
00382 
00383     *count = handle->rxDataSizeAll  -
00384              (uint32_t)handle->nbytes  *
00385                  EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle ->base , handle->rxEdmaHandle ->channel );
00386 
00387     return kStatus_Success;
00388 }
00389 
00390 /*!
00391  * brief Gets the number of bytes that have been written to UART TX register.
00392  *
00393  * This function gets the number of bytes that have been written to UART TX
00394  * register by DMA.
00395  *
00396  * param base UART peripheral base address.
00397  * param handle UART handle pointer.
00398  * param count Send bytes count.
00399  * retval kStatus_NoTransferInProgress No send in progress.
00400  * retval kStatus_InvalidArgument Parameter is invalid.
00401  * retval kStatus_Success Get successfully through the parameter \p count;
00402  */
00403 status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count)
00404 {
00405     assert(handle);
00406     assert(handle->txEdmaHandle );
00407     assert(count);
00408 
00409     if (kUART_TxIdle == handle->txState )
00410     {
00411         return kStatus_NoTransferInProgress;
00412     }
00413 
00414     *count = handle->txDataSizeAll  -
00415              (uint32_t)handle->nbytes  *
00416                  EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle ->base , handle->txEdmaHandle ->channel );
00417 
00418     return kStatus_Success;
00419 }