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.
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 }
Generated on Tue Jul 12 2022 15:37:18 by
