]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M0+_LPC51U68_LPCXpresso/drivers/fsl_usart.c
ce643d1e995855f5a8fe93989bba9c0d274fa639
[freertos] / FreeRTOS / Demo / CORTEX_M0+_LPC51U68_LPCXpresso / drivers / fsl_usart.c
1 /*\r
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.\r
3  * Copyright 2016-2019 NXP\r
4  * All rights reserved.\r
5  *\r
6  * SPDX-License-Identifier: BSD-3-Clause\r
7  */\r
8 \r
9 #include "fsl_usart.h"\r
10 #include "fsl_device_registers.h"\r
11 #include "fsl_flexcomm.h"\r
12 \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
16 #endif\r
17 \r
18 enum _usart_transfer_states\r
19 {\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
24 };\r
25 \r
26 /*******************************************************************************\r
27  * Variables\r
28  ******************************************************************************/\r
29 \r
30 /*! @brief IRQ name array */\r
31 static const IRQn_Type s_usartIRQ[] = USART_IRQS;\r
32 \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
35 \r
36 /*******************************************************************************\r
37  * Code\r
38  ******************************************************************************/\r
39 \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
43 {\r
44     int i;\r
45 \r
46     for (i = 0; i < FSL_FEATURE_SOC_USART_COUNT; i++)\r
47     {\r
48         if ((uint32_t)base == s_usartBaseAddrs[i])\r
49         {\r
50             return i;\r
51         }\r
52     }\r
53 \r
54     assert(false);\r
55     return 0;\r
56 }\r
57 \r
58 /*!\r
59  * brief Get the length of received data in RX ring buffer.\r
60  *\r
61  * param handle USART handle pointer.\r
62  * return Length of received data in RX ring buffer.\r
63  */\r
64 size_t USART_TransferGetRxRingBufferLength(usart_handle_t *handle)\r
65 {\r
66     size_t size;\r
67 \r
68     /* Check arguments */\r
69     assert(NULL != handle);\r
70 \r
71     if (handle->rxRingBufferTail > handle->rxRingBufferHead)\r
72     {\r
73         size = (size_t)(handle->rxRingBufferHead + handle->rxRingBufferSize - handle->rxRingBufferTail);\r
74     }\r
75     else\r
76     {\r
77         size = (size_t)(handle->rxRingBufferHead - handle->rxRingBufferTail);\r
78     }\r
79     return size;\r
80 }\r
81 \r
82 static bool USART_TransferIsRxRingBufferFull(usart_handle_t *handle)\r
83 {\r
84     bool full;\r
85 \r
86     /* Check arguments */\r
87     assert(NULL != handle);\r
88 \r
89     if (USART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))\r
90     {\r
91         full = true;\r
92     }\r
93     else\r
94     {\r
95         full = false;\r
96     }\r
97     return full;\r
98 }\r
99 \r
100 /*!\r
101  * brief Sets up the RX ring buffer.\r
102  *\r
103  * This function sets up the RX ring buffer to a specific USART handle.\r
104  *\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
108  *\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
111  *\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
116  */\r
117 void USART_TransferStartRingBuffer(USART_Type *base, usart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize)\r
118 {\r
119     /* Check arguments */\r
120     assert(NULL != base);\r
121     assert(NULL != handle);\r
122     assert(NULL != ringBuffer);\r
123 \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
131 }\r
132 \r
133 /*!\r
134  * brief Aborts the background transfer and uninstalls the ring buffer.\r
135  *\r
136  * This function aborts the background transfer and uninstalls the ring buffer.\r
137  *\r
138  * param base USART peripheral base address.\r
139  * param handle USART handle pointer.\r
140  */\r
141 void USART_TransferStopRingBuffer(USART_Type *base, usart_handle_t *handle)\r
142 {\r
143     /* Check arguments */\r
144     assert(NULL != base);\r
145     assert(NULL != handle);\r
146 \r
147     if (handle->rxState == kUSART_RxIdle)\r
148     {\r
149         base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENCLR_RXERR_MASK;\r
150     }\r
151     handle->rxRingBuffer     = NULL;\r
152     handle->rxRingBufferSize = 0U;\r
153     handle->rxRingBufferHead = 0U;\r
154     handle->rxRingBufferTail = 0U;\r
155 }\r
156 \r
157 /*!\r
158  * brief Initializes a USART instance with user configuration structure and peripheral clock.\r
159  *\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
163  * code\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
169  * endcode\r
170  *\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
177  */\r
178 status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz)\r
179 {\r
180     int result;\r
181 \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
185     {\r
186         return kStatus_InvalidArgument;\r
187     }\r
188 \r
189     /* initialize flexcomm to USART mode */\r
190     result = FLEXCOMM_Init(base, FLEXCOMM_PERIPH_USART);\r
191     if (kStatus_Success != result)\r
192     {\r
193         return result;\r
194     }\r
195 \r
196     if (config->enableTx)\r
197     {\r
198         /* empty and enable txFIFO */\r
199         base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK | USART_FIFOCFG_ENABLETX_MASK;\r
200         /* setup trigger level */\r
201         base->FIFOTRIG &= ~(USART_FIFOTRIG_TXLVL_MASK);\r
202         base->FIFOTRIG |= USART_FIFOTRIG_TXLVL(config->txWatermark);\r
203         /* enable trigger interrupt */\r
204         base->FIFOTRIG |= USART_FIFOTRIG_TXLVLENA_MASK;\r
205     }\r
206 \r
207     /* empty and enable rxFIFO */\r
208     if (config->enableRx)\r
209     {\r
210         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK | USART_FIFOCFG_ENABLERX_MASK;\r
211         /* setup trigger level */\r
212         base->FIFOTRIG &= ~(USART_FIFOTRIG_RXLVL_MASK);\r
213         base->FIFOTRIG |= USART_FIFOTRIG_RXLVL(config->rxWatermark);\r
214         /* enable trigger interrupt */\r
215         base->FIFOTRIG |= USART_FIFOTRIG_RXLVLENA_MASK;\r
216     }\r
217     /* setup configuration and enable USART */\r
218     base->CFG = USART_CFG_PARITYSEL(config->parityMode) | USART_CFG_STOPLEN(config->stopBitCount) |\r
219                 USART_CFG_DATALEN(config->bitCountPerChar) | USART_CFG_LOOP(config->loopback) |\r
220                 USART_CFG_SYNCEN(config->syncMode >> 1) | USART_CFG_SYNCMST(config->syncMode) |\r
221                 USART_CFG_CLKPOL(config->clockPolarity) | USART_CFG_ENABLE_MASK;\r
222 \r
223     /* Setup baudrate */\r
224     result = USART_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz);\r
225     if (kStatus_Success != result)\r
226     {\r
227         return result;\r
228     }\r
229     /* Setting continuous Clock configuration. used for synchronous mode. */\r
230     USART_EnableContinuousSCLK(base, config->enableContinuousSCLK);\r
231 \r
232     return kStatus_Success;\r
233 }\r
234 \r
235 /*!\r
236  * brief Deinitializes a USART instance.\r
237  *\r
238  * This function waits for TX complete, disables TX and RX, and disables the USART clock.\r
239  *\r
240  * param base USART peripheral base address.\r
241  */\r
242 void USART_Deinit(USART_Type *base)\r
243 {\r
244     /* Check arguments */\r
245     assert(NULL != base);\r
246     while (!(base->STAT & USART_STAT_TXIDLE_MASK))\r
247     {\r
248     }\r
249     /* Disable interrupts, disable dma requests, disable peripheral */\r
250     base->FIFOINTENCLR = USART_FIFOINTENCLR_TXERR_MASK | USART_FIFOINTENCLR_RXERR_MASK | USART_FIFOINTENCLR_TXLVL_MASK |\r
251                          USART_FIFOINTENCLR_RXLVL_MASK;\r
252     base->FIFOCFG &= ~(USART_FIFOCFG_DMATX_MASK | USART_FIFOCFG_DMARX_MASK);\r
253     base->CFG &= ~(USART_CFG_ENABLE_MASK);\r
254 }\r
255 \r
256 /*!\r
257  * brief Gets the default configuration structure.\r
258  *\r
259  * This function initializes the USART configuration structure to a default value. The default\r
260  * values are:\r
261  *   usartConfig->baudRate_Bps = 115200U;\r
262  *   usartConfig->parityMode = kUSART_ParityDisabled;\r
263  *   usartConfig->stopBitCount = kUSART_OneStopBit;\r
264  *   usartConfig->bitCountPerChar = kUSART_8BitsPerChar;\r
265  *   usartConfig->loopback = false;\r
266  *   usartConfig->enableTx = false;\r
267  *   usartConfig->enableRx = false;\r
268  *\r
269  * param config Pointer to configuration structure.\r
270  */\r
271 void USART_GetDefaultConfig(usart_config_t *config)\r
272 {\r
273     /* Check arguments */\r
274     assert(NULL != config);\r
275 \r
276     /* Initializes the configure structure to zero. */\r
277     memset(config, 0, sizeof(*config));\r
278 \r
279     /* Set always all members ! */\r
280     config->baudRate_Bps         = 115200U;\r
281     config->parityMode           = kUSART_ParityDisabled;\r
282     config->stopBitCount         = kUSART_OneStopBit;\r
283     config->bitCountPerChar      = kUSART_8BitsPerChar;\r
284     config->loopback             = false;\r
285     config->enableRx             = false;\r
286     config->enableTx             = false;\r
287     config->txWatermark          = kUSART_TxFifo0;\r
288     config->rxWatermark          = kUSART_RxFifo1;\r
289     config->syncMode             = kUSART_SyncModeDisabled;\r
290     config->enableContinuousSCLK = false;\r
291     config->clockPolarity        = kUSART_RxSampleOnFallingEdge;\r
292 }\r
293 \r
294 /*!\r
295  * brief Sets the USART instance baud rate.\r
296  *\r
297  * This function configures the USART module baud rate. This function is used to update\r
298  * the USART module baud rate after the USART module is initialized by the USART_Init.\r
299  * code\r
300  *  USART_SetBaudRate(USART1, 115200U, 20000000U);\r
301  * endcode\r
302  *\r
303  * param base USART peripheral base address.\r
304  * param baudrate_Bps USART baudrate to be set.\r
305  * param srcClock_Hz USART clock source frequency in HZ.\r
306  * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.\r
307  * retval kStatus_Success Set baudrate succeed.\r
308  * retval kStatus_InvalidArgument One or more arguments are invalid.\r
309  */\r
310 status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)\r
311 {\r
312     uint32_t best_diff = (uint32_t)-1, best_osrval = 0xf, best_brgval = (uint32_t)-1;\r
313     uint32_t osrval, brgval, diff, baudrate;\r
314 \r
315     /* check arguments */\r
316     assert(!((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz)));\r
317     if ((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz))\r
318     {\r
319         return kStatus_InvalidArgument;\r
320     }\r
321 \r
322     /* If synchronous master mode is enabled, only configure the BRG value. */\r
323     if (base->CFG & USART_CFG_SYNCEN_MASK)\r
324     {\r
325         if (base->CFG & USART_CFG_SYNCMST_MASK)\r
326         {\r
327             brgval    = srcClock_Hz / baudrate_Bps;\r
328             base->BRG = brgval - 1;\r
329         }\r
330     }\r
331     else\r
332     {\r
333         /*\r
334          * Smaller values of OSR can make the sampling position within a data bit less accurate and may\r
335          * potentially cause more noise errors or incorrect data.\r
336          */\r
337         for (osrval = best_osrval; osrval >= 8; osrval--)\r
338         {\r
339             brgval = (srcClock_Hz / ((osrval + 1) * baudrate_Bps)) - 1;\r
340             if (brgval > 0xFFFF)\r
341             {\r
342                 continue;\r
343             }\r
344             baudrate = srcClock_Hz / ((osrval + 1) * (brgval + 1));\r
345             diff     = baudrate_Bps < baudrate ? baudrate - baudrate_Bps : baudrate_Bps - baudrate;\r
346             if (diff < best_diff)\r
347             {\r
348                 best_diff   = diff;\r
349                 best_osrval = osrval;\r
350                 best_brgval = brgval;\r
351             }\r
352         }\r
353 \r
354         /* value over range */\r
355         if (best_brgval > 0xFFFF)\r
356         {\r
357             return kStatus_USART_BaudrateNotSupport;\r
358         }\r
359 \r
360         base->OSR = best_osrval;\r
361         base->BRG = best_brgval;\r
362     }\r
363 \r
364     return kStatus_Success;\r
365 }\r
366 \r
367 /*!\r
368  * brief Writes to the TX register using a blocking method.\r
369  *\r
370  * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO\r
371  * to have room and writes data to the TX buffer.\r
372  *\r
373  * param base USART peripheral base address.\r
374  * param data Start address of the data to write.\r
375  * param length Size of the data to write.\r
376  */\r
377 void USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length)\r
378 {\r
379     /* Check arguments */\r
380     assert(!((NULL == base) || (NULL == data)));\r
381     if ((NULL == base) || (NULL == data))\r
382     {\r
383         return;\r
384     }\r
385     /* Check whether txFIFO is enabled */\r
386     if (!(base->FIFOCFG & USART_FIFOCFG_ENABLETX_MASK))\r
387     {\r
388         return;\r
389     }\r
390     for (; length > 0; length--)\r
391     {\r
392         /* Loop until txFIFO get some space for new data */\r
393         while (!(base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))\r
394         {\r
395         }\r
396         base->FIFOWR = *data;\r
397         data++;\r
398     }\r
399     /* Wait to finish transfer */\r
400     while (!(base->STAT & USART_STAT_TXIDLE_MASK))\r
401     {\r
402     }\r
403 }\r
404 \r
405 /*!\r
406  * brief Read RX data register using a blocking method.\r
407  *\r
408  * This function polls the RX register, waits for the RX register to be full or for RX FIFO to\r
409  * have data and read data from the TX register.\r
410  *\r
411  * param base USART peripheral base address.\r
412  * param data Start address of the buffer to store the received data.\r
413  * param length Size of the buffer.\r
414  * retval kStatus_USART_FramingError Receiver overrun happened while receiving data.\r
415  * retval kStatus_USART_ParityError Noise error happened while receiving data.\r
416  * retval kStatus_USART_NoiseError Framing error happened while receiving data.\r
417  * retval kStatus_USART_RxError Overflow or underflow rxFIFO happened.\r
418  * retval kStatus_Success Successfully received all data.\r
419  */\r
420 status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length)\r
421 {\r
422     uint32_t status;\r
423 \r
424     /* check arguments */\r
425     assert(!((NULL == base) || (NULL == data)));\r
426     if ((NULL == base) || (NULL == data))\r
427     {\r
428         return kStatus_InvalidArgument;\r
429     }\r
430 \r
431     /* Check whether rxFIFO is enabled */\r
432     if (!(base->FIFOCFG & USART_FIFOCFG_ENABLERX_MASK))\r
433     {\r
434         return kStatus_Fail;\r
435     }\r
436     for (; length > 0; length--)\r
437     {\r
438         /* loop until rxFIFO have some data to read */\r
439         while (!(base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK))\r
440         {\r
441         }\r
442         /* check receive status */\r
443         status = base->STAT;\r
444         if (status & USART_STAT_FRAMERRINT_MASK)\r
445         {\r
446             base->STAT |= USART_STAT_FRAMERRINT_MASK;\r
447             return kStatus_USART_FramingError;\r
448         }\r
449         if (status & USART_STAT_PARITYERRINT_MASK)\r
450         {\r
451             base->STAT |= USART_STAT_PARITYERRINT_MASK;\r
452             return kStatus_USART_ParityError;\r
453         }\r
454         if (status & USART_STAT_RXNOISEINT_MASK)\r
455         {\r
456             base->STAT |= USART_STAT_RXNOISEINT_MASK;\r
457             return kStatus_USART_NoiseError;\r
458         }\r
459         /* check rxFIFO status */\r
460         if (base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK)\r
461         {\r
462             base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;\r
463             base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;\r
464             return kStatus_USART_RxError;\r
465         }\r
466 \r
467         *data = base->FIFORD;\r
468         data++;\r
469     }\r
470     return kStatus_Success;\r
471 }\r
472 \r
473 /*!\r
474  * brief Initializes the USART handle.\r
475  *\r
476  * This function initializes the USART handle which can be used for other USART\r
477  * transactional APIs. Usually, for a specified USART instance,\r
478  * call this API once to get the initialized handle.\r
479  *\r
480  * param base USART peripheral base address.\r
481  * param handle USART handle pointer.\r
482  * param callback The callback function.\r
483  * param userData The parameter of the callback function.\r
484  */\r
485 status_t USART_TransferCreateHandle(USART_Type *base,\r
486                                     usart_handle_t *handle,\r
487                                     usart_transfer_callback_t callback,\r
488                                     void *userData)\r
489 {\r
490     int32_t instance = 0;\r
491 \r
492     /* Check 'base' */\r
493     assert(!((NULL == base) || (NULL == handle)));\r
494     if ((NULL == base) || (NULL == handle))\r
495     {\r
496         return kStatus_InvalidArgument;\r
497     }\r
498 \r
499     instance = USART_GetInstance(base);\r
500 \r
501     memset(handle, 0, sizeof(*handle));\r
502     /* Set the TX/RX state. */\r
503     handle->rxState = kUSART_RxIdle;\r
504     handle->txState = kUSART_TxIdle;\r
505     /* Set the callback and user data. */\r
506     handle->callback    = callback;\r
507     handle->userData    = userData;\r
508     handle->rxWatermark = (usart_rxfifo_watermark_t)USART_FIFOTRIG_RXLVL_GET(base);\r
509     handle->txWatermark = (usart_txfifo_watermark_t)USART_FIFOTRIG_TXLVL_GET(base);\r
510 \r
511     FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)USART_TransferHandleIRQ, handle);\r
512 \r
513     /* Enable interrupt in NVIC. */\r
514     EnableIRQ(s_usartIRQ[instance]);\r
515 \r
516     return kStatus_Success;\r
517 }\r
518 \r
519 /*!\r
520  * brief Transmits a buffer of data using the interrupt method.\r
521  *\r
522  * This function sends data using an interrupt method. This is a non-blocking function, which\r
523  * returns directly without waiting for all data to be written to the TX register. When\r
524  * all data is written to the TX register in the IRQ handler, the USART driver calls the callback\r
525  * function and passes the ref kStatus_USART_TxIdle as status parameter.\r
526  *\r
527  * note The kStatus_USART_TxIdle is passed to the upper layer when all data is written\r
528  * to the TX register. However it does not ensure that all data are sent out. Before disabling the TX,\r
529  * check the kUSART_TransmissionCompleteFlag to ensure that the TX is finished.\r
530  *\r
531  * param base USART peripheral base address.\r
532  * param handle USART handle pointer.\r
533  * param xfer USART transfer structure. See  #usart_transfer_t.\r
534  * retval kStatus_Success Successfully start the data transmission.\r
535  * retval kStatus_USART_TxBusy Previous transmission still not finished, data not all written to TX register yet.\r
536  * retval kStatus_InvalidArgument Invalid argument.\r
537  */\r
538 status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer)\r
539 {\r
540     /* Check arguments */\r
541     assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));\r
542     if ((NULL == base) || (NULL == handle) || (NULL == xfer))\r
543     {\r
544         return kStatus_InvalidArgument;\r
545     }\r
546     /* Check xfer members */\r
547     assert(!((0 == xfer->dataSize) || (NULL == xfer->data)));\r
548     if ((0 == xfer->dataSize) || (NULL == xfer->data))\r
549     {\r
550         return kStatus_InvalidArgument;\r
551     }\r
552 \r
553     /* Return error if current TX busy. */\r
554     if (kUSART_TxBusy == handle->txState)\r
555     {\r
556         return kStatus_USART_TxBusy;\r
557     }\r
558     else\r
559     {\r
560         handle->txData        = xfer->data;\r
561         handle->txDataSize    = xfer->dataSize;\r
562         handle->txDataSizeAll = xfer->dataSize;\r
563         handle->txState       = kUSART_TxBusy;\r
564         /* Enable transmiter interrupt. */\r
565         base->FIFOINTENSET |= USART_FIFOINTENSET_TXLVL_MASK;\r
566     }\r
567     return kStatus_Success;\r
568 }\r
569 \r
570 /*!\r
571  * brief Aborts the interrupt-driven data transmit.\r
572  *\r
573  * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out\r
574  * how many bytes are still not sent out.\r
575  *\r
576  * param base USART peripheral base address.\r
577  * param handle USART handle pointer.\r
578  */\r
579 void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle)\r
580 {\r
581     assert(NULL != handle);\r
582 \r
583     /* Disable interrupts */\r
584     USART_DisableInterrupts(base, kUSART_TxLevelInterruptEnable);\r
585     /* Empty txFIFO */\r
586     base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK;\r
587 \r
588     handle->txDataSize = 0;\r
589     handle->txState    = kUSART_TxIdle;\r
590 }\r
591 \r
592 /*!\r
593  * brief Get the number of bytes that have been written to USART TX register.\r
594  *\r
595  * This function gets the number of bytes that have been written to USART TX\r
596  * register by interrupt method.\r
597  *\r
598  * param base USART peripheral base address.\r
599  * param handle USART handle pointer.\r
600  * param count Send bytes count.\r
601  * retval kStatus_NoTransferInProgress No send in progress.\r
602  * retval kStatus_InvalidArgument Parameter is invalid.\r
603  * retval kStatus_Success Get successfully through the parameter \p count;\r
604  */\r
605 status_t USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)\r
606 {\r
607     assert(NULL != handle);\r
608     assert(NULL != count);\r
609 \r
610     if (kUSART_TxIdle == handle->txState)\r
611     {\r
612         return kStatus_NoTransferInProgress;\r
613     }\r
614 \r
615     *count = handle->txDataSizeAll - handle->txDataSize;\r
616 \r
617     return kStatus_Success;\r
618 }\r
619 \r
620 /*!\r
621  * brief Receives a buffer of data using an interrupt method.\r
622  *\r
623  * This function receives data using an interrupt method. This is a non-blocking function, which\r
624  *  returns without waiting for all data to be received.\r
625  * If the RX ring buffer is used and not empty, the data in the ring buffer is copied and\r
626  * the parameter p receivedBytes shows how many bytes are copied from the ring buffer.\r
627  * After copying, if the data in the ring buffer is not enough to read, the receive\r
628  * request is saved by the USART driver. When the new data arrives, the receive request\r
629  * is serviced first. When all data is received, the USART driver notifies the upper layer\r
630  * through a callback function and passes the status parameter ref kStatus_USART_RxIdle.\r
631  * For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.\r
632  * The 5 bytes are copied to the xfer->data and this function returns with the\r
633  * parameter p receivedBytes set to 5. For the left 5 bytes, newly arrived data is\r
634  * saved from the xfer->data[5]. When 5 bytes are received, the USART driver notifies the upper layer.\r
635  * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt\r
636  * to receive data to the xfer->data. When all data is received, the upper layer is notified.\r
637  *\r
638  * param base USART peripheral base address.\r
639  * param handle USART handle pointer.\r
640  * param xfer USART transfer structure, see #usart_transfer_t.\r
641  * param receivedBytes Bytes received from the ring buffer directly.\r
642  * retval kStatus_Success Successfully queue the transfer into transmit queue.\r
643  * retval kStatus_USART_RxBusy Previous receive request is not finished.\r
644  * retval kStatus_InvalidArgument Invalid argument.\r
645  */\r
646 status_t USART_TransferReceiveNonBlocking(USART_Type *base,\r
647                                           usart_handle_t *handle,\r
648                                           usart_transfer_t *xfer,\r
649                                           size_t *receivedBytes)\r
650 {\r
651     uint32_t i;\r
652     /* How many bytes to copy from ring buffer to user memory. */\r
653     size_t bytesToCopy = 0U;\r
654     /* How many bytes to receive. */\r
655     size_t bytesToReceive;\r
656     /* How many bytes currently have received. */\r
657     size_t bytesCurrentReceived;\r
658     uint32_t regPrimask = 0U;\r
659 \r
660     /* Check arguments */\r
661     assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));\r
662     if ((NULL == base) || (NULL == handle) || (NULL == xfer))\r
663     {\r
664         return kStatus_InvalidArgument;\r
665     }\r
666     /* Check xfer members */\r
667     assert(!((0 == xfer->dataSize) || (NULL == xfer->data)));\r
668     if ((0 == xfer->dataSize) || (NULL == xfer->data))\r
669     {\r
670         return kStatus_InvalidArgument;\r
671     }\r
672 \r
673     /* How to get data:\r
674        1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize\r
675           to uart handle, enable interrupt to store received data to xfer->data. When\r
676           all data received, trigger callback.\r
677        2. If RX ring buffer is enabled and not empty, get data from ring buffer first.\r
678           If there are enough data in ring buffer, copy them to xfer->data and return.\r
679           If there are not enough data in ring buffer, copy all of them to xfer->data,\r
680           save the xfer->data remained empty space to uart handle, receive data\r
681           to this empty space and trigger callback when finished. */\r
682     if (kUSART_RxBusy == handle->rxState)\r
683     {\r
684         return kStatus_USART_RxBusy;\r
685     }\r
686     else\r
687     {\r
688         bytesToReceive       = xfer->dataSize;\r
689         bytesCurrentReceived = 0U;\r
690         /* If RX ring buffer is used. */\r
691         if (handle->rxRingBuffer)\r
692         {\r
693             /* Disable IRQ, protect ring buffer. */\r
694             regPrimask = DisableGlobalIRQ();\r
695             /* How many bytes in RX ring buffer currently. */\r
696             bytesToCopy = USART_TransferGetRxRingBufferLength(handle);\r
697             if (bytesToCopy)\r
698             {\r
699                 bytesToCopy = MIN(bytesToReceive, bytesToCopy);\r
700                 bytesToReceive -= bytesToCopy;\r
701                 /* Copy data from ring buffer to user memory. */\r
702                 for (i = 0U; i < bytesToCopy; i++)\r
703                 {\r
704                     xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];\r
705                     /* Wrap to 0. Not use modulo (%) because it might be large and slow. */\r
706                     if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)\r
707                     {\r
708                         handle->rxRingBufferTail = 0U;\r
709                     }\r
710                     else\r
711                     {\r
712                         handle->rxRingBufferTail++;\r
713                     }\r
714                 }\r
715             }\r
716             /* If ring buffer does not have enough data, still need to read more data. */\r
717             if (bytesToReceive)\r
718             {\r
719                 /* No data in ring buffer, save the request to UART handle. */\r
720                 handle->rxData        = xfer->data + bytesCurrentReceived;\r
721                 handle->rxDataSize    = bytesToReceive;\r
722                 handle->rxDataSizeAll = bytesToReceive;\r
723                 handle->rxState       = kUSART_RxBusy;\r
724             }\r
725             /* Enable IRQ if previously enabled. */\r
726             EnableGlobalIRQ(regPrimask);\r
727             /* Call user callback since all data are received. */\r
728             if (0 == bytesToReceive)\r
729             {\r
730                 if (handle->callback)\r
731                 {\r
732                     handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);\r
733                 }\r
734             }\r
735         }\r
736         /* Ring buffer not used. */\r
737         else\r
738         {\r
739             handle->rxData        = xfer->data + bytesCurrentReceived;\r
740             handle->rxDataSize    = bytesToReceive;\r
741             handle->rxDataSizeAll = bytesToReceive;\r
742             handle->rxState       = kUSART_RxBusy;\r
743 \r
744             /* Enable RX interrupt. */\r
745             base->FIFOINTENSET |= USART_FIFOINTENSET_RXLVL_MASK;\r
746         }\r
747         /* Return the how many bytes have read. */\r
748         if (receivedBytes)\r
749         {\r
750             *receivedBytes = bytesCurrentReceived;\r
751         }\r
752     }\r
753     return kStatus_Success;\r
754 }\r
755 \r
756 /*!\r
757  * brief Aborts the interrupt-driven data receiving.\r
758  *\r
759  * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out\r
760  * how many bytes not received yet.\r
761  *\r
762  * param base USART peripheral base address.\r
763  * param handle USART handle pointer.\r
764  */\r
765 void USART_TransferAbortReceive(USART_Type *base, usart_handle_t *handle)\r
766 {\r
767     assert(NULL != handle);\r
768 \r
769     /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */\r
770     if (!handle->rxRingBuffer)\r
771     {\r
772         /* Disable interrupts */\r
773         USART_DisableInterrupts(base, kUSART_RxLevelInterruptEnable);\r
774         /* Empty rxFIFO */\r
775         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;\r
776     }\r
777 \r
778     handle->rxDataSize = 0U;\r
779     handle->rxState    = kUSART_RxIdle;\r
780 }\r
781 \r
782 /*!\r
783  * brief Get the number of bytes that have been received.\r
784  *\r
785  * This function gets the number of bytes that have been received.\r
786  *\r
787  * param base USART peripheral base address.\r
788  * param handle USART handle pointer.\r
789  * param count Receive bytes count.\r
790  * retval kStatus_NoTransferInProgress No receive in progress.\r
791  * retval kStatus_InvalidArgument Parameter is invalid.\r
792  * retval kStatus_Success Get successfully through the parameter \p count;\r
793  */\r
794 status_t USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)\r
795 {\r
796     assert(NULL != handle);\r
797     assert(NULL != count);\r
798 \r
799     if (kUSART_RxIdle == handle->rxState)\r
800     {\r
801         return kStatus_NoTransferInProgress;\r
802     }\r
803 \r
804     *count = handle->rxDataSizeAll - handle->rxDataSize;\r
805 \r
806     return kStatus_Success;\r
807 }\r
808 \r
809 /*!\r
810  * brief USART IRQ handle function.\r
811  *\r
812  * This function handles the USART transmit and receive IRQ request.\r
813  *\r
814  * param base USART peripheral base address.\r
815  * param handle USART handle pointer.\r
816  */\r
817 void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)\r
818 {\r
819     /* Check arguments */\r
820     assert((NULL != base) && (NULL != handle));\r
821 \r
822     bool receiveEnabled = (handle->rxDataSize) || (handle->rxRingBuffer);\r
823     bool sendEnabled    = handle->txDataSize;\r
824 \r
825     /* If RX overrun. */\r
826     if (base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK)\r
827     {\r
828         /* Clear rx error state. */\r
829         base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;\r
830         /* clear rxFIFO */\r
831         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;\r
832         /* Trigger callback. */\r
833         if (handle->callback)\r
834         {\r
835             handle->callback(base, handle, kStatus_USART_RxError, handle->userData);\r
836         }\r
837     }\r
838     while ((receiveEnabled && (base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK)) ||\r
839            (sendEnabled && (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK)))\r
840     {\r
841         /* Receive data */\r
842         if (receiveEnabled && (base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK))\r
843         {\r
844             /* Receive to app bufffer if app buffer is present */\r
845             if (handle->rxDataSize)\r
846             {\r
847                 *handle->rxData = base->FIFORD;\r
848                 handle->rxDataSize--;\r
849                 handle->rxData++;\r
850                 receiveEnabled = ((handle->rxDataSize != 0) || (handle->rxRingBuffer));\r
851                 if (!handle->rxDataSize)\r
852                 {\r
853                     if (!handle->rxRingBuffer)\r
854                     {\r
855                         base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;\r
856                     }\r
857                     handle->rxState = kUSART_RxIdle;\r
858                     if (handle->callback)\r
859                     {\r
860                         handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);\r
861                     }\r
862                 }\r
863             }\r
864             /* Otherwise receive to ring buffer if ring buffer is present */\r
865             else\r
866             {\r
867                 if (handle->rxRingBuffer)\r
868                 {\r
869                     /* If RX ring buffer is full, trigger callback to notify over run. */\r
870                     if (USART_TransferIsRxRingBufferFull(handle))\r
871                     {\r
872                         if (handle->callback)\r
873                         {\r
874                             handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);\r
875                         }\r
876                     }\r
877                     /* If ring buffer is still full after callback function, the oldest data is overridden. */\r
878                     if (USART_TransferIsRxRingBufferFull(handle))\r
879                     {\r
880                         /* Increase handle->rxRingBufferTail to make room for new data. */\r
881                         if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)\r
882                         {\r
883                             handle->rxRingBufferTail = 0U;\r
884                         }\r
885                         else\r
886                         {\r
887                             handle->rxRingBufferTail++;\r
888                         }\r
889                     }\r
890                     /* Read data. */\r
891                     handle->rxRingBuffer[handle->rxRingBufferHead] = base->FIFORD;\r
892                     /* Increase handle->rxRingBufferHead. */\r
893                     if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)\r
894                     {\r
895                         handle->rxRingBufferHead = 0U;\r
896                     }\r
897                     else\r
898                     {\r
899                         handle->rxRingBufferHead++;\r
900                     }\r
901                 }\r
902             }\r
903         }\r
904         /* Send data */\r
905         if (sendEnabled && (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))\r
906         {\r
907             base->FIFOWR = *handle->txData;\r
908             handle->txDataSize--;\r
909             handle->txData++;\r
910             sendEnabled = handle->txDataSize != 0;\r
911             if (!sendEnabled)\r
912             {\r
913                 base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;\r
914                 handle->txState    = kUSART_TxIdle;\r
915                 if (handle->callback)\r
916                 {\r
917                     handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);\r
918                 }\r
919             }\r
920         }\r
921     }\r
922 \r
923     /* ring buffer is not used */\r
924     if (NULL == handle->rxRingBuffer)\r
925     {\r
926         /* restore if rx transfer ends and rxLevel is different from default value */\r
927         if ((handle->rxDataSize == 0) && (USART_FIFOTRIG_RXLVL_GET(base) != handle->rxWatermark))\r
928         {\r
929             base->FIFOTRIG =\r
930                 (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | USART_FIFOTRIG_RXLVL(handle->rxWatermark);\r
931         }\r
932         /* decrease level if rx transfer is bellow */\r
933         if ((handle->rxDataSize != 0) && (handle->rxDataSize < (USART_FIFOTRIG_RXLVL_GET(base) + 1)))\r
934         {\r
935             base->FIFOTRIG =\r
936                 (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | (USART_FIFOTRIG_RXLVL(handle->rxDataSize - 1));\r
937         }\r
938     }\r
939 }\r