2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
\r
3 * Copyright 2016-2018 NXP
\r
4 * All rights reserved.
\r
6 * SPDX-License-Identifier: BSD-3-Clause
\r
9 #include "fsl_usart.h"
\r
10 #include "fsl_device_registers.h"
\r
11 #include "fsl_flexcomm.h"
\r
13 /* Component ID definition, used by tools. */
\r
14 #ifndef FSL_COMPONENT_ID
\r
15 #define FSL_COMPONENT_ID "platform.drivers.flexcomm_usart"
\r
18 enum _usart_transfer_states
\r
20 kUSART_TxIdle, /* TX idle. */
\r
21 kUSART_TxBusy, /* TX busy. */
\r
22 kUSART_RxIdle, /* RX idle. */
\r
23 kUSART_RxBusy /* RX busy. */
\r
26 /*******************************************************************************
\r
28 ******************************************************************************/
\r
30 /*! @brief IRQ name array */
\r
31 static const IRQn_Type s_usartIRQ[] = USART_IRQS;
\r
33 /*! @brief Array to map USART instance number to base address. */
\r
34 static const uint32_t s_usartBaseAddrs[FSL_FEATURE_SOC_USART_COUNT] = USART_BASE_ADDRS;
\r
36 /*******************************************************************************
\r
38 ******************************************************************************/
\r
40 /* Get the index corresponding to the USART */
\r
41 /*! brief Returns instance number for USART peripheral base address. */
\r
42 uint32_t USART_GetInstance(USART_Type *base)
\r
46 for (i = 0; i < FSL_FEATURE_SOC_USART_COUNT; i++)
\r
48 if ((uint32_t)base == s_usartBaseAddrs[i])
\r
59 * brief Get the length of received data in RX ring buffer.
\r
61 * param handle USART handle pointer.
\r
62 * return Length of received data in RX ring buffer.
\r
64 size_t USART_TransferGetRxRingBufferLength(usart_handle_t *handle)
\r
68 /* Check arguments */
\r
69 assert(NULL != handle);
\r
71 if (handle->rxRingBufferTail > handle->rxRingBufferHead)
\r
73 size = (size_t)(handle->rxRingBufferHead + handle->rxRingBufferSize - handle->rxRingBufferTail);
\r
77 size = (size_t)(handle->rxRingBufferHead - handle->rxRingBufferTail);
\r
82 static bool USART_TransferIsRxRingBufferFull(usart_handle_t *handle)
\r
86 /* Check arguments */
\r
87 assert(NULL != handle);
\r
89 if (USART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
\r
101 * brief Sets up the RX ring buffer.
\r
103 * This function sets up the RX ring buffer to a specific USART handle.
\r
105 * When the RX ring buffer is used, data received are stored into the ring buffer even when the
\r
106 * user doesn't call the USART_TransferReceiveNonBlocking() API. If there is already data received
\r
107 * in the ring buffer, the user can get the received data from the ring buffer directly.
\r
109 * note When using the RX ring buffer, one byte is reserved for internal use. In other
\r
110 * words, if p ringBufferSize is 32, then only 31 bytes are used for saving data.
\r
112 * param base USART peripheral base address.
\r
113 * param handle USART handle pointer.
\r
114 * param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer.
\r
115 * param ringBufferSize size of the ring buffer.
\r
117 void USART_TransferStartRingBuffer(USART_Type *base, usart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize)
\r
119 /* Check arguments */
\r
120 assert(NULL != base);
\r
121 assert(NULL != handle);
\r
122 assert(NULL != ringBuffer);
\r
124 /* Setup the ringbuffer address */
\r
125 handle->rxRingBuffer = ringBuffer;
\r
126 handle->rxRingBufferSize = ringBufferSize;
\r
127 handle->rxRingBufferHead = 0U;
\r
128 handle->rxRingBufferTail = 0U;
\r
129 /* ring buffer is ready we can start receiving data */
\r
130 base->FIFOINTENSET |= USART_FIFOINTENSET_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
\r
134 * brief Aborts the background transfer and uninstalls the ring buffer.
\r
136 * This function aborts the background transfer and uninstalls the ring buffer.
\r
138 * param base USART peripheral base address.
\r
139 * param handle USART handle pointer.
\r
141 void USART_TransferStopRingBuffer(USART_Type *base, usart_handle_t *handle)
\r
143 /* Check arguments */
\r
144 assert(NULL != base);
\r
145 assert(NULL != handle);
\r
147 if (handle->rxState == kUSART_RxIdle)
\r
149 base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENCLR_RXERR_MASK;
\r
151 handle->rxRingBuffer = NULL;
\r
152 handle->rxRingBufferSize = 0U;
\r
153 handle->rxRingBufferHead = 0U;
\r
154 handle->rxRingBufferTail = 0U;
\r
158 * brief Initializes a USART instance with user configuration structure and peripheral clock.
\r
160 * This function configures the USART module with the user-defined settings. The user can configure the configuration
\r
161 * structure and also get the default configuration by using the USART_GetDefaultConfig() function.
\r
162 * Example below shows how to use this API to configure USART.
\r
164 * usart_config_t usartConfig;
\r
165 * usartConfig.baudRate_Bps = 115200U;
\r
166 * usartConfig.parityMode = kUSART_ParityDisabled;
\r
167 * usartConfig.stopBitCount = kUSART_OneStopBit;
\r
168 * USART_Init(USART1, &usartConfig, 20000000U);
\r
171 * param base USART peripheral base address.
\r
172 * param config Pointer to user-defined configuration structure.
\r
173 * param srcClock_Hz USART clock source frequency in HZ.
\r
174 * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
\r
175 * retval kStatus_InvalidArgument USART base address is not valid
\r
176 * retval kStatus_Success Status USART initialize succeed
\r
178 status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz)
\r
182 /* check arguments */
\r
183 assert(!((NULL == base) || (NULL == config) || (0 == srcClock_Hz)));
\r
184 if ((NULL == base) || (NULL == config) || (0 == srcClock_Hz))
\r
186 return kStatus_InvalidArgument;
\r
189 /* initialize flexcomm to USART mode */
\r
190 result = FLEXCOMM_Init(base, FLEXCOMM_PERIPH_USART);
\r
191 if (kStatus_Success != result)
\r
196 /* setup baudrate */
\r
197 result = USART_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
\r
198 if (kStatus_Success != result)
\r
203 if (config->enableTx)
\r
205 /* empty and enable txFIFO */
\r
206 base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK | USART_FIFOCFG_ENABLETX_MASK;
\r
207 /* setup trigger level */
\r
208 base->FIFOTRIG &= ~(USART_FIFOTRIG_TXLVL_MASK);
\r
209 base->FIFOTRIG |= USART_FIFOTRIG_TXLVL(config->txWatermark);
\r
210 /* enable trigger interrupt */
\r
211 base->FIFOTRIG |= USART_FIFOTRIG_TXLVLENA_MASK;
\r
214 /* empty and enable rxFIFO */
\r
215 if (config->enableRx)
\r
217 base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK | USART_FIFOCFG_ENABLERX_MASK;
\r
218 /* setup trigger level */
\r
219 base->FIFOTRIG &= ~(USART_FIFOTRIG_RXLVL_MASK);
\r
220 base->FIFOTRIG |= USART_FIFOTRIG_RXLVL(config->rxWatermark);
\r
221 /* enable trigger interrupt */
\r
222 base->FIFOTRIG |= USART_FIFOTRIG_RXLVLENA_MASK;
\r
224 /* setup configuration and enable USART */
\r
225 base->CFG = USART_CFG_PARITYSEL(config->parityMode) | USART_CFG_STOPLEN(config->stopBitCount) |
\r
226 USART_CFG_DATALEN(config->bitCountPerChar) | USART_CFG_LOOP(config->loopback) | USART_CFG_ENABLE_MASK;
\r
227 return kStatus_Success;
\r
231 * brief Deinitializes a USART instance.
\r
233 * This function waits for TX complete, disables TX and RX, and disables the USART clock.
\r
235 * param base USART peripheral base address.
\r
237 void USART_Deinit(USART_Type *base)
\r
239 /* Check arguments */
\r
240 assert(NULL != base);
\r
241 while (!(base->STAT & USART_STAT_TXIDLE_MASK))
\r
244 /* Disable interrupts, disable dma requests, disable peripheral */
\r
245 base->FIFOINTENCLR = USART_FIFOINTENCLR_TXERR_MASK | USART_FIFOINTENCLR_RXERR_MASK | USART_FIFOINTENCLR_TXLVL_MASK |
\r
246 USART_FIFOINTENCLR_RXLVL_MASK;
\r
247 base->FIFOCFG &= ~(USART_FIFOCFG_DMATX_MASK | USART_FIFOCFG_DMARX_MASK);
\r
248 base->CFG &= ~(USART_CFG_ENABLE_MASK);
\r
252 * brief Gets the default configuration structure.
\r
254 * This function initializes the USART configuration structure to a default value. The default
\r
256 * usartConfig->baudRate_Bps = 115200U;
\r
257 * usartConfig->parityMode = kUSART_ParityDisabled;
\r
258 * usartConfig->stopBitCount = kUSART_OneStopBit;
\r
259 * usartConfig->bitCountPerChar = kUSART_8BitsPerChar;
\r
260 * usartConfig->loopback = false;
\r
261 * usartConfig->enableTx = false;
\r
262 * usartConfig->enableRx = false;
\r
264 * param config Pointer to configuration structure.
\r
266 void USART_GetDefaultConfig(usart_config_t *config)
\r
268 /* Check arguments */
\r
269 assert(NULL != config);
\r
271 /* Initializes the configure structure to zero. */
\r
272 memset(config, 0, sizeof(*config));
\r
274 /* Set always all members ! */
\r
275 config->baudRate_Bps = 115200U;
\r
276 config->parityMode = kUSART_ParityDisabled;
\r
277 config->stopBitCount = kUSART_OneStopBit;
\r
278 config->bitCountPerChar = kUSART_8BitsPerChar;
\r
279 config->loopback = false;
\r
280 config->enableRx = false;
\r
281 config->enableTx = false;
\r
282 config->txWatermark = kUSART_TxFifo0;
\r
283 config->rxWatermark = kUSART_RxFifo1;
\r
287 * brief Sets the USART instance baud rate.
\r
289 * This function configures the USART module baud rate. This function is used to update
\r
290 * the USART module baud rate after the USART module is initialized by the USART_Init.
\r
292 * USART_SetBaudRate(USART1, 115200U, 20000000U);
\r
295 * param base USART peripheral base address.
\r
296 * param baudrate_Bps USART baudrate to be set.
\r
297 * param srcClock_Hz USART clock source freqency in HZ.
\r
298 * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.
\r
299 * retval kStatus_Success Set baudrate succeed.
\r
300 * retval kStatus_InvalidArgument One or more arguments are invalid.
\r
302 status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)
\r
304 uint32_t best_diff = (uint32_t)-1, best_osrval = 0xf, best_brgval = (uint32_t)-1;
\r
305 uint32_t osrval, brgval, diff, baudrate;
\r
307 /* check arguments */
\r
308 assert(!((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz)));
\r
309 if ((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz))
\r
311 return kStatus_InvalidArgument;
\r
315 * Smaller values of OSR can make the sampling position within a data bit less accurate and may
\r
316 * potentially cause more noise errors or incorrect data.
\r
318 for (osrval = best_osrval; osrval >= 8; osrval--)
\r
320 brgval = (srcClock_Hz / ((osrval + 1) * baudrate_Bps)) - 1;
\r
321 if (brgval > 0xFFFF)
\r
325 baudrate = srcClock_Hz / ((osrval + 1) * (brgval + 1));
\r
326 diff = baudrate_Bps < baudrate ? baudrate - baudrate_Bps : baudrate_Bps - baudrate;
\r
327 if (diff < best_diff)
\r
330 best_osrval = osrval;
\r
331 best_brgval = brgval;
\r
335 /* value over range */
\r
336 if (best_brgval > 0xFFFF)
\r
338 return kStatus_USART_BaudrateNotSupport;
\r
341 base->OSR = best_osrval;
\r
342 base->BRG = best_brgval;
\r
343 return kStatus_Success;
\r
347 * brief Writes to the TX register using a blocking method.
\r
349 * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO
\r
350 * to have room and writes data to the TX buffer.
\r
352 * param base USART peripheral base address.
\r
353 * param data Start address of the data to write.
\r
354 * param length Size of the data to write.
\r
356 void USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length)
\r
358 /* Check arguments */
\r
359 assert(!((NULL == base) || (NULL == data)));
\r
360 if ((NULL == base) || (NULL == data))
\r
364 /* Check whether txFIFO is enabled */
\r
365 if (!(base->FIFOCFG & USART_FIFOCFG_ENABLETX_MASK))
\r
369 for (; length > 0; length--)
\r
371 /* Loop until txFIFO get some space for new data */
\r
372 while (!(base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))
\r
375 base->FIFOWR = *data;
\r
378 /* Wait to finish transfer */
\r
379 while (!(base->STAT & USART_STAT_TXIDLE_MASK))
\r
385 * brief Read RX data register using a blocking method.
\r
387 * This function polls the RX register, waits for the RX register to be full or for RX FIFO to
\r
388 * have data and read data from the TX register.
\r
390 * param base USART peripheral base address.
\r
391 * param data Start address of the buffer to store the received data.
\r
392 * param length Size of the buffer.
\r
393 * retval kStatus_USART_FramingError Receiver overrun happened while receiving data.
\r
394 * retval kStatus_USART_ParityError Noise error happened while receiving data.
\r
395 * retval kStatus_USART_NoiseError Framing error happened while receiving data.
\r
396 * retval kStatus_USART_RxError Overflow or underflow rxFIFO happened.
\r
397 * retval kStatus_Success Successfully received all data.
\r
399 status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length)
\r
403 /* check arguments */
\r
404 assert(!((NULL == base) || (NULL == data)));
\r
405 if ((NULL == base) || (NULL == data))
\r
407 return kStatus_InvalidArgument;
\r
410 /* Check whether rxFIFO is enabled */
\r
411 if (!(base->FIFOCFG & USART_FIFOCFG_ENABLERX_MASK))
\r
413 return kStatus_Fail;
\r
415 for (; length > 0; length--)
\r
417 /* loop until rxFIFO have some data to read */
\r
418 while (!(base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK))
\r
421 /* check receive status */
\r
422 status = base->STAT;
\r
423 if (status & USART_STAT_FRAMERRINT_MASK)
\r
425 base->STAT |= USART_STAT_FRAMERRINT_MASK;
\r
426 return kStatus_USART_FramingError;
\r
428 if (status & USART_STAT_PARITYERRINT_MASK)
\r
430 base->STAT |= USART_STAT_PARITYERRINT_MASK;
\r
431 return kStatus_USART_ParityError;
\r
433 if (status & USART_STAT_RXNOISEINT_MASK)
\r
435 base->STAT |= USART_STAT_RXNOISEINT_MASK;
\r
436 return kStatus_USART_NoiseError;
\r
438 /* check rxFIFO status */
\r
439 if (base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK)
\r
441 base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
\r
442 base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
\r
443 return kStatus_USART_RxError;
\r
446 *data = base->FIFORD;
\r
449 return kStatus_Success;
\r
453 * brief Initializes the USART handle.
\r
455 * This function initializes the USART handle which can be used for other USART
\r
456 * transactional APIs. Usually, for a specified USART instance,
\r
457 * call this API once to get the initialized handle.
\r
459 * param base USART peripheral base address.
\r
460 * param handle USART handle pointer.
\r
461 * param callback The callback function.
\r
462 * param userData The parameter of the callback function.
\r
464 status_t USART_TransferCreateHandle(USART_Type *base,
\r
465 usart_handle_t *handle,
\r
466 usart_transfer_callback_t callback,
\r
469 int32_t instance = 0;
\r
472 assert(!((NULL == base) || (NULL == handle)));
\r
473 if ((NULL == base) || (NULL == handle))
\r
475 return kStatus_InvalidArgument;
\r
478 instance = USART_GetInstance(base);
\r
480 memset(handle, 0, sizeof(*handle));
\r
481 /* Set the TX/RX state. */
\r
482 handle->rxState = kUSART_RxIdle;
\r
483 handle->txState = kUSART_TxIdle;
\r
484 /* Set the callback and user data. */
\r
485 handle->callback = callback;
\r
486 handle->userData = userData;
\r
487 handle->rxWatermark = (usart_rxfifo_watermark_t)USART_FIFOTRIG_RXLVL_GET(base);
\r
488 handle->txWatermark = (usart_txfifo_watermark_t)USART_FIFOTRIG_TXLVL_GET(base);
\r
490 FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)USART_TransferHandleIRQ, handle);
\r
492 /* Enable interrupt in NVIC. */
\r
493 EnableIRQ(s_usartIRQ[instance]);
\r
495 return kStatus_Success;
\r
499 * brief Transmits a buffer of data using the interrupt method.
\r
501 * This function sends data using an interrupt method. This is a non-blocking function, which
\r
502 * returns directly without waiting for all data to be written to the TX register. When
\r
503 * all data is written to the TX register in the IRQ handler, the USART driver calls the callback
\r
504 * function and passes the ref kStatus_USART_TxIdle as status parameter.
\r
506 * note The kStatus_USART_TxIdle is passed to the upper layer when all data is written
\r
507 * to the TX register. However it does not ensure that all data are sent out. Before disabling the TX,
\r
508 * check the kUSART_TransmissionCompleteFlag to ensure that the TX is finished.
\r
510 * param base USART peripheral base address.
\r
511 * param handle USART handle pointer.
\r
512 * param xfer USART transfer structure. See #usart_transfer_t.
\r
513 * retval kStatus_Success Successfully start the data transmission.
\r
514 * retval kStatus_USART_TxBusy Previous transmission still not finished, data not all written to TX register yet.
\r
515 * retval kStatus_InvalidArgument Invalid argument.
\r
517 status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer)
\r
519 /* Check arguments */
\r
520 assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
\r
521 if ((NULL == base) || (NULL == handle) || (NULL == xfer))
\r
523 return kStatus_InvalidArgument;
\r
525 /* Check xfer members */
\r
526 assert(!((0 == xfer->dataSize) || (NULL == xfer->data)));
\r
527 if ((0 == xfer->dataSize) || (NULL == xfer->data))
\r
529 return kStatus_InvalidArgument;
\r
532 /* Return error if current TX busy. */
\r
533 if (kUSART_TxBusy == handle->txState)
\r
535 return kStatus_USART_TxBusy;
\r
539 handle->txData = xfer->data;
\r
540 handle->txDataSize = xfer->dataSize;
\r
541 handle->txDataSizeAll = xfer->dataSize;
\r
542 handle->txState = kUSART_TxBusy;
\r
543 /* Enable transmiter interrupt. */
\r
544 base->FIFOINTENSET |= USART_FIFOINTENSET_TXLVL_MASK;
\r
546 return kStatus_Success;
\r
550 * brief Aborts the interrupt-driven data transmit.
\r
552 * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
\r
553 * how many bytes are still not sent out.
\r
555 * param base USART peripheral base address.
\r
556 * param handle USART handle pointer.
\r
558 void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle)
\r
560 assert(NULL != handle);
\r
562 /* Disable interrupts */
\r
563 USART_DisableInterrupts(base, kUSART_TxLevelInterruptEnable);
\r
565 base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK;
\r
567 handle->txDataSize = 0;
\r
568 handle->txState = kUSART_TxIdle;
\r
572 * brief Get the number of bytes that have been written to USART TX register.
\r
574 * This function gets the number of bytes that have been written to USART TX
\r
575 * register by interrupt method.
\r
577 * param base USART peripheral base address.
\r
578 * param handle USART handle pointer.
\r
579 * param count Send bytes count.
\r
580 * retval kStatus_NoTransferInProgress No send in progress.
\r
581 * retval kStatus_InvalidArgument Parameter is invalid.
\r
582 * retval kStatus_Success Get successfully through the parameter \p count;
\r
584 status_t USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
\r
586 assert(NULL != handle);
\r
587 assert(NULL != count);
\r
589 if (kUSART_TxIdle == handle->txState)
\r
591 return kStatus_NoTransferInProgress;
\r
594 *count = handle->txDataSizeAll - handle->txDataSize;
\r
596 return kStatus_Success;
\r
600 * brief Receives a buffer of data using an interrupt method.
\r
602 * This function receives data using an interrupt method. This is a non-blocking function, which
\r
603 * returns without waiting for all data to be received.
\r
604 * If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
\r
605 * the parameter p receivedBytes shows how many bytes are copied from the ring buffer.
\r
606 * After copying, if the data in the ring buffer is not enough to read, the receive
\r
607 * request is saved by the USART driver. When the new data arrives, the receive request
\r
608 * is serviced first. When all data is received, the USART driver notifies the upper layer
\r
609 * through a callback function and passes the status parameter ref kStatus_USART_RxIdle.
\r
610 * For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.
\r
611 * The 5 bytes are copied to the xfer->data and this function returns with the
\r
612 * parameter p receivedBytes set to 5. For the left 5 bytes, newly arrived data is
\r
613 * saved from the xfer->data[5]. When 5 bytes are received, the USART driver notifies the upper layer.
\r
614 * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
\r
615 * to receive data to the xfer->data. When all data is received, the upper layer is notified.
\r
617 * param base USART peripheral base address.
\r
618 * param handle USART handle pointer.
\r
619 * param xfer USART transfer structure, see #usart_transfer_t.
\r
620 * param receivedBytes Bytes received from the ring buffer directly.
\r
621 * retval kStatus_Success Successfully queue the transfer into transmit queue.
\r
622 * retval kStatus_USART_RxBusy Previous receive request is not finished.
\r
623 * retval kStatus_InvalidArgument Invalid argument.
\r
625 status_t USART_TransferReceiveNonBlocking(USART_Type *base,
\r
626 usart_handle_t *handle,
\r
627 usart_transfer_t *xfer,
\r
628 size_t *receivedBytes)
\r
631 /* How many bytes to copy from ring buffer to user memory. */
\r
632 size_t bytesToCopy = 0U;
\r
633 /* How many bytes to receive. */
\r
634 size_t bytesToReceive;
\r
635 /* How many bytes currently have received. */
\r
636 size_t bytesCurrentReceived;
\r
637 uint32_t regPrimask = 0U;
\r
639 /* Check arguments */
\r
640 assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));
\r
641 if ((NULL == base) || (NULL == handle) || (NULL == xfer))
\r
643 return kStatus_InvalidArgument;
\r
645 /* Check xfer members */
\r
646 assert(!((0 == xfer->dataSize) || (NULL == xfer->data)));
\r
647 if ((0 == xfer->dataSize) || (NULL == xfer->data))
\r
649 return kStatus_InvalidArgument;
\r
652 /* How to get data:
\r
653 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
\r
654 to uart handle, enable interrupt to store received data to xfer->data. When
\r
655 all data received, trigger callback.
\r
656 2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
\r
657 If there are enough data in ring buffer, copy them to xfer->data and return.
\r
658 If there are not enough data in ring buffer, copy all of them to xfer->data,
\r
659 save the xfer->data remained empty space to uart handle, receive data
\r
660 to this empty space and trigger callback when finished. */
\r
661 if (kUSART_RxBusy == handle->rxState)
\r
663 return kStatus_USART_RxBusy;
\r
667 bytesToReceive = xfer->dataSize;
\r
668 bytesCurrentReceived = 0U;
\r
669 /* If RX ring buffer is used. */
\r
670 if (handle->rxRingBuffer)
\r
672 /* Disable IRQ, protect ring buffer. */
\r
673 regPrimask = DisableGlobalIRQ();
\r
674 /* How many bytes in RX ring buffer currently. */
\r
675 bytesToCopy = USART_TransferGetRxRingBufferLength(handle);
\r
678 bytesToCopy = MIN(bytesToReceive, bytesToCopy);
\r
679 bytesToReceive -= bytesToCopy;
\r
680 /* Copy data from ring buffer to user memory. */
\r
681 for (i = 0U; i < bytesToCopy; i++)
\r
683 xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
\r
684 /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
\r
685 if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
\r
687 handle->rxRingBufferTail = 0U;
\r
691 handle->rxRingBufferTail++;
\r
695 /* If ring buffer does not have enough data, still need to read more data. */
\r
696 if (bytesToReceive)
\r
698 /* No data in ring buffer, save the request to UART handle. */
\r
699 handle->rxData = xfer->data + bytesCurrentReceived;
\r
700 handle->rxDataSize = bytesToReceive;
\r
701 handle->rxDataSizeAll = bytesToReceive;
\r
702 handle->rxState = kUSART_RxBusy;
\r
704 /* Enable IRQ if previously enabled. */
\r
705 EnableGlobalIRQ(regPrimask);
\r
706 /* Call user callback since all data are received. */
\r
707 if (0 == bytesToReceive)
\r
709 if (handle->callback)
\r
711 handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
\r
715 /* Ring buffer not used. */
\r
718 handle->rxData = xfer->data + bytesCurrentReceived;
\r
719 handle->rxDataSize = bytesToReceive;
\r
720 handle->rxDataSizeAll = bytesToReceive;
\r
721 handle->rxState = kUSART_RxBusy;
\r
723 /* Enable RX interrupt. */
\r
724 base->FIFOINTENSET |= USART_FIFOINTENSET_RXLVL_MASK;
\r
726 /* Return the how many bytes have read. */
\r
729 *receivedBytes = bytesCurrentReceived;
\r
732 return kStatus_Success;
\r
736 * brief Aborts the interrupt-driven data receiving.
\r
738 * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
\r
739 * how many bytes not received yet.
\r
741 * param base USART peripheral base address.
\r
742 * param handle USART handle pointer.
\r
744 void USART_TransferAbortReceive(USART_Type *base, usart_handle_t *handle)
\r
746 assert(NULL != handle);
\r
748 /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
\r
749 if (!handle->rxRingBuffer)
\r
751 /* Disable interrupts */
\r
752 USART_DisableInterrupts(base, kUSART_RxLevelInterruptEnable);
\r
754 base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
\r
757 handle->rxDataSize = 0U;
\r
758 handle->rxState = kUSART_RxIdle;
\r
762 * brief Get the number of bytes that have been received.
\r
764 * This function gets the number of bytes that have been received.
\r
766 * param base USART peripheral base address.
\r
767 * param handle USART handle pointer.
\r
768 * param count Receive bytes count.
\r
769 * retval kStatus_NoTransferInProgress No receive in progress.
\r
770 * retval kStatus_InvalidArgument Parameter is invalid.
\r
771 * retval kStatus_Success Get successfully through the parameter \p count;
\r
773 status_t USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)
\r
775 assert(NULL != handle);
\r
776 assert(NULL != count);
\r
778 if (kUSART_RxIdle == handle->rxState)
\r
780 return kStatus_NoTransferInProgress;
\r
783 *count = handle->rxDataSizeAll - handle->rxDataSize;
\r
785 return kStatus_Success;
\r
789 * brief USART IRQ handle function.
\r
791 * This function handles the USART transmit and receive IRQ request.
\r
793 * param base USART peripheral base address.
\r
794 * param handle USART handle pointer.
\r
796 void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)
\r
798 /* Check arguments */
\r
799 assert((NULL != base) && (NULL != handle));
\r
801 bool receiveEnabled = (handle->rxDataSize) || (handle->rxRingBuffer);
\r
802 bool sendEnabled = handle->txDataSize;
\r
804 /* If RX overrun. */
\r
805 if (base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK)
\r
807 /* Clear rx error state. */
\r
808 base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
\r
810 base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
\r
811 /* Trigger callback. */
\r
812 if (handle->callback)
\r
814 handle->callback(base, handle, kStatus_USART_RxError, handle->userData);
\r
817 while ((receiveEnabled && (base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK)) ||
\r
818 (sendEnabled && (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK)))
\r
821 if (receiveEnabled && (base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK))
\r
823 /* Receive to app bufffer if app buffer is present */
\r
824 if (handle->rxDataSize)
\r
826 *handle->rxData = base->FIFORD;
\r
827 handle->rxDataSize--;
\r
829 receiveEnabled = ((handle->rxDataSize != 0) || (handle->rxRingBuffer));
\r
830 if (!handle->rxDataSize)
\r
832 if (!handle->rxRingBuffer)
\r
834 base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
\r
836 handle->rxState = kUSART_RxIdle;
\r
837 if (handle->callback)
\r
839 handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
\r
843 /* Otherwise receive to ring buffer if ring buffer is present */
\r
846 if (handle->rxRingBuffer)
\r
848 /* If RX ring buffer is full, trigger callback to notify over run. */
\r
849 if (USART_TransferIsRxRingBufferFull(handle))
\r
851 if (handle->callback)
\r
853 handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);
\r
856 /* If ring buffer is still full after callback function, the oldest data is overrided. */
\r
857 if (USART_TransferIsRxRingBufferFull(handle))
\r
859 /* Increase handle->rxRingBufferTail to make room for new data. */
\r
860 if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
\r
862 handle->rxRingBufferTail = 0U;
\r
866 handle->rxRingBufferTail++;
\r
870 handle->rxRingBuffer[handle->rxRingBufferHead] = base->FIFORD;
\r
871 /* Increase handle->rxRingBufferHead. */
\r
872 if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
\r
874 handle->rxRingBufferHead = 0U;
\r
878 handle->rxRingBufferHead++;
\r
884 if (sendEnabled && (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))
\r
886 base->FIFOWR = *handle->txData;
\r
887 handle->txDataSize--;
\r
889 sendEnabled = handle->txDataSize != 0;
\r
892 base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;
\r
893 handle->txState = kUSART_TxIdle;
\r
894 if (handle->callback)
\r
896 handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);
\r
902 /* ring buffer is not used */
\r
903 if (NULL == handle->rxRingBuffer)
\r
905 /* restore if rx transfer ends and rxLevel is different from default value */
\r
906 if ((handle->rxDataSize == 0) && (USART_FIFOTRIG_RXLVL_GET(base) != handle->rxWatermark))
\r
909 (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | USART_FIFOTRIG_RXLVL(handle->rxWatermark);
\r
911 /* decrease level if rx transfer is bellow */
\r
912 if ((handle->rxDataSize != 0) && (handle->rxDataSize < (USART_FIFOTRIG_RXLVL_GET(base) + 1)))
\r
915 (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | (USART_FIFOTRIG_RXLVL(handle->rxDataSize - 1));
\r